diff --git a/codeCore/src/prog8/code/ast/AstStatements.kt b/codeCore/src/prog8/code/ast/AstStatements.kt index f7860e790..d8b6990f9 100644 --- a/codeCore/src/prog8/code/ast/AstStatements.kt +++ b/codeCore/src/prog8/code/ast/AstStatements.kt @@ -149,6 +149,18 @@ class PtVariable( position: Position ) : PtNamedNode(name, position), IPtVariable { init { + + if(value!=null) { + require(value is PtArray || value is PtString) { "variable initializer value must only be array or string" } + // NOTE: the 6502 code generator expects numerical variables to not have an initialization value, + // because that is done via assignment statements. There are no "inline" variables with a given value. + // All variables are put into zeropage or into the BSS section and initialized afterwards during program + // startup or at the start of the subroutine. + // The IR codegen however is different it has a special section for all variables + // that have a non-zero initialization value, regardless of the datatype. It removes the initialization + // assignment and puts the value back into the variable (but only in the symboltable). + } + value?.let {it.parent=this} } } diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt index e8047cd10..35bfa6f88 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt @@ -674,28 +674,34 @@ internal class ProgramAndVarsGen( } private fun staticVariable2asm(variable: StStaticVariable) { - val initialValue: Number = - if(variable.initializationNumericValue!=null) { - if(variable.dt.isFloat) - variable.initializationNumericValue!! - else - variable.initializationNumericValue!!.toInt() - } else 0 + if(!variable.dt.isArray && !variable.dt.isString) { + throw AssemblyError("static variables with an initialization value can only be an array or a string, not ${variable.dt} (${variable.name} ${variable.astNode?.position}") + // because numeric variables are in the BSS section and get initialized via assignment statements + } + +// val initialValue: Number = +// if(variable.initializationNumericValue!=null) { +// if(variable.dt.isFloat) +// variable.initializationNumericValue!! +// else +// variable.initializationNumericValue!!.toInt() +// } else 0 +// val dt=variable.dt when { - dt.isBool || dt.isUnsignedByte -> asmgen.out("${variable.name}\t.byte ${initialValue.toHex()}") - dt.isSignedByte -> asmgen.out("${variable.name}\t.char $initialValue") - dt.isUnsignedWord -> asmgen.out("${variable.name}\t.word ${initialValue.toHex()}") - dt.isSignedWord -> asmgen.out("${variable.name}\t.sint $initialValue") - dt.isFloat -> { - if(initialValue==0) { - asmgen.out("${variable.name}\t.byte 0,0,0,0,0 ; float") - } else { - val floatFill = compTarget.getFloatAsmBytes(initialValue) - asmgen.out("${variable.name}\t.byte $floatFill ; float $initialValue") - } - } +// dt.isBool || dt.isUnsignedByte -> asmgen.out("${variable.name}\t.byte ${initialValue.toHex()}") +// dt.isSignedByte -> asmgen.out("${variable.name}\t.char $initialValue") +// dt.isUnsignedWord -> asmgen.out("${variable.name}\t.word ${initialValue.toHex()}") +// dt.isSignedWord -> asmgen.out("${variable.name}\t.sint $initialValue") +// dt.isFloat -> { +// if(initialValue==0) { +// asmgen.out("${variable.name}\t.byte 0,0,0,0,0 ; float") +// } else { +// val floatFill = compTarget.getFloatAsmBytes(initialValue) +// asmgen.out("${variable.name}\t.byte $floatFill ; float $initialValue") +// } +// } dt.isString -> { throw AssemblyError("all string vars should have been interned into prog") } diff --git a/codeGenCpu6502/test/TestCodegen.kt b/codeGenCpu6502/test/TestCodegen.kt index e946236f8..240bf443b 100644 --- a/codeGenCpu6502/test/TestCodegen.kt +++ b/codeGenCpu6502/test/TestCodegen.kt @@ -54,7 +54,7 @@ class TestCodegen: FunSpec({ DataType.forDt(BaseDataType.UBYTE), ZeropageWish.DONTCARE, 0u, - PtNumber(BaseDataType.UBYTE, 0.0, Position.DUMMY), + null, null, Position.DUMMY )) @@ -81,7 +81,7 @@ class TestCodegen: FunSpec({ DataType.forDt(BaseDataType.WORD), ZeropageWish.DONTCARE, 0u, - PtNumber(BaseDataType.WORD, 1.0, Position.DUMMY), + null, null, Position.DUMMY )) diff --git a/codeGenIntermediate/test/TestVmCodeGen.kt b/codeGenIntermediate/test/TestVmCodeGen.kt index f6576d66f..5e5fdfb07 100644 --- a/codeGenIntermediate/test/TestVmCodeGen.kt +++ b/codeGenIntermediate/test/TestVmCodeGen.kt @@ -51,7 +51,7 @@ class TestVmCodeGen: FunSpec({ DataType.forDt(BaseDataType.UBYTE), ZeropageWish.DONTCARE, 0u, - PtNumber(BaseDataType.UBYTE, 0.0, Position.DUMMY), + null, null, Position.DUMMY )) @@ -78,7 +78,7 @@ class TestVmCodeGen: FunSpec({ DataType.forDt(BaseDataType.WORD), ZeropageWish.DONTCARE, 0u, - PtNumber(BaseDataType.WORD, 1.0, Position.DUMMY), + null, null, Position.DUMMY )) diff --git a/compiler/test/codegeneration/TestAsmGenSymbols.kt b/compiler/test/codegeneration/TestAsmGenSymbols.kt index d0b1937e6..015130156 100644 --- a/compiler/test/codegeneration/TestAsmGenSymbols.kt +++ b/compiler/test/codegeneration/TestAsmGenSymbols.kt @@ -19,6 +19,7 @@ import prog8.code.source.SourceCode import prog8.code.target.C64Target import prog8.code.target.VMTarget import prog8.codegen.cpu6502.AsmGen6502Internal +import prog8.compiler.astprocessing.AstChecker import prog8.compiler.astprocessing.SimplifiedAstMaker import prog8tests.helpers.* @@ -31,7 +32,7 @@ class TestAsmGenSymbols: StringSpec({ uword var_outside sub start () { - uword localvar = 1234 + uword localvar uword tgt locallabel: @@ -48,7 +49,7 @@ class TestAsmGenSymbols: StringSpec({ */ val varInSub = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UWORD), ZeropageWish.DONTCARE, - SplitWish.DONTCARE, null, "localvar", emptyList(), NumericLiteral.optimalInteger(1234, Position.DUMMY), false, 0u, false, Position.DUMMY) + SplitWish.DONTCARE, null, "localvar", emptyList(), null, false, 0u, false, Position.DUMMY) val var2InSub = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UWORD), ZeropageWish.DONTCARE, SplitWish.DONTCARE, null, "tgt", emptyList(), null, false, 0u, false, Position.DUMMY) val labelInSub = Label("locallabel", Position.DUMMY) @@ -79,6 +80,9 @@ class TestAsmGenSymbols: StringSpec({ fun createTestAsmGen6502(program: Program): AsmGen6502Internal { val errors = ErrorReporterForTests() val options = CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, false, true, C64Target(), 999u, 0xffffu) + val astchecker = AstChecker(program, errors, options) + astchecker.visit(program) + errors.report() val ptProgram = SimplifiedAstMaker(program, errors).transform() val st = SymbolTableMaker(ptProgram, options).make() return AsmGen6502Internal(ptProgram, st, options, errors, 0) diff --git a/examples/test.p8 b/examples/test.p8 index 89b860d8b..3dbd741cd 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -5,12 +5,15 @@ main { + + ubyte @nozp @shared staticvar=51 + sub start() { ubyte x = math.rnd() ubyte a,b = multi1() - ubyte c,d = 99 + ubyte c,d = multi2() - x++ + x=irmen txt.print_ub(a) txt.spc() txt.print_ub(b)