Skip to content

Commit

Permalink
fix multi-var decl in nested scopes
Browse files Browse the repository at this point in the history
  • Loading branch information
irmen committed Dec 9, 2023
1 parent ae3b2dd commit e076b3a
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 35 deletions.
40 changes: 22 additions & 18 deletions compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand All @@ -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
Expand Down
22 changes: 18 additions & 4 deletions compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVars.kt
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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,
Expand Down Expand Up @@ -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
}
}
5 changes: 4 additions & 1 deletion compilerAst/src/prog8/ast/AstToSourceTextConverter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 1 addition & 2 deletions docs/source/todo.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 ....

...
Expand Down Expand Up @@ -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
24 changes: 14 additions & 10 deletions examples/test.p8
Original file line number Diff line number Diff line change
Expand Up @@ -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++
}
}
}

0 comments on commit e076b3a

Please sign in to comment.