From 61398ee8f8b7b07faf4b6be9f995fb2869fc49b0 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Wed, 9 Mar 2022 22:39:05 +0100 Subject: [PATCH] decide sim is not worth it --- simulator/src/prog8/sim/Evaluator.kt | 19 ++++- simulator/src/prog8/sim/Simulator.kt | 118 +++++++++++++-------------- 2 files changed, 72 insertions(+), 65 deletions(-) diff --git a/simulator/src/prog8/sim/Evaluator.kt b/simulator/src/prog8/sim/Evaluator.kt index 17dde8c0c..69d71efc8 100644 --- a/simulator/src/prog8/sim/Evaluator.kt +++ b/simulator/src/prog8/sim/Evaluator.kt @@ -1,6 +1,9 @@ package prog8.sim import prog8.ast.base.DataType +import prog8.ast.base.PassByReferenceDatatypes +import prog8.ast.base.Position +import prog8.ast.expressions.AddressOf import prog8.compilerinterface.Encoding import prog8.compilerinterface.StNodeType import prog8.compilerinterface.StStaticVariable @@ -111,7 +114,8 @@ class Evaluator( throw NotImplementedError("simulator can't run asmsub ${node.name}") node as PtSub passCallArgs(node, args) - return simulator.executeSubroutine(node)!! + simulator.instructionPtrStack.push(simulator.ip) + simulator.ip = InstructionPointer(node.children) } } } @@ -135,9 +139,16 @@ class Evaluator( StNodeType.STATICVAR -> { val variable = target as StStaticVariable val value = variables.getValue(variable) - if(value.number==null) - TODO("${ident.ref} -> $value") - return Pair(value.number!!, target.dt) + if(value.number==null){ + if(variable.dt in PassByReferenceDatatypes) { + // return the address instead + val addrof = PtAddressOf(ident.position) + addrof.add(PtIdentifier(ident.ref, ident.targetName, ident.position)) + return evaluate(addrof) + } else + throw IllegalArgumentException("invalid dt") + } + return Pair(value.number, target.dt) } StNodeType.CONSTANT -> throw IllegalArgumentException("constants should have been const folded") else -> throw IllegalArgumentException("weird ref target") diff --git a/simulator/src/prog8/sim/Simulator.kt b/simulator/src/prog8/sim/Simulator.kt index dd1384250..5e3ee0986 100644 --- a/simulator/src/prog8/sim/Simulator.kt +++ b/simulator/src/prog8/sim/Simulator.kt @@ -1,105 +1,97 @@ package prog8.sim import prog8.ast.base.DataType -import prog8.ast.base.Position -import prog8.compilerinterface.Encoding import prog8.compilerinterface.StStaticVariable import prog8.compilerinterface.SymbolTable import prog8.compilerinterface.intermediate.* -import java.util.Stack +import java.util.* sealed class FlowcontrolException : Exception() -class ReturnValue(val value: Pair?): FlowcontrolException() - class ExitProgram(val status: Int): FlowcontrolException() -class JumpTo(val targetName: List): FlowcontrolException() - class Simulator(val program: PtProgram, val symboltable: SymbolTable) { val memory = Memory() private val variables = Variables(symboltable) private val eval = Evaluator(symboltable, memory, variables, this) + internal val instructionPtrStack = Stack() + internal var ip = InstructionPointer(emptyList()) fun run() { memory.clear() val start = program.entrypoint() ?: throw NoSuchElementException("no main.start() found") + + ip = InstructionPointer(start.children) try { - executeSubroutine(start) - } catch(r: ReturnValue) { - println("Program Exit.") + while(true) + executeStatement(ip.current) } catch (exit: ExitProgram) { println("Program Exit! Status code: ${exit.status}") } } - internal fun executeSubroutine(sub: PtSub): Pair? { - return try { - executeStatementList(sub.children) - null - } catch(r: ReturnValue) { - r.value - } - } - internal fun executeStatementList(nodes: List) { - var instructionPtr = InstructionPointer(nodes) - while(true) { - try { - if (executeStatement(instructionPtr.current)) - instructionPtr.next() - } catch(jump: JumpTo) { - val target = findPtNode(jump.targetName, instructionPtr.current) - val nodes = target.parent.children - instructionPtr = InstructionPointer(nodes, nodes.indexOf(target)) - } - } - } - - internal fun executeStatement(node: PtNode): Boolean { + internal fun executeStatement(node: PtNode) { return when(node) { is PtAsmSub -> throw NotImplementedError("can't run assembly subroutine in simulator at this time") is PtAssignment -> execute(node) is PtBuiltinFunctionCall -> { eval.evaluate(node) // throw away any result - true + ip.next() } is PtConditionalBranch -> TODO() is PtDirective -> execute(node) is PtForLoop -> TODO() is PtFunctionCall -> { eval.evaluate(node) // throw away any result - true + ip.next() } - is PtGosub -> TODO() + is PtGosub -> execute(node) is PtIfElse -> execute(node) is PtInlineAssembly -> throw NotImplementedError("can't run inline assembly in simulator at this time") is PtJump -> execute(node) - is PtLabel -> true + is PtLabel -> ip.next() is PtPipe -> execute(node) is PtPostIncrDecr -> execute(node) is PtRepeatLoop -> execute(node) is PtReturn -> execute(node) - is PtSub -> true // this simulator doesn't "fall through" into nested subroutines - is PtVariable -> true + is PtSub -> ip.next() // this simulator doesn't "fall through" into nested subroutines + is PtVariable -> ip.next() is PtWhen -> TODO() else -> TODO("missing code for node $node") } } - private fun execute(jump: PtJump): Boolean { + private fun execute(jump: PtJump) { if(jump.address!=null) throw NotImplementedError("simulator can't jump into memory machine code") else if(jump.generatedLabel!=null) throw NotImplementedError("simulator can't jump into generated label") else { - throw JumpTo(jump.identifier!!.targetName) + ip = findTargetNode(jump.identifier!!.targetName) } } - private fun execute(post: PtPostIncrDecr): Boolean { + internal fun findTargetNode(targetName: List): InstructionPointer { + val target = findPtNode(targetName, ip.current) + val nodes = target.parent.children + return InstructionPointer(nodes, nodes.indexOf(target)) + } + + private fun execute(gosub: PtGosub) { + if(gosub.address!=null) + throw NotImplementedError("simulator can't jump into memory machine code") + else if(gosub.generatedLabel!=null) + throw NotImplementedError("simulator can't jump into generated label") + else { + instructionPtrStack.push(ip) + ip = findTargetNode(gosub.identifier!!.targetName) + } + } + + private fun execute(post: PtPostIncrDecr) { val identifier = post.target.identifier val memoryAddr = post.target.memory val array = post.target.array @@ -117,41 +109,45 @@ class Simulator(val program: PtProgram, val symboltable: SymbolTable) { } else if(array!=null) { println("TODO: ${array.variable.ref}[] ${post.operator}") } - return true + ip.next() } - private fun execute(ifelse: PtIfElse): Boolean { + private fun execute(ifelse: PtIfElse) { val condition = eval.evaluateExpression(ifelse.condition) - if(condition.first!=0.0) { - println("TODO: if part") + ip = if(condition.first!=0.0) { + InstructionPointer(ifelse.ifScope.children) } else { - println("TODO: else part") + InstructionPointer(ifelse.elseScope.children) } - return true + // TODO how to handle the exiting of the subscopes, and continue after the ifelse statement. } - private fun execute(repeat: PtRepeatLoop): Boolean { - TODO("repeat $repeat. ${repeat.position}") - return true + private fun execute(repeat: PtRepeatLoop) { + val count = eval.evaluateExpression(repeat.count).first.toInt() + // TODO how to handle the exiting of the subscopes, and continue after the repeat statement. + TODO("repeat $count ${repeat.position}") + ip.next() } - private fun execute(pipe: PtPipe): Boolean { + private fun execute(pipe: PtPipe) { TODO("pipe stmt $pipe") + ip.next() } - private fun execute(ret: PtReturn): Boolean { - if(ret.hasValue) - throw ReturnValue(eval.evaluateExpression(ret.value!!)) - else - throw ReturnValue(null) + private fun execute(ret: PtReturn) { + if(ret.hasValue) { + // TODO how to handle the actual return value + } + ip = instructionPtrStack.pop() + ip.next() } - private fun execute(directive: PtDirective): Boolean { + private fun execute(directive: PtDirective) { // TODO handle directive - return true + ip.next() } - private fun execute(assign: PtAssignment): Boolean { + private fun execute(assign: PtAssignment) { val value = eval.evaluateExpression(assign.value) val identifier = assign.target.identifier val memoryAddr = assign.target.memory @@ -170,7 +166,7 @@ class Simulator(val program: PtProgram, val symboltable: SymbolTable) { TODO("assign $value to array $array") else throw IllegalArgumentException("missing assign target") - return true + ip.next() } }