diff --git a/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt b/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt index 7c30e61f2..eae3fb5e7 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt @@ -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 { - 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 diff --git a/compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVars.kt b/compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVars.kt index e04406b23..c7634161c 100644 --- a/compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVars.kt +++ b/compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVars.kt @@ -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 { + 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 + } } diff --git a/compilerAst/src/prog8/ast/AstToSourceTextConverter.kt b/compilerAst/src/prog8/ast/AstToSourceTextConverter.kt index db8be973a..0f3beaa52 100644 --- a/compilerAst/src/prog8/ast/AstToSourceTextConverter.kt +++ b/compilerAst/src/prog8/ast/AstToSourceTextConverter.kt @@ -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) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 205c09ba1..6814b5855 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -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==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 diff --git a/examples/test.p8 b/examples/test.p8 index 696eb3961..a5c73c7a2 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -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++ + } } }