diff --git a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt index 27dd25c4c..d6386d95e 100644 --- a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt +++ b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt @@ -781,12 +781,12 @@ class AsmGen(private val program: Program, is BranchStatement -> translate(stmt) is IfStatement -> translate(stmt) is ForLoop -> forloopsAsmGen.translate(stmt) - is WhileLoop -> translate(stmt) is RepeatLoop -> translate(stmt) - is UntilLoop -> translate(stmt) is WhenStatement -> translate(stmt) is AnonymousScope -> translate(stmt) is BuiltinFunctionStatementPlaceholder -> throw AssemblyError("builtin function should not have placeholder anymore") + is UntilLoop -> throw AssemblyError("do..until should have been desugared to jumps") + is WhileLoop -> throw AssemblyError("while should have been desugared to jumps") is Block -> throw AssemblyError("block should have been handled elsewhere") is Break -> throw AssemblyError("break should have been replaced by goto") else -> throw AssemblyError("missing asm translation for $stmt") @@ -1268,35 +1268,6 @@ $repeatLabel lda $counterVar return counterVar } - private fun translate(stmt: WhileLoop) { - requireComparisonExpression(stmt.condition) // WhileLoop: condition must be of form 'x ' - val booleanCondition = stmt.condition as BinaryExpression - - val whileLabel = makeLabel("while") - val endLabel = makeLabel("whileend") - loopEndLabels.push(endLabel) - out(whileLabel) - translateComparisonExpressionWithJumpIfFalse(booleanCondition, endLabel) - translate(stmt.body) - jmp(whileLabel) - out(endLabel) - loopEndLabels.pop() - } - - private fun translate(stmt: UntilLoop) { - requireComparisonExpression(stmt.condition) // UntilLoop: condition must be of form 'x ' - val booleanCondition = stmt.condition as BinaryExpression - - val repeatLabel = makeLabel("repeat") - val endLabel = makeLabel("repeatend") - loopEndLabels.push(endLabel) - out(repeatLabel) - translate(stmt.body) - translateComparisonExpressionWithJumpIfFalse(booleanCondition, repeatLabel) - out(endLabel) - loopEndLabels.pop() - } - private fun translate(stmt: WhenStatement) { val endLabel = makeLabel("choice_end") val choiceBlocks = mutableListOf>() diff --git a/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt b/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt index cf132c36c..59e0a4a13 100644 --- a/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt +++ b/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt @@ -35,6 +35,14 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, private val o throw FatalAstException("break should have been replaced by goto $breakStmt") } + override fun before(whileLoop: WhileLoop, parent: Node): Iterable { + throw FatalAstException("while should have been desugared to jumps") + } + + override fun before(untilLoop: UntilLoop, parent: Node): Iterable { + throw FatalAstException("do..until should have been desugared to jumps") + } + override fun before(block: Block, parent: Node): Iterable { // move all subroutines to the bottom of the block val subs = block.statements.filterIsInstance() @@ -185,7 +193,6 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, private val o return noModifications } - @Suppress("DuplicatedCode") override fun after(ifStatement: IfStatement, parent: Node): Iterable { val prefixExpr = ifStatement.condition as? PrefixExpression if(prefixExpr!=null && prefixExpr.operator=="not") { @@ -282,74 +289,6 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, private val o ) } - @Suppress("DuplicatedCode") - override fun after(untilLoop: UntilLoop, parent: Node): Iterable { - val prefixExpr = untilLoop.condition as? PrefixExpression - if(prefixExpr!=null && prefixExpr.operator=="not") { - // until not x -> until x==0 - val booleanExpr = BinaryExpression(prefixExpr.expression, "==", NumericLiteralValue.optimalInteger(0, untilLoop.condition.position), untilLoop.condition.position) - return listOf(IAstModification.ReplaceNode(untilLoop.condition, booleanExpr, untilLoop)) - } - - val binExpr = untilLoop.condition as? BinaryExpression - if(binExpr==null || binExpr.operator !in ComparisonOperators) { - // until x -> until x!=0, until x+5 -> until x+5 != 0 - val booleanExpr = BinaryExpression(untilLoop.condition, "!=", NumericLiteralValue.optimalInteger(0, untilLoop.condition.position), untilLoop.condition.position) - return listOf(IAstModification.ReplaceNode(untilLoop.condition, booleanExpr, untilLoop)) - } - - if((binExpr.left as? NumericLiteralValue)?.number==0.0 && - (binExpr.right as? NumericLiteralValue)?.number!=0.0) - throw FatalAstException("0==X should have been swapped to if X==0") - - // simplify the conditional expression, introduce simple assignments if required. - // NOTE: sometimes this increases code size because additional stores/loads are generated for the - // intermediate variables. We assume these are optimized away from the resulting assembly code later. - val simplify = simplifyConditionalExpression(binExpr) - val modifications = mutableListOf() - if(simplify.rightVarAssignment!=null) { - modifications += IAstModification.ReplaceNode(binExpr.right, simplify.rightOperandReplacement!!, binExpr) - modifications += IAstModification.InsertLast(simplify.rightVarAssignment, untilLoop.body) - } - if(simplify.leftVarAssignment!=null) { - modifications += IAstModification.ReplaceNode(binExpr.left, simplify.leftOperandReplacement!!, binExpr) - modifications += IAstModification.InsertLast(simplify.leftVarAssignment, untilLoop.body) - } - - return modifications - } - - @Suppress("DuplicatedCode") - override fun after(whileLoop: WhileLoop, parent: Node): Iterable { - val prefixExpr = whileLoop.condition as? PrefixExpression - if(prefixExpr!=null && prefixExpr.operator=="not") { - // while not x -> while x==0 - val booleanExpr = BinaryExpression(prefixExpr.expression, "==", NumericLiteralValue.optimalInteger(0, whileLoop.condition.position), whileLoop.condition.position) - return listOf(IAstModification.ReplaceNode(whileLoop.condition, booleanExpr, whileLoop)) - } - - val binExpr = whileLoop.condition as? BinaryExpression - if(binExpr==null || binExpr.operator !in ComparisonOperators) { - // while x -> while x!=0, while x+5 -> while x+5 != 0 - val booleanExpr = BinaryExpression(whileLoop.condition, "!=", NumericLiteralValue.optimalInteger(0, whileLoop.condition.position), whileLoop.condition.position) - return listOf(IAstModification.ReplaceNode(whileLoop.condition, booleanExpr, whileLoop)) - } - - if((binExpr.left as? NumericLiteralValue)?.number==0.0 && - (binExpr.right as? NumericLiteralValue)?.number!=0.0) - throw FatalAstException("0==X should have been swapped to if X==0") - - // TODO simplify the conditional expression, introduce simple assignments if required. - // make sure to evaluate it only once, but also right at entry of the while loop - // NOTE: sometimes this increases code size because additional stores/loads are generated for the - // intermediate variables. We assume these are optimized away from the resulting assembly code later. - // NOTE: this is nasty for a while-statement as the condition occurs at the top of the loop - // so the expression needs to be evaluated also before the loop is entered... - // but I don't want to duplicate the expression. - // val simplify = simplifyConditionalExpression(binExpr) - return noModifications - } - override fun after(functionCallStatement: FunctionCallStatement, parent: Node): Iterable { if(functionCallStatement.target.nameInSource==listOf("cmp")) { // if the datatype of the arguments of cmp() are different, cast the byte one to word. diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index 3df6c6324..fbecabc74 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -305,13 +305,13 @@ private fun postprocessAst(program: Program, errors: IErrorReporter, compilerOpt program.addTypecasts(errors, compilerOptions) errors.report() program.variousCleanups(program, errors) - program.checkValid(errors, compilerOptions) // check if final tree is still valid - errors.report() val callGraph = CallGraph(program) callGraph.checkRecursiveCalls(errors) errors.report() program.verifyFunctionArgTypes() program.moveMainAndStartToFirst() + program.checkValid(errors, compilerOptions) // check if final tree is still valid + errors.report() } private sealed class WriteAssemblyResult { diff --git a/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt b/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt index e1028c5e6..0f2414962 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt @@ -16,6 +16,8 @@ import prog8.compilerinterface.IStringEncoding internal fun Program.checkValid(errors: IErrorReporter, compilerOptions: CompilationOptions) { + val parentChecker = ParentNodeChecker() + parentChecker.visit(this) val checker = AstChecker(this, errors, compilerOptions) checker.visit(this) } diff --git a/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt b/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt index 032b04c42..2b9bd0cbe 100644 --- a/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt +++ b/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt @@ -1,10 +1,13 @@ package prog8.compiler.astprocessing +import com.github.michaelbull.result.toResultOr import prog8.ast.IStatementContainer import prog8.ast.Node import prog8.ast.Program import prog8.ast.base.ParentSentinel +import prog8.ast.base.Position import prog8.ast.expressions.IdentifierReference +import prog8.ast.expressions.PrefixExpression import prog8.ast.statements.* import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstModification @@ -25,18 +28,22 @@ internal class CodeDesugarer(val program: Program, private val errors: IErrorRep private var generatedLabelSequenceNumber: Int = 0 private val generatedLabelPrefix = "prog8_label_" - private fun makeLabel(postfix: String): String { + private fun makeLabel(postfix: String, position: Position): Label { generatedLabelSequenceNumber++ - return "${generatedLabelPrefix}${generatedLabelSequenceNumber}_$postfix" + return Label("${generatedLabelPrefix}${generatedLabelSequenceNumber}_$postfix", position) + } + + private fun jumpLabel(label: Label): Jump { + val ident = IdentifierReference(listOf(label.name), label.position) + return Jump(null, ident, null, label.position) } override fun before(breakStmt: Break, parent: Node): Iterable { fun jumpAfter(stmt: Statement): Iterable { - val labelName = makeLabel("after") - val ident = IdentifierReference(listOf(labelName), breakStmt.position) + val label = makeLabel("after", breakStmt.position) return listOf( - IAstModification.ReplaceNode(breakStmt, Jump(null, ident, null, breakStmt.position), parent), - IAstModification.InsertAfter(stmt, Label(labelName, breakStmt.position), stmt.parent as IStatementContainer) + IAstModification.ReplaceNode(breakStmt, jumpLabel(label), parent), + IAstModification.InsertAfter(stmt, label, stmt.parent as IStatementContainer) ) } @@ -56,4 +63,52 @@ internal class CodeDesugarer(val program: Program, private val errors: IErrorRep } } + override fun after(untilLoop: UntilLoop, parent: Node): Iterable { + /* +do { STUFF } until CONDITION + ===> +_loop: + STUFF +if not CONDITION + goto _loop + */ + val pos = untilLoop.position + val loopLabel = makeLabel("untilloop", pos) + val notCondition = PrefixExpression("not", untilLoop.condition, pos) + val replacement = AnonymousScope(mutableListOf( + loopLabel, + untilLoop.body, + IfStatement(notCondition, + AnonymousScope(mutableListOf(jumpLabel(loopLabel)), pos), + AnonymousScope(mutableListOf(), pos), + pos) + ), pos) + return listOf(IAstModification.ReplaceNode(untilLoop, replacement, parent)) + } + + override fun after(whileLoop: WhileLoop, parent: Node): Iterable { + /* +while CONDITION { STUFF } + ==> + goto _whilecond +_whileloop: + STUFF +_whilecond: + if CONDITION goto _whileloop + */ + val pos = whileLoop.position + val condLabel = makeLabel("whilecond", pos) + val loopLabel = makeLabel("whileloop", pos) + val replacement = AnonymousScope(mutableListOf( + jumpLabel(condLabel), + loopLabel, + whileLoop.body, + condLabel, + IfStatement(whileLoop.condition, + AnonymousScope(mutableListOf(jumpLabel(loopLabel)), pos), + AnonymousScope(mutableListOf(), pos), + pos) + ), pos) + return listOf(IAstModification.ReplaceNode(whileLoop, replacement, parent)) + } } diff --git a/compiler/src/prog8/compiler/astprocessing/ParentNodeChecker.kt b/compiler/src/prog8/compiler/astprocessing/ParentNodeChecker.kt new file mode 100644 index 000000000..7b51276b6 --- /dev/null +++ b/compiler/src/prog8/compiler/astprocessing/ParentNodeChecker.kt @@ -0,0 +1,241 @@ +package prog8.compiler.astprocessing + +import prog8.ast.Module +import prog8.ast.Node +import prog8.ast.base.FatalAstException +import prog8.ast.expressions.* +import prog8.ast.statements.* +import prog8.ast.walk.AstWalker +import prog8.ast.walk.IAstModification + + +internal class ParentNodeChecker: AstWalker() { + + override fun before(addressOf: AddressOf, parent: Node): Iterable { + if(addressOf.parent!==parent) + throw FatalAstException("parent node mismatch at $addressOf") + return noModifications + } + + override fun before(array: ArrayLiteralValue, parent: Node): Iterable { + if(array.parent!==parent) + throw FatalAstException("parent node mismatch at $array") + return noModifications + } + + override fun before(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable { + if(arrayIndexedExpression.parent!==parent) + throw FatalAstException("parent node mismatch at $arrayIndexedExpression") + return noModifications + } + + override fun before(assignTarget: AssignTarget, parent: Node): Iterable { + if(assignTarget.parent!==parent) + throw FatalAstException("parent node mismatch at $assignTarget") + return noModifications + } + + override fun before(assignment: Assignment, parent: Node): Iterable { + if(assignment.parent!==parent) + throw FatalAstException("parent node mismatch at $assignment") + return noModifications + } + + override fun before(block: Block, parent: Node): Iterable { + if(block.parent!==parent) + throw FatalAstException("parent node mismatch at $block") + return noModifications + } + + override fun before(branchStatement: BranchStatement, parent: Node): Iterable { + if(branchStatement.parent!==parent) + throw FatalAstException("parent node mismatch at $branchStatement") + return noModifications + } + + override fun before(breakStmt: Break, parent: Node): Iterable { + if(breakStmt.parent!==parent) + throw FatalAstException("parent node mismatch at $breakStmt") + return noModifications + } + + override fun before(decl: VarDecl, parent: Node): Iterable { + if(decl.parent!==parent) + throw FatalAstException("parent node mismatch at $decl") + return noModifications + } + + override fun before(directive: Directive, parent: Node): Iterable { + if(directive.parent!==parent) + throw FatalAstException("parent node mismatch at $directive") + return noModifications + } + + override fun before(expr: BinaryExpression, parent: Node): Iterable { + if(expr.parent!==parent) + throw FatalAstException("parent node mismatch at $expr") + return noModifications + } + + override fun before(expr: PrefixExpression, parent: Node): Iterable { + if(expr.parent!==parent) + throw FatalAstException("parent node mismatch at $expr") + return noModifications + } + + override fun before(forLoop: ForLoop, parent: Node): Iterable { + if(forLoop.parent!==parent) + throw FatalAstException("parent node mismatch at $forLoop") + return noModifications + } + + override fun before(repeatLoop: RepeatLoop, parent: Node): Iterable { + if(repeatLoop.parent!==parent) + throw FatalAstException("parent node mismatch at $repeatLoop") + return noModifications + } + + override fun before(identifier: IdentifierReference, parent: Node): Iterable { + if(identifier.parent!==parent) + throw FatalAstException("parent node mismatch at $identifier") + return noModifications + } + + override fun before(ifStatement: IfStatement, parent: Node): Iterable { + if(ifStatement.parent!==parent) + throw FatalAstException("parent node mismatch at $ifStatement") + return noModifications + } + + override fun before(inlineAssembly: InlineAssembly, parent: Node): Iterable { + if(inlineAssembly.parent!==parent) + throw FatalAstException("parent node mismatch at $inlineAssembly") + return noModifications + } + + override fun before(jump: Jump, parent: Node): Iterable { + if(jump.parent!==parent) + throw FatalAstException("parent node mismatch at $jump") + return noModifications + } + + override fun before(label: Label, parent: Node): Iterable { + if(label.parent!==parent) + throw FatalAstException("parent node mismatch at $label") + return noModifications + } + + override fun before(memread: DirectMemoryRead, parent: Node): Iterable { + if(memread.parent!==parent) + throw FatalAstException("parent node mismatch at $memread") + return noModifications + } + + override fun before(memwrite: DirectMemoryWrite, parent: Node): Iterable { + if(memwrite.parent!==parent) + throw FatalAstException("parent node mismatch at $memwrite") + return noModifications + } + + override fun before(module: Module, parent: Node): Iterable { + if(module.parent!==parent) + throw FatalAstException("parent node mismatch at $module") + return noModifications + } + + override fun before(numLiteral: NumericLiteralValue, parent: Node): Iterable { + if(numLiteral.parent!==parent) + throw FatalAstException("parent node mismatch at $numLiteral") + return noModifications + } + + override fun before(postIncrDecr: PostIncrDecr, parent: Node): Iterable { + if(postIncrDecr.parent!==parent) + throw FatalAstException("parent node mismatch at $postIncrDecr") + return noModifications + } + + override fun before(range: RangeExpr, parent: Node): Iterable { + if(range.parent!==parent) + throw FatalAstException("parent node mismatch at $range") + return noModifications + } + + override fun before(untilLoop: UntilLoop, parent: Node): Iterable { + if(untilLoop.parent!==parent) + throw FatalAstException("parent node mismatch at $untilLoop") + return noModifications + } + + override fun before(returnStmt: Return, parent: Node): Iterable { + if(returnStmt.parent!==parent) + throw FatalAstException("parent node mismatch at $returnStmt") + return noModifications + } + + override fun before(char: CharLiteral, parent: Node): Iterable { + if(char.parent!==parent) + throw FatalAstException("parent node mismatch at $char") + return noModifications + } + + override fun before(string: StringLiteralValue, parent: Node): Iterable { + if(string.parent!==parent) + throw FatalAstException("parent node mismatch at $string") + return noModifications + } + + override fun before(subroutine: Subroutine, parent: Node): Iterable { + if(subroutine.parent!==parent) + throw FatalAstException("parent node mismatch at $subroutine") + return noModifications + } + + override fun before(typecast: TypecastExpression, parent: Node): Iterable { + if(typecast.parent!==parent) + throw FatalAstException("parent node mismatch at $typecast") + return noModifications + } + + override fun before(whenChoice: WhenChoice, parent: Node): Iterable { + if(whenChoice.parent!==parent) + throw FatalAstException("parent node mismatch at $whenChoice") + return noModifications + } + + override fun before(whenStatement: WhenStatement, parent: Node): Iterable { + if(whenStatement.parent!==parent) + throw FatalAstException("parent node mismatch at $whenStatement") + return noModifications + } + + override fun before(whileLoop: WhileLoop, parent: Node): Iterable { + if(whileLoop.parent!==parent) + throw FatalAstException("parent node mismatch at $whileLoop") + return noModifications + } + + override fun before(functionCall: FunctionCall, parent: Node): Iterable { + if(functionCall.parent!==parent) + throw FatalAstException("parent node mismatch at $functionCall") + return noModifications + } + + override fun before(functionCallStatement: FunctionCallStatement, parent: Node): Iterable { + if(functionCallStatement.parent!==parent) + throw FatalAstException("parent node mismatch at $functionCallStatement") + return noModifications + } + + override fun before(nopStatement: NopStatement, parent: Node): Iterable { + if(nopStatement.parent!==parent) + throw FatalAstException("parent node mismatch at $nopStatement") + return noModifications + } + + override fun before(scope: AnonymousScope, parent: Node): Iterable { + if(scope.parent!==parent) + throw FatalAstException("parent node mismatch at $scope") + return noModifications + } +} diff --git a/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt b/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt index 9a87b52c2..fe562f47e 100644 --- a/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt +++ b/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt @@ -19,14 +19,14 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter) return listOf(IAstModification.Remove(nopStatement, parent as IStatementContainer)) } - override fun before(scope: AnonymousScope, parent: Node): Iterable { + override fun after(scope: AnonymousScope, parent: Node): Iterable { return if(parent is IStatementContainer) listOf(ScopeFlatten(scope, parent as IStatementContainer)) else noModifications } - class ScopeFlatten(val scope: AnonymousScope, val into: IStatementContainer) : IAstModification { + private class ScopeFlatten(val scope: AnonymousScope, val into: IStatementContainer) : IAstModification { override fun perform() { val idx = into.statements.indexOf(scope) if(idx>=0) { @@ -37,15 +37,16 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter) } } - override fun before(functionCallStatement: FunctionCallStatement, parent: Node): Iterable { - return before(functionCallStatement as IFunctionCall, parent, functionCallStatement.position) - } + override fun before(functionCallStatement: FunctionCallStatement, parent: Node) = + before(functionCallStatement as IFunctionCall, parent, functionCallStatement.position) - override fun before(functionCall: FunctionCall, parent: Node): Iterable { - return before(functionCall as IFunctionCall, parent, functionCall.position) - } + override fun before(functionCall: FunctionCall, parent: Node) = + before(functionCall as IFunctionCall, parent, functionCall.position) private fun before(functionCall: IFunctionCall, parent: Node, position: Position): Iterable { + + // TODO move to CodeDesugarer + if(functionCall.target.nameInSource==listOf("peek")) { // peek(a) is synonymous with @(a) val memread = DirectMemoryRead(functionCall.args.single(), position) @@ -61,9 +62,6 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter) } override fun after(typecast: TypecastExpression, parent: Node): Iterable { - if(typecast.parent!==parent) - throw FatalAstException("parent node mismatch at $typecast") - if(typecast.expression is NumericLiteralValue) { val value = (typecast.expression as NumericLiteralValue).cast(typecast.type) if(value.isValid) @@ -85,16 +83,7 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter) return noModifications } - override fun after(subroutine: Subroutine, parent: Node): Iterable { - if(subroutine.parent!==parent) - throw FatalAstException("parent node mismatch at $subroutine") - return noModifications - } - override fun after(assignment: Assignment, parent: Node): Iterable { - if(assignment.parent!==parent) - throw FatalAstException("parent node mismatch at $assignment") - val nextAssign = assignment.nextSibling() as? Assignment if(nextAssign!=null && nextAssign.target.isSameAs(assignment.target, program)) { if(nextAssign.value isSameAs assignment.value) @@ -103,34 +92,4 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter) return noModifications } - - override fun after(assignTarget: AssignTarget, parent: Node): Iterable { - if(assignTarget.parent!==parent) - throw FatalAstException("parent node mismatch at $assignTarget") - return noModifications - } - - override fun after(decl: VarDecl, parent: Node): Iterable { - if(decl.parent!==parent) - throw FatalAstException("parent node mismatch at $decl") - return noModifications - } - - override fun after(scope: AnonymousScope, parent: Node): Iterable { - if(scope.parent!==parent) - throw FatalAstException("parent node mismatch at $scope") - return noModifications - } - - override fun after(returnStmt: Return, parent: Node): Iterable { - if(returnStmt.parent!==parent) - throw FatalAstException("parent node mismatch at $returnStmt") - return noModifications - } - - override fun after(identifier: IdentifierReference, parent: Node): Iterable { - if(identifier.parent!==parent) - throw FatalAstException("parent node mismatch at $identifier") - return noModifications - } } diff --git a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt index bd011c680..0dddacf89 100644 --- a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt +++ b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt @@ -476,7 +476,12 @@ class NumericLiteralValue(val type: DataType, // only numerical types allowed } override fun referencesIdentifier(nameInSource: List) = false - override fun constValue(program: Program) = this + override fun constValue(program: Program): NumericLiteralValue { + return copy().also { + if(::parent.isInitialized) + it.parent = parent + } + } override fun accept(visitor: IAstVisitor) = visitor.visit(this) override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 72167e591..cf9074baa 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,7 @@ TODO For next compiler release (7.6) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... +optimize ifs containing only a jump: reuse old code from AsmGen translateComparisonExpressionWithJumpIfFalse? Blocked by an official Commander-x16 v39 release @@ -37,10 +37,6 @@ Future More code optimization ideas ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- remove special code generation for while and util expression - by rewriting while and until expressions into if+jump (just consider them syntactic sugar) - but the result should not produce larger code ofcourse! -- while-expression should now also get the simplifyConditionalExpression() treatment - byte typed expressions should be evaluated in the accumulator where possible, without (temp)var for instance value = otherbyte >> 1 --> lda otherbite ; lsr a; sta value - rewrite multiple choice if into when: diff --git a/examples/test.p8 b/examples/test.p8 index d06525874..e7671cc34 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -11,6 +11,9 @@ main { ubyte @shared zz = other[3] } sub start() { + + txt.print("should print: 10 40 80 20\n") + ubyte @shared xx repeat { xx++