From 0247fb0d84b9df975d50127fd8a2b5f14320e419 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Mon, 21 Oct 2024 00:20:54 +0200 Subject: [PATCH] some ast2 var tweaks --- codeCore/src/prog8/code/SymbolTableMaker.kt | 7 +++++-- codeCore/src/prog8/code/ast/AstExpressions.kt | 7 +++++++ codeCore/src/prog8/code/ast/Verify.kt | 16 ++++++++++++++++ codeCore/src/prog8/code/optimize/Optimizer.kt | 2 +- compiler/src/prog8/compiler/Compiler.kt | 4 ++++ compiler/test/ast/TestIntermediateAst.kt | 10 ++-------- docs/source/libraries.rst | 2 ++ docs/source/todo.rst | 5 +++++ 8 files changed, 42 insertions(+), 11 deletions(-) create mode 100644 codeCore/src/prog8/code/ast/Verify.kt diff --git a/codeCore/src/prog8/code/SymbolTableMaker.kt b/codeCore/src/prog8/code/SymbolTableMaker.kt index 77e414913..8d9646eab 100644 --- a/codeCore/src/prog8/code/SymbolTableMaker.kt +++ b/codeCore/src/prog8/code/SymbolTableMaker.kt @@ -66,23 +66,26 @@ class SymbolTableMaker(private val program: PtProgram, private val options: Comp val numElements: Int? val value = node.value if(value!=null) { - val number = (value as? PtNumber)?.number - initialNumeric = if(number==0.0) null else number // 0 as init value -> just uninitialized when (value) { is PtString -> { initialString = StString(value.value, value.encoding) initialArray = null + initialNumeric = null numElements = value.value.length + 1 // include the terminating 0-byte } is PtArray -> { initialArray = makeInitialArray(value) initialString = null + initialNumeric = null numElements = initialArray.size require(node.arraySize?.toInt()==numElements) } else -> { + require(value is PtNumber) initialString = null initialArray = null + val number = value.number + initialNumeric = if(number==0.0) null else number // 0 as init value -> just uninitialized TODO weird? numElements = node.arraySize?.toInt() } } diff --git a/codeCore/src/prog8/code/ast/AstExpressions.kt b/codeCore/src/prog8/code/ast/AstExpressions.kt index 3eef2cdeb..ff088aa6e 100644 --- a/codeCore/src/prog8/code/ast/AstExpressions.kt +++ b/codeCore/src/prog8/code/ast/AstExpressions.kt @@ -238,6 +238,13 @@ class PtFunctionCall(val name: String, position: Position) : PtExpression(type, position) { val args: List get() = children.map { it as PtExpression } + + init { + if(void) require(type==DataType.UNDEFINED) { + "void fcall should have undefined datatype" + } + // note: non-void calls can have UNDEFINED type: is if they return more than 1 value + } } diff --git a/codeCore/src/prog8/code/ast/Verify.kt b/codeCore/src/prog8/code/ast/Verify.kt new file mode 100644 index 000000000..75f680a19 --- /dev/null +++ b/codeCore/src/prog8/code/ast/Verify.kt @@ -0,0 +1,16 @@ +package prog8.code.ast + +import prog8.code.SymbolTable +import prog8.code.core.* + +fun verifyFinalAstBeforeAsmGen(program: PtProgram, options: CompilationOptions, st: SymbolTable, errors: IErrorReporter) { +/* + walkAst(program) { node, _ -> + if(node is PtVariable) { + if(node.value!=null) { + // require(node.type in ArrayDatatypes || node.type==DataType.STR) { "final check before asmgen: only string and array variables can still have an init value ${node.name} ${node.type} ${node.position}"} + } + } + } +*/ +} diff --git a/codeCore/src/prog8/code/optimize/Optimizer.kt b/codeCore/src/prog8/code/optimize/Optimizer.kt index 4b02e8d37..eafb0c74e 100644 --- a/codeCore/src/prog8/code/optimize/Optimizer.kt +++ b/codeCore/src/prog8/code/optimize/Optimizer.kt @@ -60,7 +60,7 @@ private fun optimizeAssignTargets(program: PtProgram, st: SymbolTable, errors: I if(node.children.dropLast(1).all { (it as PtAssignTarget).void }) { // all targets are now void, the whole assignment can be discarded and replaced by just a (void) call to the subroutine val index = node.parent.children.indexOf(node) - val voidCall = PtFunctionCall(functionName, true, value.type, value.position) + val voidCall = PtFunctionCall(functionName, true, DataType.UNDEFINED, value.position) value.children.forEach { voidCall.add(it) } node.parent.children[index] = voidCall voidCall.parent = node.parent diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index d8a105a78..8c0be66ca 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -12,6 +12,7 @@ import prog8.ast.statements.Directive import prog8.code.SymbolTableMaker import prog8.code.ast.PtProgram import prog8.code.ast.printAst +import prog8.code.ast.verifyFinalAstBeforeAsmGen import prog8.code.core.* import prog8.code.optimize.optimizeIntermediateAst import prog8.code.target.AtariTarget @@ -146,6 +147,9 @@ fun compileProgram(args: CompilerArguments): CompilationResult? { println("*********** INTERMEDIATE AST END *************\n") } + verifyFinalAstBeforeAsmGen(intermediateAst, compilationOptions, symbolTable, args.errors) + args.errors.report() + if(!createAssemblyAndAssemble(intermediateAst, args.errors, compilationOptions)) { System.err.println("Error in codegeneration or assembler") return null diff --git a/compiler/test/ast/TestIntermediateAst.kt b/compiler/test/ast/TestIntermediateAst.kt index 25c2091e4..2d7711e8d 100644 --- a/compiler/test/ast/TestIntermediateAst.kt +++ b/compiler/test/ast/TestIntermediateAst.kt @@ -1,17 +1,11 @@ package prog8tests.ast -import io.kotest.assertions.fail import io.kotest.core.spec.style.FunSpec -import io.kotest.matchers.ints.shouldBeGreaterThan import io.kotest.matchers.shouldBe -import io.kotest.matchers.types.instanceOf -import prog8.code.ast.* +import prog8.code.ast.PtBinaryExpression +import prog8.code.ast.PtNumber import prog8.code.core.DataType import prog8.code.core.Position -import prog8.code.target.C64Target -import prog8.compiler.astprocessing.IntermediateAstMaker -import prog8tests.helpers.ErrorReporterForTests -import prog8tests.helpers.compileText class TestIntermediateAst: FunSpec({ diff --git a/docs/source/libraries.rst b/docs/source/libraries.rst index 5ab163062..455eafea5 100644 --- a/docs/source/libraries.rst +++ b/docs/source/libraries.rst @@ -134,6 +134,7 @@ rol (x) (essentially, it is a 9-bit or 17-bit rotation) Modifies in-place, doesn't return a value (so can't be used in an expression). You can rol a memory location directly by using the direct memory access syntax, so like ``rol(@($5000))`` + You can use ``if_cc`` or ``if_cs`` after a rol to act on the new carry bit, if required. rol2 (x) Like ``rol`` but now as 8-bit or 16-bit rotation. @@ -148,6 +149,7 @@ ror (x) (essentially, it is a 9-bit or 17-bit rotation) Modifies in-place, doesn't return a value (so can't be used in an expression). You can ror a memory location directly by using the direct memory access syntax, so like ``ror(@($5000))`` + You can use ``if_cc`` or ``if_cs`` after a ror to act on the new carry bit, if required. ror2 (x) Like ``ror`` but now as 8-bit or 16-bit rotation. diff --git a/docs/source/todo.rst b/docs/source/todo.rst index abcf3e01b..f45f56a4e 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,6 +1,11 @@ TODO ==== +In ast2 allow PtVariable to still have a numeric initialization value in codegen. (instead of only array and string) +why is 0 as value stored as null in symboltablemaker? + +are variables initialized with 0 reset to 0 with an assignment? WHY is the BSS area then cleared with memset? shouldn't be necessary? + - defers that haven't been reached yet should not be executed (how will we do this? some kind of runtime support needed? refcount or bitmask, not a boolean var per defer that would be wasteful) - unit test for defer - describe defer in the manual