fix multi-var decl in nested scopes

This commit is contained in:
Irmen de Jong 2023-12-09 12:07:09 +01:00
parent ae3b2ddf5f
commit e076b3aedc
5 changed files with 59 additions and 35 deletions

View File

@ -1,9 +1,12 @@
package prog8.compiler.astprocessing
import prog8.ast.*
import prog8.ast.IFunctionCall
import prog8.ast.Node
import prog8.ast.Program
import prog8.ast.base.FatalAstException
import prog8.ast.base.SyntaxError
import prog8.ast.expressions.*
import prog8.ast.findParentNode
import prog8.ast.statements.*
import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification
@ -113,11 +116,26 @@ class AstPreprocessor(val program: Program,
movements.add(IAstModification.InsertFirst(decl, parentscope))
replacements.add(IAstModification.Remove(decl, scope))
} else {
val declToInsert: VarDecl
if(decl.names.size>1) {
// we need to handle multi-decl here too, the desugarer maybe has not processed it here yet...
TODO("handle multi-decl movement")
if(decl.value!=null) {
decl.names.forEach { name ->
val target = AssignTarget(IdentifierReference(listOf(name), decl.position), null, null, decl.position)
val assign = Assignment(target.copy(), decl.value!!.copy(), AssignmentOrigin.VARINIT, decl.position)
replacements.add(IAstModification.InsertAfter(decl, assign, scope))
}
replacements.add(IAstModification.Remove(decl, scope))
decl.value = null
decl.allowInitializeWithZero = false
declToInsert = decl
} else {
// just move it to the defining scope
replacements.add(IAstModification.Remove(decl, scope))
declToInsert = decl
}
} else {
val declToInsert: VarDecl
// handle declaration of a single variable
if(decl.value!=null && decl.datatype in NumericDatatypes) {
val target = AssignTarget(IdentifierReference(listOf(decl.name), decl.position), null, null, decl.position)
val assign = Assignment(target, decl.value!!, AssignmentOrigin.VARINIT, decl.position)
@ -129,8 +147,8 @@ class AstPreprocessor(val program: Program,
replacements.add(IAstModification.Remove(decl, scope))
declToInsert = decl
}
movements.add(IAstModification.InsertFirst(declToInsert, parentscope))
}
movements.add(IAstModification.InsertFirst(declToInsert, parentscope))
}
}
return movements + replacements
@ -152,20 +170,6 @@ class AstPreprocessor(val program: Program,
}
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
if(decl.names.size>1) {
// note: the desugaring of a multi-variable vardecl has to be done here
// and not in CodeDesugarer, that one is too late (identifiers can't be found otherwise)
if(decl.datatype !in NumericDatatypes)
errors.err("can only multi declare numeric variables", decl.position)
return if(errors.noErrors()) {
// desugar into individual vardecl per name.
decl.desugarMultiDecl().map {
IAstModification.InsertAfter(decl, it, parent as IStatementContainer)
} + IAstModification.Remove(decl, parent as IStatementContainer)
} else
noModifications
}
val nextAssignment = decl.nextSibling() as? Assignment
if(nextAssignment!=null && nextAssignment.origin!=AssignmentOrigin.VARINIT) {
// check if it's a proper initializer assignment for the variable

View File

@ -1,6 +1,7 @@
package prog8.compiler.astprocessing
import prog8.ast.IFunctionCall
import prog8.ast.IStatementContainer
import prog8.ast.Node
import prog8.ast.Program
import prog8.ast.expressions.ArrayLiteral
@ -12,10 +13,7 @@ import prog8.ast.statements.VarDecl
import prog8.ast.statements.WhenChoice
import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification
import prog8.code.core.DataType
import prog8.code.core.ICompilationTarget
import prog8.code.core.IErrorReporter
import prog8.code.core.SplitWordArrayTypes
import prog8.code.core.*
internal class LiteralsToAutoVars(private val program: Program,
@ -73,4 +71,20 @@ internal class LiteralsToAutoVars(private val program: Program,
}
return noModifications
}
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
if(decl.names.size>1) {
// note: the desugaring of a multi-variable vardecl has to be done here
// and not in CodeDesugarer, that one is too late (identifiers can't be found otherwise)
if(decl.datatype !in NumericDatatypes)
errors.err("can only multi declare numeric variables", decl.position)
if(errors.noErrors()) {
// desugar into individual vardecl per name.
return decl.desugarMultiDecl().map {
IAstModification.InsertAfter(decl, it, parent as IStatementContainer)
} + IAstModification.Remove(decl, parent as IStatementContainer)
}
}
return noModifications
}
}

View File

@ -131,7 +131,10 @@ class AstToSourceTextConverter(val output: (text: String) -> Unit, val program:
output(" @zp")
if(decl.sharedWithAsm)
output(" @shared")
output(" ${decl.name} ")
if(decl.names.size>1)
output(decl.names.joinToString(prefix=" "))
else
output(" ${decl.name} ")
if(decl.value!=null) {
output("= ")
decl.value?.accept(this)

View File

@ -2,8 +2,6 @@
TODO
====
- fix multi-decl in for loops, see AstPreprocessor TODO("handle multi-decl movement")
- [on branch: shortcircuit] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 ....
...
@ -80,6 +78,7 @@ What if we were to re-introduce Structs in prog8? Some thoughts:
Other language/syntax features to think about
---------------------------------------------
- underscores in numeric literals for grouping
- chained comparisons `10<x<20` , `x==y==z` (desugars to `10<x and x<20`, `x==y and y==z`) BUT this changes the semantics of what it is right now ! (x==(y==z) 0> x==true)
- postincrdecr as expression, preincrdecr expression (`y = x++`, `y = ++x`) .... is this even possible, expression with side effects like this?
- negative array index to refer to an element from the end of the array. Python `[-1]` or Raku syntax `[\*-1]` , `[\*/2]` .... \*=size of the array

View File

@ -5,17 +5,21 @@ main {
const ubyte VAL = 11
sub start() {
uword w
ubyte @zp x,y,z = 99
txt.print_ub(x)
txt.spc()
txt.print_ub(y)
txt.spc()
txt.print_ub(z)
txt.spc()
txt.print_uw(w)
txt.nl()
if x==y==z
for w in 0 to 20 {
ubyte x,y,z=13
txt.print_ub(x)
txt.spc()
txt.print_ub(y)
txt.spc()
txt.print_ub(z)
txt.spc()
txt.print_uw(w)
txt.nl()
x++
y++
z++
}
}
}