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