decide sim is not worth it

This commit is contained in:
Irmen de Jong 2022-03-09 22:39:05 +01:00
parent e6e84859b7
commit 61398ee8f8
2 changed files with 72 additions and 65 deletions

View File

@ -1,6 +1,9 @@
package prog8.sim package prog8.sim
import prog8.ast.base.DataType 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.Encoding
import prog8.compilerinterface.StNodeType import prog8.compilerinterface.StNodeType
import prog8.compilerinterface.StStaticVariable import prog8.compilerinterface.StStaticVariable
@ -111,7 +114,8 @@ class Evaluator(
throw NotImplementedError("simulator can't run asmsub ${node.name}") throw NotImplementedError("simulator can't run asmsub ${node.name}")
node as PtSub node as PtSub
passCallArgs(node, args) 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 -> { StNodeType.STATICVAR -> {
val variable = target as StStaticVariable val variable = target as StStaticVariable
val value = variables.getValue(variable) val value = variables.getValue(variable)
if(value.number==null) if(value.number==null){
TODO("${ident.ref} -> $value") if(variable.dt in PassByReferenceDatatypes) {
return Pair(value.number!!, target.dt) // 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") StNodeType.CONSTANT -> throw IllegalArgumentException("constants should have been const folded")
else -> throw IllegalArgumentException("weird ref target") else -> throw IllegalArgumentException("weird ref target")

View File

@ -1,105 +1,97 @@
package prog8.sim package prog8.sim
import prog8.ast.base.DataType import prog8.ast.base.DataType
import prog8.ast.base.Position
import prog8.compilerinterface.Encoding
import prog8.compilerinterface.StStaticVariable import prog8.compilerinterface.StStaticVariable
import prog8.compilerinterface.SymbolTable import prog8.compilerinterface.SymbolTable
import prog8.compilerinterface.intermediate.* import prog8.compilerinterface.intermediate.*
import java.util.Stack import java.util.*
sealed class FlowcontrolException : Exception() sealed class FlowcontrolException : Exception()
class ReturnValue(val value: Pair<Double, DataType>?): FlowcontrolException()
class ExitProgram(val status: Int): FlowcontrolException() class ExitProgram(val status: Int): FlowcontrolException()
class JumpTo(val targetName: List<String>): FlowcontrolException()
class Simulator(val program: PtProgram, val symboltable: SymbolTable) { class Simulator(val program: PtProgram, val symboltable: SymbolTable) {
val memory = Memory() val memory = Memory()
private val variables = Variables(symboltable) private val variables = Variables(symboltable)
private val eval = Evaluator(symboltable, memory, variables, this) private val eval = Evaluator(symboltable, memory, variables, this)
internal val instructionPtrStack = Stack<InstructionPointer>()
internal var ip = InstructionPointer(emptyList())
fun run() { fun run() {
memory.clear() memory.clear()
val start = program.entrypoint() ?: throw NoSuchElementException("no main.start() found") val start = program.entrypoint() ?: throw NoSuchElementException("no main.start() found")
ip = InstructionPointer(start.children)
try { try {
executeSubroutine(start) while(true)
} catch(r: ReturnValue) { executeStatement(ip.current)
println("Program Exit.")
} catch (exit: ExitProgram) { } catch (exit: ExitProgram) {
println("Program Exit! Status code: ${exit.status}") println("Program Exit! Status code: ${exit.status}")
} }
} }
internal fun executeSubroutine(sub: PtSub): Pair<Double, DataType>? {
return try {
executeStatementList(sub.children)
null
} catch(r: ReturnValue) {
r.value
}
}
internal fun executeStatementList(nodes: List<PtNode>) { internal fun executeStatement(node: PtNode) {
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 {
return when(node) { return when(node) {
is PtAsmSub -> throw NotImplementedError("can't run assembly subroutine in simulator at this time") is PtAsmSub -> throw NotImplementedError("can't run assembly subroutine in simulator at this time")
is PtAssignment -> execute(node) is PtAssignment -> execute(node)
is PtBuiltinFunctionCall -> { is PtBuiltinFunctionCall -> {
eval.evaluate(node) // throw away any result eval.evaluate(node) // throw away any result
true ip.next()
} }
is PtConditionalBranch -> TODO() is PtConditionalBranch -> TODO()
is PtDirective -> execute(node) is PtDirective -> execute(node)
is PtForLoop -> TODO() is PtForLoop -> TODO()
is PtFunctionCall -> { is PtFunctionCall -> {
eval.evaluate(node) // throw away any result eval.evaluate(node) // throw away any result
true ip.next()
} }
is PtGosub -> TODO() is PtGosub -> execute(node)
is PtIfElse -> execute(node) is PtIfElse -> execute(node)
is PtInlineAssembly -> throw NotImplementedError("can't run inline assembly in simulator at this time") is PtInlineAssembly -> throw NotImplementedError("can't run inline assembly in simulator at this time")
is PtJump -> execute(node) is PtJump -> execute(node)
is PtLabel -> true is PtLabel -> ip.next()
is PtPipe -> execute(node) is PtPipe -> execute(node)
is PtPostIncrDecr -> execute(node) is PtPostIncrDecr -> execute(node)
is PtRepeatLoop -> execute(node) is PtRepeatLoop -> execute(node)
is PtReturn -> execute(node) is PtReturn -> execute(node)
is PtSub -> true // this simulator doesn't "fall through" into nested subroutines is PtSub -> ip.next() // this simulator doesn't "fall through" into nested subroutines
is PtVariable -> true is PtVariable -> ip.next()
is PtWhen -> TODO() is PtWhen -> TODO()
else -> TODO("missing code for node $node") else -> TODO("missing code for node $node")
} }
} }
private fun execute(jump: PtJump): Boolean { private fun execute(jump: PtJump) {
if(jump.address!=null) if(jump.address!=null)
throw NotImplementedError("simulator can't jump into memory machine code") throw NotImplementedError("simulator can't jump into memory machine code")
else if(jump.generatedLabel!=null) else if(jump.generatedLabel!=null)
throw NotImplementedError("simulator can't jump into generated label") throw NotImplementedError("simulator can't jump into generated label")
else { else {
throw JumpTo(jump.identifier!!.targetName) ip = findTargetNode(jump.identifier!!.targetName)
} }
} }
private fun execute(post: PtPostIncrDecr): Boolean { internal fun findTargetNode(targetName: List<String>): 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 identifier = post.target.identifier
val memoryAddr = post.target.memory val memoryAddr = post.target.memory
val array = post.target.array val array = post.target.array
@ -117,41 +109,45 @@ class Simulator(val program: PtProgram, val symboltable: SymbolTable) {
} else if(array!=null) { } else if(array!=null) {
println("TODO: ${array.variable.ref}[] ${post.operator}") 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) val condition = eval.evaluateExpression(ifelse.condition)
if(condition.first!=0.0) { ip = if(condition.first!=0.0) {
println("TODO: if part") InstructionPointer(ifelse.ifScope.children)
} else { } 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 { private fun execute(repeat: PtRepeatLoop) {
TODO("repeat $repeat. ${repeat.position}") val count = eval.evaluateExpression(repeat.count).first.toInt()
return true // 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") TODO("pipe stmt $pipe")
ip.next()
} }
private fun execute(ret: PtReturn): Boolean { private fun execute(ret: PtReturn) {
if(ret.hasValue) if(ret.hasValue) {
throw ReturnValue(eval.evaluateExpression(ret.value!!)) // TODO how to handle the actual return value
else }
throw ReturnValue(null) ip = instructionPtrStack.pop()
ip.next()
} }
private fun execute(directive: PtDirective): Boolean { private fun execute(directive: PtDirective) {
// TODO handle directive // 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 value = eval.evaluateExpression(assign.value)
val identifier = assign.target.identifier val identifier = assign.target.identifier
val memoryAddr = assign.target.memory val memoryAddr = assign.target.memory
@ -170,7 +166,7 @@ class Simulator(val program: PtProgram, val symboltable: SymbolTable) {
TODO("assign $value to array $array") TODO("assign $value to array $array")
else else
throw IllegalArgumentException("missing assign target") throw IllegalArgumentException("missing assign target")
return true ip.next()
} }
} }