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
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")

View File

@ -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<Double, DataType>?): FlowcontrolException()
class ExitProgram(val status: Int): FlowcontrolException()
class JumpTo(val targetName: List<String>): 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<InstructionPointer>()
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<Double, DataType>? {
return try {
executeStatementList(sub.children)
null
} catch(r: ReturnValue) {
r.value
}
}
internal fun executeStatementList(nodes: List<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 {
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<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 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()
}
}