mirror of
https://github.com/irmen/prog8.git
synced 2025-02-18 20:30:43 +00:00
Initial variable values semantics changed: now always sets value at program (re)start (except strings/arrays).
This may change later by introducing a compiler option to choose a strategy, perhaps.
This commit is contained in:
parent
7232134931
commit
3a99115070
@ -19,8 +19,13 @@ class TypecastsAdder(val program: Program, val errors: ErrorReporter) : AstWalke
|
|||||||
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
|
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
|
||||||
|
|
||||||
// collect all variables that have an initialisation value
|
// collect all variables that have an initialisation value
|
||||||
if(decl.value!=null && decl.type== VarDeclType.VAR && decl.datatype in NumericDatatypes)
|
val declValue = decl.value
|
||||||
decl.definingBlock().initialValues += decl
|
if(declValue!=null
|
||||||
|
&& decl.type== VarDeclType.VAR
|
||||||
|
&& decl.datatype in NumericDatatypes
|
||||||
|
&& declValue.constValue(program)!=null) {
|
||||||
|
decl.definingBlock().initialValues[decl.scopedname] = decl
|
||||||
|
}
|
||||||
|
|
||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ class Block(override val name: String,
|
|||||||
val idx = statements.indexOf(node)
|
val idx = statements.indexOf(node)
|
||||||
statements[idx] = replacement
|
statements[idx] = replacement
|
||||||
}
|
}
|
||||||
val initialValues = mutableListOf<VarDecl>() // will be gathered by one of the Ast processing steps
|
val initialValues = mutableMapOf<String, VarDecl>() // will be gathered by one of the Ast processing steps
|
||||||
|
|
||||||
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
|
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
|
||||||
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
|
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
|
||||||
|
@ -175,10 +175,10 @@ internal class AsmGen(private val program: Program,
|
|||||||
// it will be called from program init.
|
// it will be called from program init.
|
||||||
if(block.initialValues.isNotEmpty()) {
|
if(block.initialValues.isNotEmpty()) {
|
||||||
out("prog8_init_vars\t.proc\n")
|
out("prog8_init_vars\t.proc\n")
|
||||||
block.initialValues.forEach {
|
block.initialValues.forEach { (scopedName, decl) ->
|
||||||
val target = AssignTarget(null, IdentifierReference(listOf(it.scopedname), it.position), null, null, it.position)
|
val target = AssignTarget(null, IdentifierReference(scopedName.split('.'), decl.position), null, null, decl.position)
|
||||||
val assign = Assignment(target, null, it.value!!, it.position)
|
val assign = Assignment(target, null, decl.value!!, decl.position)
|
||||||
assign.linkParents(it.parent)
|
assign.linkParents(decl.parent)
|
||||||
assignmentAsmGen.translate(assign)
|
assignmentAsmGen.translate(assign)
|
||||||
}
|
}
|
||||||
out(" rts\n .pend")
|
out(" rts\n .pend")
|
||||||
|
@ -198,6 +198,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
when(expr.operator) {
|
when(expr.operator) {
|
||||||
">>" -> {
|
">>" -> {
|
||||||
// bit-shifts are always by a constant number (for now)
|
// bit-shifts are always by a constant number (for now)
|
||||||
|
// TODO for everything except UBYTE, if shifting > 2 bits, use a subroutine
|
||||||
translateExpression(expr.left)
|
translateExpression(expr.left)
|
||||||
val amount = expr.right.constValue(program)!!.number.toInt()
|
val amount = expr.right.constValue(program)!!.number.toInt()
|
||||||
when (leftDt) {
|
when (leftDt) {
|
||||||
@ -211,6 +212,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
}
|
}
|
||||||
"<<" -> {
|
"<<" -> {
|
||||||
// bit-shifts are always by a constant number (for now)
|
// bit-shifts are always by a constant number (for now)
|
||||||
|
// TODO for the word types, if shifting > 3 bits, use a subroutine
|
||||||
translateExpression(expr.left)
|
translateExpression(expr.left)
|
||||||
val amount = expr.right.constValue(program)!!.number.toInt()
|
val amount = expr.right.constValue(program)!!.number.toInt()
|
||||||
if (leftDt in ByteDatatypes)
|
if (leftDt in ByteDatatypes)
|
||||||
|
@ -369,18 +369,7 @@ Initial values across multiple runs of the program
|
|||||||
When declaring values with an initial value, this value will be set into the variable each time
|
When declaring values with an initial value, this value will be set into the variable each time
|
||||||
the program reaches the declaration again. This can be in loops, multiple subroutine calls,
|
the program reaches the declaration again. This can be in loops, multiple subroutine calls,
|
||||||
or even multiple invocations of the entire program.
|
or even multiple invocations of the entire program.
|
||||||
|
If you omit the initial value, zero will be used instead.
|
||||||
.. sidebar::
|
|
||||||
Zeroing not for ZP
|
|
||||||
|
|
||||||
If a variable gets allocated in zero-page, it will *not* be set to zero for you at
|
|
||||||
the start of the program. Instead, it will simply be whatever the last value in that zero page
|
|
||||||
location was. Code should not depend on the uninitialized starting value of such variables.
|
|
||||||
|
|
||||||
If you omit an initial value, it will
|
|
||||||
be set to zero *but only for the first run of the program*. A second run will utilize the last value
|
|
||||||
where it left off (but your code will be a bit smaller because no initialization instructions
|
|
||||||
are generated)
|
|
||||||
|
|
||||||
This only works for simple types, *and not for string variables and arrays*.
|
This only works for simple types, *and not for string variables and arrays*.
|
||||||
It is assumed these are left unchanged by the program; they are not re-initialized on
|
It is assumed these are left unchanged by the program; they are not re-initialized on
|
||||||
|
@ -216,7 +216,8 @@ Variable declarations
|
|||||||
|
|
||||||
Variables should be declared with their exact type and size so the compiler can allocate storage
|
Variables should be declared with their exact type and size so the compiler can allocate storage
|
||||||
for them. You can give them an initial value as well. That value can be a simple literal value,
|
for them. You can give them an initial value as well. That value can be a simple literal value,
|
||||||
or an expression. You can add a ``@zp`` zeropage-tag, to tell the compiler to prioritize it
|
or an expression. If you don't provide an intial value yourself, zero will be used.
|
||||||
|
You can add a ``@zp`` zeropage-tag, to tell the compiler to prioritize it
|
||||||
when selecting variables to be put into zeropage.
|
when selecting variables to be put into zeropage.
|
||||||
The syntax is::
|
The syntax is::
|
||||||
|
|
||||||
@ -321,7 +322,7 @@ Constants
|
|||||||
^^^^^^^^^
|
^^^^^^^^^
|
||||||
|
|
||||||
All variables can be assigned new values unless you use the ``const`` keyword.
|
All variables can be assigned new values unless you use the ``const`` keyword.
|
||||||
The initial value will now be evaluated at compile time (it must be a compile time constant expression).
|
The initial value must be known at compile time (it must be a compile time constant expression).
|
||||||
This is only valid for the simple numeric types (byte, word, float)::
|
This is only valid for the simple numeric types (byte, word, float)::
|
||||||
|
|
||||||
const byte max_age = 99
|
const byte max_age = 99
|
||||||
|
@ -4,7 +4,9 @@ TODO
|
|||||||
|
|
||||||
- remove statements after an exit() or return
|
- remove statements after an exit() or return
|
||||||
- fix warnings about that unreachable code?
|
- fix warnings about that unreachable code?
|
||||||
- why are some programs for example cube3d increasing in size when compiling with optimizations???
|
|
||||||
|
- add a compiler option to not include variable initialization code (useful if the program is expected to run only once, such as a game)
|
||||||
|
the program will then rely solely on the values as they are in memory at the time of program startup.
|
||||||
|
|
||||||
- create real assembly routines for the bresenham line and circle code
|
- create real assembly routines for the bresenham line and circle code
|
||||||
- also add assembly routines in c64scr for drawing rectangles (filled/open)
|
- also add assembly routines in c64scr for drawing rectangles (filled/open)
|
||||||
|
@ -1,55 +1,68 @@
|
|||||||
%import c64utils
|
%import c64utils
|
||||||
;%import c64flt
|
;%import c64flt
|
||||||
;%option enable_floats
|
;%option enable_floats
|
||||||
%zeropage basicsafe
|
%zeropage dontuse
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
|
sub subje() {
|
||||||
|
ubyte xyz = 123
|
||||||
|
ubyte foo
|
||||||
|
c64scr.print_ub(xyz)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
c64scr.print_ub(foo)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
xyz++
|
||||||
|
foo++
|
||||||
|
}
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
ubyte xyz = 99 ; TODO fix compiler error when removing unused var
|
ubyte xyz = 99 ; TODO fix compiler error when removing unused var
|
||||||
word wcosa = cos8(xyz)
|
word wcosa = cos8(xyz)
|
||||||
word wcosa_sinb = wcosa / 128
|
word wcosa_sinb = wcosa / 128
|
||||||
; TODO fix too much assembly in prog8_init_vars
|
|
||||||
|
|
||||||
|
subje()
|
||||||
|
subje()
|
||||||
|
subje()
|
||||||
|
|
||||||
ubyte ub1
|
; ubyte ub1
|
||||||
ubyte ub2 = 99
|
; ubyte ub2 = 99
|
||||||
uword uw1
|
; uword uw1
|
||||||
uword uw2 = 9999
|
; uword uw2 = 9999
|
||||||
ubyte[5] array1
|
; ubyte[5] array1
|
||||||
ubyte[5] array2 = [22,33,44,55,66]
|
; ubyte[5] array2 = [22,33,44,55,66]
|
||||||
|
;
|
||||||
c64scr.print_ub(ub1)
|
; c64scr.print_ub(ub1)
|
||||||
c64.CHROUT(',')
|
; c64.CHROUT(',')
|
||||||
c64scr.print_ub(ub2)
|
; c64scr.print_ub(ub2)
|
||||||
c64.CHROUT(',')
|
; c64.CHROUT(',')
|
||||||
c64scr.print_uw(uw1)
|
; c64scr.print_uw(uw1)
|
||||||
c64.CHROUT(',')
|
; c64.CHROUT(',')
|
||||||
c64scr.print_uw(uw2)
|
; c64scr.print_uw(uw2)
|
||||||
c64.CHROUT(',')
|
; c64.CHROUT(',')
|
||||||
c64scr.print_ub(array1[0])
|
; c64scr.print_ub(array1[0])
|
||||||
c64.CHROUT(',')
|
; c64.CHROUT(',')
|
||||||
c64scr.print_ub(array2[0])
|
; c64scr.print_ub(array2[0])
|
||||||
c64.CHROUT('\n')
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
ub1++
|
; ub1++
|
||||||
ub2++
|
; ub2++
|
||||||
uw1++
|
; uw1++
|
||||||
uw2++
|
; uw2++
|
||||||
array1[0]++
|
; array1[0]++
|
||||||
array2[0]++
|
; array2[0]++
|
||||||
|
;
|
||||||
c64scr.print_ub(ub1)
|
; c64scr.print_ub(ub1)
|
||||||
c64.CHROUT(',')
|
; c64.CHROUT(',')
|
||||||
c64scr.print_ub(ub2)
|
; c64scr.print_ub(ub2)
|
||||||
c64.CHROUT(',')
|
; c64.CHROUT(',')
|
||||||
c64scr.print_uw(uw1)
|
; c64scr.print_uw(uw1)
|
||||||
c64.CHROUT(',')
|
; c64.CHROUT(',')
|
||||||
c64scr.print_uw(uw2)
|
; c64scr.print_uw(uw2)
|
||||||
c64.CHROUT(',')
|
; c64.CHROUT(',')
|
||||||
c64scr.print_ub(array1[0])
|
; c64scr.print_ub(array1[0])
|
||||||
c64.CHROUT(',')
|
; c64.CHROUT(',')
|
||||||
c64scr.print_ub(array2[0])
|
; c64scr.print_ub(array2[0])
|
||||||
c64.CHROUT('\n')
|
; c64.CHROUT('\n')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user