From 0a04e626d7ae83b3a6e8163b6542f88a4d4c09e3 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 6 Mar 2022 17:29:30 +0100 Subject: [PATCH] added new intermediate (simplified) AST meant for new codegen --- .../prog8/codegen/experimental6502/AsmGen.kt | 3 + .../experimental6502/IntermediateAstMaker.kt | 412 ++++++++++++++++++ compiler/test/ast/TestIntermediateAst.kt | 32 ++ .../compilerinterface/intermediate/AstBase.kt | 110 +++++ .../intermediate/AstExpressions.kt | 108 +++++ .../intermediate/AstStatements.kt | 213 +++++++++ examples/test.p8 | 3 + 7 files changed, 881 insertions(+) create mode 100644 codeGenExperimental6502/src/prog8/codegen/experimental6502/IntermediateAstMaker.kt create mode 100644 compiler/test/ast/TestIntermediateAst.kt create mode 100644 compilerInterfaces/src/prog8/compilerinterface/intermediate/AstBase.kt create mode 100644 compilerInterfaces/src/prog8/compilerinterface/intermediate/AstExpressions.kt create mode 100644 compilerInterfaces/src/prog8/compilerinterface/intermediate/AstStatements.kt diff --git a/codeGenExperimental6502/src/prog8/codegen/experimental6502/AsmGen.kt b/codeGenExperimental6502/src/prog8/codegen/experimental6502/AsmGen.kt index c68b8e04a..0707055f8 100644 --- a/codeGenExperimental6502/src/prog8/codegen/experimental6502/AsmGen.kt +++ b/codeGenExperimental6502/src/prog8/codegen/experimental6502/AsmGen.kt @@ -14,6 +14,9 @@ class AsmGen(internal val program: Program, symbolTable.print() + // TODO temporary location to do this: + val intermediateAst = IntermediateAstMaker.transform(program) + intermediateAst.print() println("..todo: create assembly code into ${options.outputDir.toAbsolutePath()}..") return AssemblyProgram("dummy") diff --git a/codeGenExperimental6502/src/prog8/codegen/experimental6502/IntermediateAstMaker.kt b/codeGenExperimental6502/src/prog8/codegen/experimental6502/IntermediateAstMaker.kt new file mode 100644 index 000000000..8e7f94582 --- /dev/null +++ b/codeGenExperimental6502/src/prog8/codegen/experimental6502/IntermediateAstMaker.kt @@ -0,0 +1,412 @@ +package prog8.codegen.experimental6502 + +import prog8.ast.Module +import prog8.ast.Program +import prog8.ast.base.FatalAstException +import prog8.ast.base.VarDeclType +import prog8.ast.expressions.* +import prog8.ast.statements.* +import prog8.compilerinterface.intermediate.* + + +object IntermediateAstMaker { + fun transform(srcProgram: Program): PtProgram { + val program = PtProgram( + srcProgram.name, + srcProgram.builtinFunctions, + srcProgram.memsizer, + srcProgram.encoding + ) + + for (module in srcProgram.modules) { + program.add(transform(module)) + } + + return program + } + + private fun transform(srcModule: Module): PtModule { + val module = PtModule( + srcModule.name, + srcModule.source, + srcModule.loadAddress, + srcModule.isLibrary, + srcModule.position + ) + + for (statement in srcModule.statements) + module.add(transformStatement(statement)) + + return module + } + + private fun transformStatement(statement: Statement): PtNode { + return when (statement) { + is AnonymousScope -> throw FatalAstException("AnonymousScopes should have been flattened") + is Assignment -> transform(statement) + is Block -> transform(statement) + is Break -> throw FatalAstException("break should have been replaced by Goto") + is BuiltinFunctionCallStatement -> transform(statement) + is BuiltinFunctionPlaceholder -> throw FatalAstException("BuiltinFunctionPlaceholder should not occur in Ast here") + is ConditionalBranch -> transform(statement) + is Directive -> transform(statement) + is ForLoop -> transform(statement) + is FunctionCallStatement -> transform(statement) + is GoSub -> transform(statement) + is IfElse -> transform(statement) + is InlineAssembly -> transform(statement) + is Jump -> transform(statement) + is Label -> transform(statement) + is Pipe -> transform(statement) + is PostIncrDecr -> transform(statement) + is RepeatLoop -> transform(statement) + is Return -> transform(statement) + is Subroutine -> { + if(statement.isAsmSubroutine) + transformAsmSub(statement) + else + transformSub(statement) + } + is UntilLoop -> throw FatalAstException("until loops must have been converted to jumps") + is VarDecl -> transform(statement) + is When -> transform(statement) + is WhileLoop -> throw FatalAstException("while loops must have been converted to jumps") + } + } + + private fun transformExpression(expr: Expression): PtNode { + return when(expr) { + is AddressOf -> transform(expr) + is ArrayIndexedExpression -> transform(expr) + is ArrayLiteral -> transform(expr) + is BinaryExpression -> transform(expr) + is BuiltinFunctionCall -> transform(expr) + is CharLiteral -> throw FatalAstException("char literals should have been converted into bytes") + is ContainmentCheck -> transform(expr) + is DirectMemoryRead -> transform(expr) + is FunctionCallExpression -> transform(expr) + is IdentifierReference -> transform(expr) + is NumericLiteral -> transform(expr) + is PipeExpression -> transform(expr) + is PrefixExpression -> transform(expr) + is RangeExpression -> transform(expr) + is StringLiteral -> transform(expr) + is TypecastExpression -> transform(expr) + } + } + + private fun transform(srcAssign: Assignment): PtAssignment { + val assign = PtAssignment(srcAssign.isAugmentable, srcAssign.origin, srcAssign.position) + assign.add(transform(srcAssign.target)) + assign.add(transformExpression(srcAssign.value)) + return assign + } + + private fun transform(srcTarget: AssignTarget): PtAssignTarget { + val target = PtAssignTarget(srcTarget.position) + if(srcTarget.identifier!=null) + target.add(transform(srcTarget.identifier!!)) + else if(srcTarget.arrayindexed!=null) + target.add(transform(srcTarget.arrayindexed!!)) + else if(srcTarget.memoryAddress!=null) + target.add(transform(srcTarget.memoryAddress!!)) + else + throw FatalAstException("invalid AssignTarget") + return target + } + + private fun transform(identifier: IdentifierReference): PtIdentifier = + PtIdentifier(identifier.nameInSource, identifier.position) + + private fun transform(srcBlock: Block): PtBlock { + val block = PtBlock(srcBlock.name, srcBlock.address, srcBlock.isInLibrary, srcBlock.position) + + for (stmt in srcBlock.statements) + block.add(transformStatement(stmt)) + + return block + } + + private fun transform(srcNode: BuiltinFunctionCallStatement): PtBuiltinFunctionCall { + val call = PtBuiltinFunctionCall(srcNode.name, srcNode.position) + for (arg in srcNode.args) + call.add(transformExpression(arg)) + return call + } + + private fun transform(srcBranch: ConditionalBranch): PtConditionalBranch { + val branch = PtConditionalBranch(srcBranch.condition, srcBranch.position) + val trueScope = PtNodeGroup() + val falseScope = PtNodeGroup() + for (stmt in srcBranch.truepart.statements) + trueScope.add(transformStatement(stmt)) + for (stmt in srcBranch.elsepart.statements) + falseScope.add(transformStatement(stmt)) + branch.add(trueScope) + branch.add(falseScope) + return branch + } + + private fun transform(directive: Directive): PtDirective { + val dir = PtDirective(directive.directive, directive.position) + for (arg in directive.args) { + dir.add(transform(arg)) + } + return dir + } + + private fun transform(arg: DirectiveArg): PtDirectiveArg = + PtDirectiveArg(arg.str, arg.name, arg.int, arg.position) + + private fun transform(srcFor: ForLoop): PtForLoop { + val forloop = PtForLoop(srcFor.position) + forloop.add(transform(srcFor.loopVar)) + forloop.add(transformExpression(srcFor.iterable)) + val statements = PtNodeGroup() + for (stmt in srcFor.body.statements) + statements.add(transformStatement(stmt)) + forloop.add(statements) + return forloop + } + + private fun transform(srcCall: FunctionCallStatement): PtFunctionCall { + val call = PtFunctionCall(true, srcCall.position) + call.add(transform(srcCall.target)) + val args = PtNodeGroup() + for (arg in srcCall.args) + args.add(transformExpression(arg)) + call.add(args) + return call + } + + private fun transform(srcCall: FunctionCallExpression): PtFunctionCall { + val call = PtFunctionCall(false, srcCall.position) + call.add(transform(srcCall.target)) + val args = PtNodeGroup() + for (arg in srcCall.args) + args.add(transformExpression(arg)) + call.add(args) + return call + } + + private fun transform(gosub: GoSub): PtGosub { + val identifier = if(gosub.identifier!=null) transform(gosub.identifier!!) else null + return PtGosub(identifier, + gosub.address, + gosub.generatedLabel, + gosub.position) + } + + private fun transform(srcIf: IfElse): PtIfElse { + val ifelse = PtIfElse(srcIf.position) + ifelse.add(transformExpression(srcIf.condition)) + val ifScope = PtNodeGroup() + val elseScope = PtNodeGroup() + for (stmt in srcIf.truepart.statements) + ifScope.add(transformStatement(stmt)) + for (stmt in srcIf.elsepart.statements) + elseScope.add(transformStatement(stmt)) + ifelse.add(ifScope) + ifelse.add(elseScope) + return ifelse + } + + private fun transform(srcNode: InlineAssembly): PtInlineAssembly = + PtInlineAssembly(srcNode.assembly, srcNode.position) + + private fun transform(srcJump: Jump): PtJump { + val identifier = if(srcJump.identifier!=null) transform(srcJump.identifier!!) else null + return PtJump(identifier, + srcJump.address, + srcJump.generatedLabel, + srcJump.position) + } + + private fun transform(label: Label): PtLabel = + PtLabel(label.name, label.position) + + private fun transform(srcPipe: Pipe): PtPipe { + val pipe = PtPipe(srcPipe.position) + pipe.add(transformExpression(srcPipe.source)) + for (segment in srcPipe.segments) + pipe.add(transformExpression(segment)) + return pipe + } + + private fun transform(src: PostIncrDecr): PtPostIncrDecr { + val post = PtPostIncrDecr(src.operator, src.position) + post.add(transform(src.target)) + return post + } + + private fun transform(srcRepeat: RepeatLoop): PtRepeatLoop { + val repeat = PtRepeatLoop(srcRepeat.iterations==null, srcRepeat.position) + if(srcRepeat.iterations!=null) + repeat.add(transformExpression(srcRepeat.iterations!!)) + for (statement in srcRepeat.body.statements) { + repeat.add(transformStatement(statement)) + } + return repeat + } + + private fun transform(srcNode: Return): PtReturn { + val ret = PtReturn(srcNode.position) + if(srcNode.value!=null) + ret.add(transformExpression(srcNode.value!!)) + return ret + } + + private fun transformAsmSub(srcSub: Subroutine): PtAsmSub { + val sub = PtAsmSub(srcSub.name, + srcSub.asmAddress, + srcSub.asmClobbers, + srcSub.asmParameterRegisters, + srcSub.asmReturnvaluesRegisters, + srcSub.inline, + srcSub.position) + if(srcSub.asmAddress==null) { + var combinedAsm = "" + for (asm in srcSub.statements) + combinedAsm += (asm as InlineAssembly).assembly + "\n" + if(combinedAsm.isNotEmpty()) + sub.add(PtInlineAssembly(combinedAsm, srcSub.statements[0].position)) + else + sub.add(PtInlineAssembly("", srcSub.position)) + } + + return sub + } + + private fun transformSub(srcSub: Subroutine): PtSub { + val sub = PtSub(srcSub.name, + srcSub.parameters, + srcSub.returntypes, + srcSub.inline, + srcSub.position) + + for (statement in srcSub.statements) + sub.add(transformStatement(statement)) + + return sub + } + + private fun transform(srcVar: VarDecl): PtNode { + return when(srcVar.type) { + VarDeclType.VAR -> PtVariable(srcVar.name, srcVar.datatype, srcVar.position) + VarDeclType.CONST -> PtConstant(srcVar.name, srcVar.datatype, (srcVar.value as NumericLiteral).number, srcVar.position) + VarDeclType.MEMORY -> PtMemMapped(srcVar.name, srcVar.datatype, (srcVar.value as NumericLiteral).number.toUInt(), srcVar.position) + } + } + + private fun transform(srcWhen: When): PtWhen { + val w = PtWhen(srcWhen.position) + w.add(transformExpression(srcWhen.condition)) + val choices = PtNodeGroup() + for (choice in srcWhen.choices) + choices.add(transform(choice)) + w.add(choices) + return w + } + + private fun transform(srcChoice: WhenChoice): PtWhenChoice { + val choice = PtWhenChoice(srcChoice.values==null, srcChoice.position) + val values = PtNodeGroup() + val statements = PtNodeGroup() + if(!choice.isElse) { + for (value in srcChoice.values!!) + values.add(transformExpression(value)) + } + for (stmt in srcChoice.statements.statements) + statements.add(transformStatement(stmt)) + choice.add(values) + choice.add(statements) + return choice + } + + private fun transform(src: AddressOf): PtAddressOf { + val addr = PtAddressOf(src.position) + addr.add(transform(src.identifier)) + return addr + } + + private fun transform(srcArr: ArrayIndexedExpression): PtArrayIndexer { + val array = PtArrayIndexer(srcArr.position) + array.add(transform(srcArr.arrayvar)) + array.add(transformExpression(srcArr.indexer.indexExpr)) + return array + } + + private fun transform(srcArr: ArrayLiteral): PtArrayLiteral { + val arr = PtArrayLiteral(srcArr.type.getOrElse { throw FatalAstException("array must know its type") }, srcArr.position) + for (elt in srcArr.value) + arr.add(transformExpression(elt)) + return arr + } + + private fun transform(srcExpr: BinaryExpression): PtBinaryExpression { + val expr = PtBinaryExpression(srcExpr.operator, srcExpr.position) + expr.add(transformExpression(srcExpr.left)) + expr.add(transformExpression(srcExpr.right)) + return expr + } + + private fun transform(srcCall: BuiltinFunctionCall): PtBuiltinFunctionCall { + val call = PtBuiltinFunctionCall(srcCall.name, srcCall.position) + for (arg in srcCall.args) + call.add(transformExpression(arg)) + return call + } + + private fun transform(srcCheck: ContainmentCheck): PtContainmentCheck { + val check = PtContainmentCheck(srcCheck.position) + check.add(transformExpression(srcCheck.element)) + check.add(transformExpression(srcCheck.iterable)) + return check + } + + private fun transform(memory: DirectMemoryWrite): PtMemoryByte { + val mem = PtMemoryByte(memory.position) + mem.add(transformExpression(memory.addressExpression)) + return mem + } + + private fun transform(memory: DirectMemoryRead): PtMemoryByte { + val mem = PtMemoryByte(memory.position) + mem.add(transformExpression(memory.addressExpression)) + return mem + } + + private fun transform(number: NumericLiteral): PtNumber = + PtNumber(number.type, number.number, number.position) + + private fun transform(srcPipe: PipeExpression): PtPipe { + val pipe = PtPipe(srcPipe.position) + pipe.add(transformExpression(srcPipe.source)) + for (segment in srcPipe.segments) + pipe.add(transformExpression(segment)) + return pipe + } + + private fun transform(srcPrefix: PrefixExpression): PtPrefix { + val prefix = PtPrefix(srcPrefix.operator, srcPrefix.position) + prefix.add(transformExpression(srcPrefix.expression)) + return prefix + } + + private fun transform(srcRange: RangeExpression): PtRange { + val range=PtRange(srcRange.position) + range.add(transformExpression(srcRange.from)) + range.add(transformExpression(srcRange.to)) + range.add(transformExpression(srcRange.step)) + return range + } + + private fun transform(srcString: StringLiteral): PtString = + PtString(srcString.value, srcString.encoding, srcString.position) + + private fun transform(srcCast: TypecastExpression): PtTypeCast { + val cast = PtTypeCast(srcCast.type, srcCast.position) + cast.add(transformExpression(srcCast.expression)) + return cast + } +} diff --git a/compiler/test/ast/TestIntermediateAst.kt b/compiler/test/ast/TestIntermediateAst.kt new file mode 100644 index 000000000..67ed7e4f7 --- /dev/null +++ b/compiler/test/ast/TestIntermediateAst.kt @@ -0,0 +1,32 @@ +package prog8tests.ast + +import io.kotest.core.spec.style.FunSpec +import io.kotest.matchers.shouldBe +import prog8.codegen.experimental6502.IntermediateAstMaker +import prog8.codegen.target.C64Target +import prog8tests.helpers.assertSuccess +import prog8tests.helpers.compileText + +class TestIntermediateAst: FunSpec({ + + test("creation") { + val text=""" + %import textio + %import graphics + main { + sub start() { + ubyte cc + ubyte[] array = [1,2,3] + cc = 11 in array + cc = cc |> sin8u() |> cos8u() + } + } + """ + val result = compileText(C64Target(), false, text, writeAssembly = false).assertSuccess() + val ast = IntermediateAstMaker.transform(result.program) + ast.name shouldBe result.program.name + ast.builtinFunctions.names shouldBe result.program.builtinFunctions.names + ast.print() + } + +}) \ No newline at end of file diff --git a/compilerInterfaces/src/prog8/compilerinterface/intermediate/AstBase.kt b/compilerInterfaces/src/prog8/compilerinterface/intermediate/AstBase.kt new file mode 100644 index 000000000..3b2679c97 --- /dev/null +++ b/compilerInterfaces/src/prog8/compilerinterface/intermediate/AstBase.kt @@ -0,0 +1,110 @@ +package prog8.compilerinterface.intermediate + +import prog8.ast.IBuiltinFunctions +import prog8.ast.base.Position +import prog8.compilerinterface.IMemSizer +import prog8.compilerinterface.IStringEncoding +import prog8.parser.SourceCode + +// TODO : once the CodeGen doesn't need the old Ast anymore, get rid of the 'Pt' prefixes. + + +abstract class PtNode(val position: Position, val children: MutableList = mutableListOf()) { + + lateinit var parent: PtNode + + protected fun printIndented(indent: Int) { + print(" ".repeat(indent)) + print("${this.javaClass.simpleName} ") + printProperties() + println() + children.forEach { it.printIndented(indent+1) } + } + + abstract fun printProperties() + + fun add(child: PtNode) { + children.add(child) + child.parent = this + } + + fun add(index: Int, child: PtNode) { + children.add(index, child) + child.parent = this + } +} + + +class PtNodeGroup(): PtNode(Position.DUMMY) { + override fun printProperties() {} +} + + +class PtProgram( + val name: String, + val builtinFunctions: IBuiltinFunctions, + val memsizer: IMemSizer, + val encoding: IStringEncoding +) : PtNode(Position.DUMMY) { + fun print() = printIndented(0) + override fun printProperties() { + print("'$name'") + } +} + + +class PtModule( + val name: String, + val source: SourceCode, + val loadAddress: UInt, + val library: Boolean, + position: Position +) : PtNode(position) { + override fun printProperties() { + print("$name addr=$loadAddress library=$library") + } +} + + +class PtBlock(val name: String, + val address: UInt?, + val library: Boolean, + position: Position) : PtNode(position) { + override fun printProperties() { + print("$name addr=$address library=$library") + } +} + + +class PtDirective(val name: String, position: Position) : PtNode(position) { + val args: List + get() = children.map { it as PtDirectiveArg } + + override fun printProperties() { + print(name) + } +} + + +class PtDirectiveArg(val str: String?, + val name: String?, + val int: UInt?, + position: Position +): PtNode(position) { + override fun printProperties() { + print("str=$str name=$name int=$int") + } +} + + +class PtInlineAssembly(val assembly: String, position: Position) : PtNode(position) { + override fun printProperties() {} +} + + +class PtLabel(val name: String, position: Position) : PtNode(position) { + override fun printProperties() { + print(name) + } +} + diff --git a/compilerInterfaces/src/prog8/compilerinterface/intermediate/AstExpressions.kt b/compilerInterfaces/src/prog8/compilerinterface/intermediate/AstExpressions.kt new file mode 100644 index 000000000..0fa109b5d --- /dev/null +++ b/compilerInterfaces/src/prog8/compilerinterface/intermediate/AstExpressions.kt @@ -0,0 +1,108 @@ +package prog8.compilerinterface.intermediate + +import prog8.ast.base.DataType +import prog8.ast.base.Position +import prog8.compilerinterface.Encoding + + +class PtAddressOf(position: Position) : PtNode(position) { + val addr: PtNode + get() = children.single() + + override fun printProperties() {} +} + + +class PtArrayIndexer(position: Position): PtNode(position) { + val variable: PtIdentifier + get() = children[0] as PtIdentifier + val index: PtNode + get() = children[1] + + override fun printProperties() {} +} + + +class PtArrayLiteral(val type: DataType, position: Position): PtNode(position) { + override fun printProperties() { + print(type) + } +} + + +class PtBinaryExpression(val operator: String, position: Position): PtNode(position) { + val left: PtNode + get() = children[0] + val right: PtNode + get() = children[1] + + override fun printProperties() { + print(operator) + } +} + + +class PtContainmentCheck(position: Position): PtNode(position) { + val element: PtNode + get() = children[0] + val iterable: PtNode + get() = children[0] + override fun printProperties() {} +} + + +class PtIdentifier(val name: List, position: Position) : PtNode(position) { + override fun printProperties() { + print(name) + } +} + + +class PtMemoryByte(position: Position) : PtNode(position) { + val address: PtNode + get() = children.single() + override fun printProperties() {} +} + + +class PtNumber(val type: DataType, val number: Double, position: Position) : PtNode(position) { + override fun printProperties() { + print("$number ($type)") + } +} + + +class PtPrefix(val operator: String, position: Position): PtNode(position) { + val value: PtNode + get() = children.single() + + override fun printProperties() { + print(operator) + } +} + + +class PtRange(position: Position) : PtNode(position) { + val from: PtNode + get() = children[0] + val to: PtNode + get() = children[1] + val step: PtNode + get() = children[2] + + override fun printProperties() {} +} + + +class PtString(val value: String, val encoding: Encoding, position: Position) : PtNode(position) { + override fun printProperties() { + print("$encoding:\"$value\"") + } +} + + +class PtTypeCast(val type: DataType, position: Position) : PtNode(position) { + override fun printProperties() { + print(type) + } +} \ No newline at end of file diff --git a/compilerInterfaces/src/prog8/compilerinterface/intermediate/AstStatements.kt b/compilerInterfaces/src/prog8/compilerinterface/intermediate/AstStatements.kt new file mode 100644 index 000000000..5de8e4b8c --- /dev/null +++ b/compilerInterfaces/src/prog8/compilerinterface/intermediate/AstStatements.kt @@ -0,0 +1,213 @@ +package prog8.compilerinterface.intermediate + +import prog8.ast.base.BranchCondition +import prog8.ast.base.CpuRegister +import prog8.ast.base.DataType +import prog8.ast.base.Position +import prog8.ast.statements.AssignmentOrigin +import prog8.ast.statements.RegisterOrStatusflag +import prog8.ast.statements.SubroutineParameter +import prog8.ast.toHex + + +class PtAsmSub( + val name: String, + val address: UInt?, + val clobbers: Set, + val paramRegisters: List, + val retvalRegisters: List, + val inline: Boolean, + position: Position +) : PtNode(position) { + override fun printProperties() { + print("$name inline=$inline") + } +} + + +class PtSub( + val name: String, + val parameters: List, + val returntypes: List, + val inline: Boolean, + position: Position +) : PtNode(position) { + override fun printProperties() { + print(name) + } +} + + +class PtAssignment(val augmentable: Boolean, val origin: AssignmentOrigin, position: Position) : PtNode(position) { + val target: PtAssignTarget + get() = children[0] as PtAssignTarget + val value: PtNode + get() = children[1] + + override fun printProperties() { + print("aug=$augmentable origin=$origin") + } +} + + +class PtAssignTarget(position: Position) : PtNode(position) { + val identifier: PtIdentifier? + get() = children.single() as? PtIdentifier + val array: PtArrayIndexer? + get() = children.single() as? PtArrayIndexer + val memory: PtMemoryByte? + get() = children.single() as? PtMemoryByte + + override fun printProperties() {} +} + + +class PtBuiltinFunctionCall(val name: String, position: Position) : PtNode(position) { + override fun printProperties() { + print(name) + } +} + + +class PtConditionalBranch(val condition: BranchCondition, position: Position) : PtNode(position) { + val trueScope: PtNodeGroup + get() = children[0] as PtNodeGroup + val falseScope: PtNodeGroup + get() = children[1] as PtNodeGroup + + override fun printProperties() { + print(condition) + } +} + + +class PtForLoop(position: Position) : PtNode(position) { + val variable: PtIdentifier + get() = children[0] as PtIdentifier + val iterable: PtNode + get() = children[1] + val statements: PtNodeGroup + get() = children[2] as PtNodeGroup + + override fun printProperties() {} +} + + +class PtFunctionCall(val void: Boolean, position: Position) : PtNode(position) { + val target: PtIdentifier + get() = children[0] as PtIdentifier + val args: PtNodeGroup + get() = children[1] as PtNodeGroup + + override fun printProperties() { + print("void=$void") + } +} + + +class PtGosub(val identifier: PtIdentifier?, + val address: UInt?, + val generatedLabel: String?, + position: Position) : PtNode(position) { + override fun printProperties() { + identifier?.printProperties() + if(address!=null) print(address.toHex()) + if(generatedLabel!=null) print(generatedLabel) + } +} + + +class PtIfElse(position: Position) : PtNode(position) { + val condition: PtNode + get() = children[0] + val ifScope: PtNodeGroup + get() = children[1] as PtNodeGroup + val elseScope: PtNodeGroup + get() = children[2] as PtNodeGroup + + override fun printProperties() {} +} + + +class PtJump(val identifier: PtIdentifier?, + val address: UInt?, + val generatedLabel: String?, + position: Position) : PtNode(position) { + override fun printProperties() { + identifier?.printProperties() + if(address!=null) print(address.toHex()) + if(generatedLabel!=null) print(generatedLabel) + } +} + + +class PtPipe(position: Position) : PtNode(position) { + override fun printProperties() {} +} + + +class PtPostIncrDecr(val operator: String, position: Position) : PtNode(position) { + val target: PtAssignTarget + get() = children.single() as PtAssignTarget + + override fun printProperties() { + print(operator) + } +} + + +class PtRepeatLoop(val forever: Boolean, position: Position) : PtNode(position) { + override fun printProperties() { + print("forever=$forever") + } +} + + +class PtReturn(position: Position) : PtNode(position) { + val hasValue = children.any() + val value: PtNode? + get() { + return if(children.any()) + children.single() + else + null + } + + override fun printProperties() {} +} + + +class PtVariable(val name: String, val type: DataType, position: Position) : PtNode(position) { + override fun printProperties() { + print("$type $name") + } +} + + +class PtConstant(val name: String, val type: DataType, val value: Double, position: Position) : PtNode(position) { + override fun printProperties() { + print("$type $name = $value") + } +} + + +class PtMemMapped(val name: String, val type: DataType, val address: UInt, position: Position) : PtNode(position) { + override fun printProperties() { + print("&$type $name = ${address.toHex()}") + } +} + + +class PtWhen(position: Position) : PtNode(position) { + val value: PtNode + get() = children[0] + val choices: PtNodeGroup + get() = children[1] as PtNodeGroup + + override fun printProperties() {} +} + + +class PtWhenChoice(val isElse: Boolean, position: Position) : PtNode(position) { + override fun printProperties() {} +} diff --git a/examples/test.p8 b/examples/test.p8 index 377a16819..866ab6561 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -12,6 +12,9 @@ main { sub start() { sys.memset(sieve, 256, false) ; clear the sieve, to reset starting situation on subsequent runs + ubyte qq = candidate_prime |> sin8u() |> cos8u() + candidate_prime |> sin8u() |> txt.print_ub() + ; calculate primes txt.print("prime numbers up to 255:\n\n") ubyte amount=0