From a03c4c365929c175d52a9e874baad25c41537c7a Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 4 Mar 2022 22:26:46 +0100 Subject: [PATCH] working on symbol table --- .../prog8/codegen/experimental6502/AsmGen.kt | 4 + .../codegen/experimental6502/SymbolTable.kt | 82 +++++++++++++++++++ .../experimental6502/SymbolTableMaker.kt | 65 +++++++++++++++ .../target/cx16/CX16MachineDefinition.kt | 2 +- compiler/res/version.txt | 2 +- .../src/prog8/compilerinterface/Zeropage.kt | 2 +- examples/test.p8 | 57 +++++++++---- 7 files changed, 196 insertions(+), 18 deletions(-) create mode 100644 codeGenExperimental6502/src/prog8/codegen/experimental6502/SymbolTable.kt create mode 100644 codeGenExperimental6502/src/prog8/codegen/experimental6502/SymbolTableMaker.kt diff --git a/codeGenExperimental6502/src/prog8/codegen/experimental6502/AsmGen.kt b/codeGenExperimental6502/src/prog8/codegen/experimental6502/AsmGen.kt index 1376b477e..92731387a 100644 --- a/codeGenExperimental6502/src/prog8/codegen/experimental6502/AsmGen.kt +++ b/codeGenExperimental6502/src/prog8/codegen/experimental6502/AsmGen.kt @@ -12,6 +12,10 @@ class AsmGen(internal val program: Program, println("\n** experimental 65(c)02 code generator **\n") + val stMaker = SymbolTableMaker() + val symbolTable = stMaker.make(program) + symbolTable.print() + println("..todo: create assembly code into ${options.outputDir.toAbsolutePath()}..") return AssemblyProgram("dummy") } diff --git a/codeGenExperimental6502/src/prog8/codegen/experimental6502/SymbolTable.kt b/codeGenExperimental6502/src/prog8/codegen/experimental6502/SymbolTable.kt new file mode 100644 index 000000000..2d27b9c12 --- /dev/null +++ b/codeGenExperimental6502/src/prog8/codegen/experimental6502/SymbolTable.kt @@ -0,0 +1,82 @@ +package prog8.codegen.experimental6502 + +import prog8.ast.base.DataType +import prog8.ast.base.Position +import prog8.ast.toHex + + +enum class StNodeType { + GLOBAL, + // MODULE, // not used with current scoping rules + BLOCK, + SUBROUTINE, + LABEL, + VARIABLE, + MEMVAR, + CONSTANT, + BUILTINFUNC +} + +open class StNode(val name: String, + val type: StNodeType, + val position: Position, + val children: MutableMap = mutableMapOf() +) { + + lateinit var parent: StNode + + val scopedName: List by lazy { + if(type==StNodeType.GLOBAL) + emptyList() + else + parent.scopedName + name + } + + fun printIndented(indent: Int) { + print(" ".repeat(indent)) + when(type) { + StNodeType.GLOBAL -> print("SYMBOL-TABLE:") + StNodeType.BLOCK -> print("[B] ") + StNodeType.SUBROUTINE -> print("[S] ") + StNodeType.LABEL -> print("[L] ") + StNodeType.VARIABLE -> print("[V] ") + StNodeType.MEMVAR -> print("[M] ") + StNodeType.CONSTANT -> print("[C] ") + StNodeType.BUILTINFUNC -> print("[F] ") + } + printProperties() + println(" pos=$position sn=$scopedName") + children.forEach { (_, node) -> node.printIndented(indent+1) } + } + + open fun printProperties() { + print("$name ") + } +} + +class SymbolTable() : StNode("", StNodeType.GLOBAL, Position.DUMMY) { + fun print() = printIndented(0) + + override fun printProperties() { } +} + +class StVariable(name: String, val dt: DataType, position: Position) : StNode(name, StNodeType.VARIABLE, position) { + override fun printProperties() { + print("dt=$dt") + } +} + +class StConstant(name: String, val dt: DataType, val value: Double, position: Position) : + StNode(name, StNodeType.CONSTANT, position) { + override fun printProperties() { + print("dt=$dt value=$value") + } +} + +class StMemVar(name: String, val dt: DataType, val address: UInt, position: Position) : + StNode(name, StNodeType.MEMVAR, position +) { + override fun printProperties() { + print("dt=$dt address=${address.toHex()}") + } +} diff --git a/codeGenExperimental6502/src/prog8/codegen/experimental6502/SymbolTableMaker.kt b/codeGenExperimental6502/src/prog8/codegen/experimental6502/SymbolTableMaker.kt new file mode 100644 index 000000000..c137751f5 --- /dev/null +++ b/codeGenExperimental6502/src/prog8/codegen/experimental6502/SymbolTableMaker.kt @@ -0,0 +1,65 @@ +package prog8.codegen.experimental6502 + +import prog8.ast.Program +import prog8.ast.base.Position +import prog8.ast.base.VarDeclType +import prog8.ast.expressions.NumericLiteral +import prog8.ast.statements.Block +import prog8.ast.statements.Label +import prog8.ast.statements.Subroutine +import prog8.ast.statements.VarDecl +import prog8.ast.walk.IAstVisitor +import java.util.* + +class SymbolTableMaker: IAstVisitor { + + private val st = SymbolTable() + private val scopestack = Stack() + + fun make(program: Program): SymbolTable { + scopestack.clear() + st.children.clear() + this.visit(program) + program.builtinFunctions.names.forEach { + val node = StNode(it, StNodeType.BUILTINFUNC, Position.DUMMY) + node.parent = st + st.children[it] = node + } + return st + } + + override fun visit(block: Block) { + val node = StNode(block.name, StNodeType.BLOCK, block.position) + node.parent = st + scopestack.push(node) + super.visit(block) + scopestack.pop() + st.children[node.name] = node + } + + override fun visit(subroutine: Subroutine) { + val node = StNode(subroutine.name, StNodeType.SUBROUTINE, subroutine.position) + node.parent = scopestack.peek() + scopestack.push(node) + super.visit(subroutine) + scopestack.pop() + scopestack.peek().children[node.name] = node + } + + override fun visit(decl: VarDecl) { + val node = + when(decl.type) { + VarDeclType.VAR -> StVariable(decl.name, decl.datatype, decl.position) + VarDeclType.CONST -> StConstant(decl.name, decl.datatype, (decl.value as NumericLiteral).number, decl.position) + VarDeclType.MEMORY -> StMemVar(decl.name, decl.datatype, (decl.value as NumericLiteral).number.toUInt(), decl.position) + } + node.parent = scopestack.peek() + node.parent.children[node.name] = node + } + + override fun visit(label: Label) { + val node = StNode(label.name, StNodeType.LABEL, label.position) + node.parent = scopestack.peek() + node.parent.children[node.name] = node + } +} diff --git a/codeGenTargets/src/prog8/codegen/target/cx16/CX16MachineDefinition.kt b/codeGenTargets/src/prog8/codegen/target/cx16/CX16MachineDefinition.kt index 693f1b66e..3c8c62395 100644 --- a/codeGenTargets/src/prog8/codegen/target/cx16/CX16MachineDefinition.kt +++ b/codeGenTargets/src/prog8/codegen/target/cx16/CX16MachineDefinition.kt @@ -60,7 +60,7 @@ class CX16MachineDefinition: IMachineDefinition { zeropage = CX16Zeropage(compilerOptions) } - // 6502 opcodes (including aliases and illegal opcodes), these cannot be used as variable or label names + // 65c02 opcodes, these cannot be used as variable or label names override val opcodeNames = setOf("adc", "and", "asl", "bcc", "bcs", "beq", "bge", "bit", "blt", "bmi", "bne", "bpl", "brk", "bvc", "bvs", "clc", "cld", "cli", "clv", "cmp", "cpx", "cpy", "dec", "dex", "dey", diff --git a/compiler/res/version.txt b/compiler/res/version.txt index fbf1779b2..8dce890fd 100644 --- a/compiler/res/version.txt +++ b/compiler/res/version.txt @@ -1 +1 @@ -7.9 +7.10-dev diff --git a/compilerInterfaces/src/prog8/compilerinterface/Zeropage.kt b/compilerInterfaces/src/prog8/compilerinterface/Zeropage.kt index 623f71a5d..a44dc2a2e 100644 --- a/compilerInterfaces/src/prog8/compilerinterface/Zeropage.kt +++ b/compilerInterfaces/src/prog8/compilerinterface/Zeropage.kt @@ -23,7 +23,7 @@ abstract class Zeropage(protected val options: CompilationOptions) { data class ZpAllocation(val address: UInt, val dt: DataType, val size: Int, - val originalScope: INameScope, + val originalScope: INameScope, // TODO try to get rid of this reference val initialStringValue: StringLiteral?, val initialArrayValue: ArrayLiteral?) diff --git a/examples/test.p8 b/examples/test.p8 index 964a882b2..377a16819 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,27 +1,54 @@ %import textio -%import floats %import test_stack %zeropage basicsafe +; Note: this program is compatible with C64 and CX16. + main { + + ubyte[256] sieve + ubyte candidate_prime = 2 ; is increased in the loop + sub start() { - get_player(1) - |> determine_score() - |> add_bonus() - |> txt.print_uw() - } + sys.memset(sieve, 256, false) ; clear the sieve, to reset starting situation on subsequent runs - sub get_player(ubyte xx) -> ubyte { - return xx+33 - } + ; calculate primes + txt.print("prime numbers up to 255:\n\n") + ubyte amount=0 + repeat { + ubyte prime = find_next_prime() + if prime==0 + break + txt.print_ub(prime) + txt.print(", ") + amount++ + } + txt.nl() + txt.print("number of primes (expected 54): ") + txt.print_ub(amount) + txt.nl() - sub determine_score(ubyte zz) -> ubyte { - return zz+22 - } - - sub add_bonus(ubyte qq) -> ubyte { - return qq+1 + ; test_stack.test() } + sub find_next_prime() -> ubyte { + + while sieve[candidate_prime] { + candidate_prime++ + if candidate_prime==0 + return 0 ; we wrapped; no more primes available in the sieve + } + + ; found next one, mark the multiples and return it. + sieve[candidate_prime] = true + uword multiple = candidate_prime + + + while multiple < len(sieve) { + sieve[lsb(multiple)] = true + multiple += candidate_prime + } + return candidate_prime + } }