mirror of
https://github.com/irmen/prog8.git
synced 2024-11-26 11:49:22 +00:00
decide sim is not worth it
This commit is contained in:
parent
e6e84859b7
commit
61398ee8f8
@ -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")
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user