From 7232134931258577fe37c434820eaa3b08a4d66c Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 22 Mar 2020 13:47:13 +0100 Subject: [PATCH] fix some compiler errors --- .../ast/processing/StatementReorderer.kt | 42 +++++++++++++++++++ .../prog8/ast/processing/TypecastsAdder.kt | 7 +--- .../compiler/target/c64/codegen/AsmGen.kt | 26 +++++++----- examples/test.p8 | 6 +++ 4 files changed, 65 insertions(+), 16 deletions(-) diff --git a/compiler/src/prog8/ast/processing/StatementReorderer.kt b/compiler/src/prog8/ast/processing/StatementReorderer.kt index a04e4dd02..1abd46677 100644 --- a/compiler/src/prog8/ast/processing/StatementReorderer.kt +++ b/compiler/src/prog8/ast/processing/StatementReorderer.kt @@ -3,6 +3,8 @@ package prog8.ast.processing import prog8.ast.* import prog8.ast.base.DataType import prog8.ast.base.FatalAstException +import prog8.ast.base.NumericDatatypes +import prog8.ast.base.VarDeclType import prog8.ast.expressions.* import prog8.ast.statements.* @@ -19,13 +21,16 @@ internal class StatementReorderer(private val program: Program): IAstModifyingVi // - the 'start' subroutine in the 'main' block will be moved to the top immediately following the directives. // - all other subroutines will be moved to the end of their block. // - sorts the choices in when statement. + // - a vardecl with a non-const initializer value is split into a regular vardecl and an assignment statement. private val directivesToMove = setOf("%output", "%launcher", "%zeropage", "%zpreserved", "%address", "%option") private val addReturns = mutableListOf>() + private val addVardecls = mutableMapOf>() override fun visit(module: Module) { addReturns.clear() + addVardecls.clear() super.visit(module) val (blocks, other) = module.statements.partition { it is Block } @@ -54,11 +59,17 @@ internal class StatementReorderer(private val program: Program): IAstModifyingVi module.statements.removeAll(directives) module.statements.addAll(0, directives) + // add new statements for(pos in addReturns) { val returnStmt = Return(null, pos.first.position) returnStmt.linkParents(pos.first as Node) pos.first.statements.add(pos.second, returnStmt) } + + for((where, decls) in addVardecls) { + where.statements.addAll(0, decls) + decls.forEach { it.linkParents(where as Node) } + } } override fun visit(block: Block): Statement { @@ -148,6 +159,37 @@ internal class StatementReorderer(private val program: Program): IAstModifyingVi return subroutine } + + private fun addVarDecl(scope: INameScope, variable: VarDecl): VarDecl { + if(scope !in addVardecls) + addVardecls[scope] = mutableListOf() + val declList = addVardecls.getValue(scope) + val existing = declList.singleOrNull { it.name==variable.name } + return if(existing!=null) { + existing + } else { + declList.add(variable) + variable + } + } + + override fun visit(decl: VarDecl): Statement { + val declValue = decl.value + if(declValue!=null && decl.type== VarDeclType.VAR && decl.datatype in NumericDatatypes) { + val declConstValue = declValue.constValue(program) + if(declConstValue==null) { + // move the vardecl (without value) to the scope and replace this with a regular assignment + val target = AssignTarget(null, IdentifierReference(listOf(decl.name), decl.position), null, null, decl.position) + val assign = Assignment(target, null, declValue, decl.position) + assign.linkParents(decl.parent) + decl.value = null + addVarDecl(decl.definingScope(), decl) + return assign + } + } + return super.visit(decl) + } + override fun visit(assignment: Assignment): Statement { val assg = super.visit(assignment) if(assg !is Assignment) diff --git a/compiler/src/prog8/ast/processing/TypecastsAdder.kt b/compiler/src/prog8/ast/processing/TypecastsAdder.kt index 0432d90df..6b7b1122d 100644 --- a/compiler/src/prog8/ast/processing/TypecastsAdder.kt +++ b/compiler/src/prog8/ast/processing/TypecastsAdder.kt @@ -4,10 +4,7 @@ import prog8.ast.IFunctionCall import prog8.ast.INameScope import prog8.ast.Node import prog8.ast.Program -import prog8.ast.base.DataType -import prog8.ast.base.ErrorReporter -import prog8.ast.base.FatalAstException -import prog8.ast.base.VarDeclType +import prog8.ast.base.* import prog8.ast.expressions.* import prog8.ast.statements.* import prog8.functions.BuiltinFunctions @@ -22,7 +19,7 @@ class TypecastsAdder(val program: Program, val errors: ErrorReporter) : AstWalke override fun after(decl: VarDecl, parent: Node): Iterable { // collect all variables that have an initialisation value - if(decl.value!=null && decl.type== VarDeclType.VAR && !decl.isArray) + if(decl.value!=null && decl.type== VarDeclType.VAR && decl.datatype in NumericDatatypes) decl.definingBlock().initialValues += decl return emptyList() diff --git a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt index b201b00ec..49e4fd43e 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt @@ -400,17 +400,22 @@ internal class AsmGen(private val program: Program, } private fun makeArrayFillDataSigned(decl: VarDecl): List { - val array = (decl.value as ArrayLiteralValue).value - - return when { - decl.datatype == DataType.ARRAY_UB -> + val array = + if(decl.value!=null) + (decl.value as ArrayLiteralValue).value + else { + // no array init value specified, use a list of zeros + val zero = decl.asDefaultValueDecl(decl.parent).value!! + Array(decl.arraysize!!.size()!!) { zero } + } + return when (decl.datatype) { + DataType.ARRAY_UB -> // byte array can never contain pointer-to types, so treat values as all integers array.map { val number = (it as NumericLiteralValue).number.toInt() - val hexnum = number.toString(16).padStart(2, '0') - "$$hexnum" + "$"+number.toString(16).padStart(2, '0') } - decl.datatype == DataType.ARRAY_B -> + DataType.ARRAY_B -> // byte array can never contain pointer-to types, so treat values as all integers array.map { val number = (it as NumericLiteralValue).number.toInt() @@ -420,12 +425,11 @@ internal class AsmGen(private val program: Program, else "-$$hexnum" } - decl.datatype== DataType.ARRAY_UW -> array.map { + DataType.ARRAY_UW -> array.map { val number = (it as NumericLiteralValue).number.toInt() - val hexnum = number.toString(16).padStart(4, '0') - "$$hexnum" + "$" + number.toString(16).padStart(4, '0') } - decl.datatype== DataType.ARRAY_W -> array.map { + DataType.ARRAY_W -> array.map { val number = (it as NumericLiteralValue).number.toInt() val hexnum = number.absoluteValue.toString(16).padStart(4, '0') if(number>=0) diff --git a/examples/test.p8 b/examples/test.p8 index 09754ff88..0d3a71279 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -6,6 +6,12 @@ main { sub start() { + ubyte xyz = 99 ; TODO fix compiler error when removing unused var + word wcosa = cos8(xyz) + word wcosa_sinb = wcosa / 128 + ; TODO fix too much assembly in prog8_init_vars + + ubyte ub1 ubyte ub2 = 99 uword uw1