mirror of
https://github.com/irmen/prog8.git
synced 2024-11-23 07:32:10 +00:00
fix memory pointer variables in the StackVm
This commit is contained in:
parent
89ac374db9
commit
711d6f4ee5
@ -27,31 +27,34 @@ sub start() {
|
|||||||
; }
|
; }
|
||||||
|
|
||||||
|
|
||||||
float[10] farr
|
ubyte bv = 99
|
||||||
float f = 3.3
|
word wv = 14443
|
||||||
memory float mflt = $c000
|
float fv = 3.14
|
||||||
memory float[10] mfarr = $d000
|
memory ubyte mb = $c000
|
||||||
ubyte i=3
|
memory word mw = $c100
|
||||||
|
memory float mf = $c200
|
||||||
mflt = 55.44 ; @todo fix memory variables for stackvm???! (or proper error)
|
memory ubyte[10] mba = $d000
|
||||||
mfarr[2] = 44.44 ; @todo fix memory variables for stackvm???! (or proper error)
|
memory word[10] mwa = $d100
|
||||||
|
memory float[10] mfa = $d200
|
||||||
farr[2] = 4.44
|
memory str mstr = $d300
|
||||||
farr[2] = f
|
memory str_p mstrp = $d300
|
||||||
farr[2] = mflt
|
memory str_s mstrs = $d300
|
||||||
farr[2] = farr[3]
|
memory str_ps mstrps = $d300
|
||||||
farr[2] = mfarr[3]
|
|
||||||
farr[Y] = 4.44
|
|
||||||
farr[Y] = f
|
|
||||||
farr[Y] = mflt
|
|
||||||
farr[Y] = farr[3]
|
|
||||||
farr[Y] = mfarr[3]
|
|
||||||
farr[i] = 4.44
|
|
||||||
farr[i] = f
|
|
||||||
farr[i] = mflt
|
|
||||||
farr[i] = farr[3]
|
|
||||||
farr[i] = mfarr[3]
|
|
||||||
|
|
||||||
|
mb = 5
|
||||||
|
mb = Y
|
||||||
|
mb = bv
|
||||||
|
mw = 22334
|
||||||
|
mw = wv
|
||||||
|
mf = 4.45
|
||||||
|
mf = fv
|
||||||
|
mba[9] = 5
|
||||||
|
mba[9] = Y
|
||||||
|
mba[9] = bv
|
||||||
|
mwa[9] = 22334
|
||||||
|
mwa[9] = wv
|
||||||
|
mfa[9] = 5.667
|
||||||
|
mfa[9] = fv
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -755,7 +755,7 @@ class AstChecker(private val namespace: INameScope,
|
|||||||
// check out of bounds
|
// check out of bounds
|
||||||
val index = (arrayIndexedExpression.arrayspec.x as? LiteralValue)?.asIntegerValue
|
val index = (arrayIndexedExpression.arrayspec.x as? LiteralValue)?.asIntegerValue
|
||||||
if(index!=null && (index<0 || index>=arraysize))
|
if(index!=null && (index<0 || index>=arraysize))
|
||||||
checkResult.add(ExpressionError("arrayspec index out of bounds", arrayIndexedExpression.arrayspec.position))
|
checkResult.add(ExpressionError("array index out of bounds", arrayIndexedExpression.arrayspec.position))
|
||||||
} else if(target.datatype in StringDatatypes) {
|
} else if(target.datatype in StringDatatypes) {
|
||||||
// check string lengths
|
// check string lengths
|
||||||
val heapId = (target.value as LiteralValue).heapId!!
|
val heapId = (target.value as LiteralValue).heapId!!
|
||||||
@ -896,9 +896,9 @@ class AstChecker(private val namespace: INameScope,
|
|||||||
return err("initializer arrayspec size mismatch (expecting $expectedSize, got $arraySize)")
|
return err("initializer arrayspec size mismatch (expecting $expectedSize, got $arraySize)")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return err("invalid byte arrayspec size, must be 1-256")
|
return err("invalid byte array size, must be 1-256")
|
||||||
}
|
}
|
||||||
return err("invalid byte arrayspec initialization value ${value.type}, expected $targetDt")
|
return err("invalid byte array initialization value ${value.type}, expected $targetDt")
|
||||||
}
|
}
|
||||||
DataType.ARRAY_UW, DataType.ARRAY_W -> {
|
DataType.ARRAY_UW, DataType.ARRAY_W -> {
|
||||||
// value may be either a single word, or a word arrayspec
|
// value may be either a single word, or a word arrayspec
|
||||||
|
@ -177,7 +177,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
|||||||
if(subroutine.isNotEmpty())
|
if(subroutine.isNotEmpty())
|
||||||
throw CompilerException("kernel subroutines (with memory address) can't have a body: $subroutine")
|
throw CompilerException("kernel subroutines (with memory address) can't have a body: $subroutine")
|
||||||
|
|
||||||
prog.symbolDef(subroutine.scopedname, subroutine.asmAddress)
|
prog.memoryPointer(subroutine.scopedname, subroutine.asmAddress, DataType.UBYTE) // the datatype is a bit of a dummy in this case
|
||||||
}
|
}
|
||||||
return super.process(subroutine)
|
return super.process(subroutine)
|
||||||
}
|
}
|
||||||
@ -555,9 +555,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
|||||||
}
|
}
|
||||||
is IdentifierReference -> translate(expr)
|
is IdentifierReference -> translate(expr)
|
||||||
is ArrayIndexedExpression -> translate(expr, false)
|
is ArrayIndexedExpression -> translate(expr, false)
|
||||||
is RangeExpr -> {
|
is RangeExpr -> throw CompilerException("it's not possible to just have a range expression that has to be translated")
|
||||||
TODO("TRANSLATE range $expr")
|
|
||||||
}
|
|
||||||
else -> {
|
else -> {
|
||||||
val lv = expr.constValue(namespace, heap) ?: throw CompilerException("constant expression required, not $expr")
|
val lv = expr.constValue(namespace, heap) ?: throw CompilerException("constant expression required, not $expr")
|
||||||
when(lv.type) {
|
when(lv.type) {
|
||||||
@ -800,59 +798,68 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
|||||||
val valueA: IExpression
|
val valueA: IExpression
|
||||||
val valueX: IExpression
|
val valueX: IExpression
|
||||||
val paramDt = arg.first.resultingDatatype(namespace, heap)
|
val paramDt = arg.first.resultingDatatype(namespace, heap)
|
||||||
if(paramDt==DataType.UBYTE) {
|
when (paramDt) {
|
||||||
valueA=arg.first
|
DataType.UBYTE -> {
|
||||||
valueX=LiteralValue.optimalInteger(0, callPosition)
|
valueA=arg.first
|
||||||
val assignA = Assignment(listOf(AssignTarget(Register.A, null, null, callPosition)), null, valueA, callPosition)
|
valueX=LiteralValue.optimalInteger(0, callPosition)
|
||||||
val assignX = Assignment(listOf(AssignTarget(Register.X, null, null, callPosition)), null, valueX, callPosition)
|
val assignA = Assignment(listOf(AssignTarget(Register.A, null, null, callPosition)), null, valueA, callPosition)
|
||||||
assignA.linkParents(arguments[0].parent)
|
val assignX = Assignment(listOf(AssignTarget(Register.X, null, null, callPosition)), null, valueX, callPosition)
|
||||||
assignX.linkParents(arguments[0].parent)
|
assignA.linkParents(arguments[0].parent)
|
||||||
translate(assignA)
|
assignX.linkParents(arguments[0].parent)
|
||||||
translate(assignX)
|
translate(assignA)
|
||||||
} else if(paramDt==DataType.UWORD) {
|
translate(assignX)
|
||||||
translate(arg.first)
|
}
|
||||||
prog.instr(Opcode.POP_REGAX_WORD)
|
DataType.UWORD -> {
|
||||||
} else
|
translate(arg.first)
|
||||||
TODO("pass parameter of type $paramDt in registers ${arg.second.registerOrPair}")
|
prog.instr(Opcode.POP_REGAX_WORD)
|
||||||
|
}
|
||||||
|
else -> TODO("pass parameter of type $paramDt in registers ${arg.second.registerOrPair}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
AY -> {
|
AY -> {
|
||||||
val valueA: IExpression
|
val valueA: IExpression
|
||||||
val valueY: IExpression
|
val valueY: IExpression
|
||||||
val paramDt = arg.first.resultingDatatype(namespace, heap)
|
val paramDt = arg.first.resultingDatatype(namespace, heap)
|
||||||
if(paramDt==DataType.UBYTE) {
|
when (paramDt) {
|
||||||
valueA=arg.first
|
DataType.UBYTE -> {
|
||||||
valueY=LiteralValue.optimalInteger(0, callPosition)
|
valueA=arg.first
|
||||||
val assignA = Assignment(listOf(AssignTarget(Register.A, null, null, callPosition)), null, valueA, callPosition)
|
valueY=LiteralValue.optimalInteger(0, callPosition)
|
||||||
val assignY = Assignment(listOf(AssignTarget(Register.Y, null, null, callPosition)), null, valueY, callPosition)
|
val assignA = Assignment(listOf(AssignTarget(Register.A, null, null, callPosition)), null, valueA, callPosition)
|
||||||
assignA.linkParents(arguments[0].parent)
|
val assignY = Assignment(listOf(AssignTarget(Register.Y, null, null, callPosition)), null, valueY, callPosition)
|
||||||
assignY.linkParents(arguments[0].parent)
|
assignA.linkParents(arguments[0].parent)
|
||||||
translate(assignA)
|
assignY.linkParents(arguments[0].parent)
|
||||||
translate(assignY)
|
translate(assignA)
|
||||||
} else if(paramDt==DataType.UWORD) {
|
translate(assignY)
|
||||||
translate(arg.first)
|
}
|
||||||
prog.instr(Opcode.POP_REGAY_WORD)
|
DataType.UWORD -> {
|
||||||
} else
|
translate(arg.first)
|
||||||
TODO("pass parameter of type $paramDt in registers ${arg.second.registerOrPair}")
|
prog.instr(Opcode.POP_REGAY_WORD)
|
||||||
|
}
|
||||||
|
else -> TODO("pass parameter of type $paramDt in registers ${arg.second.registerOrPair}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
XY -> {
|
XY -> {
|
||||||
// TODO: save X on stack & restore after call
|
// TODO: save X on stack & restore after call
|
||||||
val valueX: IExpression
|
val valueX: IExpression
|
||||||
val valueY: IExpression
|
val valueY: IExpression
|
||||||
val paramDt = arg.first.resultingDatatype(namespace, heap)
|
val paramDt = arg.first.resultingDatatype(namespace, heap)
|
||||||
if(paramDt==DataType.UBYTE) {
|
when (paramDt) {
|
||||||
valueX=arg.first
|
DataType.UBYTE -> {
|
||||||
valueY=LiteralValue.optimalInteger(0, callPosition)
|
valueX=arg.first
|
||||||
val assignX = Assignment(listOf(AssignTarget(Register.X, null, null, callPosition)), null, valueX, callPosition)
|
valueY=LiteralValue.optimalInteger(0, callPosition)
|
||||||
val assignY = Assignment(listOf(AssignTarget(Register.Y, null, null, callPosition)), null, valueY, callPosition)
|
val assignX = Assignment(listOf(AssignTarget(Register.X, null, null, callPosition)), null, valueX, callPosition)
|
||||||
assignX.linkParents(arguments[0].parent)
|
val assignY = Assignment(listOf(AssignTarget(Register.Y, null, null, callPosition)), null, valueY, callPosition)
|
||||||
assignY.linkParents(arguments[0].parent)
|
assignX.linkParents(arguments[0].parent)
|
||||||
translate(assignX)
|
assignY.linkParents(arguments[0].parent)
|
||||||
translate(assignY)
|
translate(assignX)
|
||||||
} else if(paramDt==DataType.UWORD) {
|
translate(assignY)
|
||||||
translate(arg.first)
|
}
|
||||||
prog.instr(Opcode.POP_REGXY_WORD)
|
DataType.UWORD -> {
|
||||||
} else
|
translate(arg.first)
|
||||||
TODO("pass parameter of type $paramDt in registers ${arg.second.registerOrPair}")
|
prog.instr(Opcode.POP_REGXY_WORD)
|
||||||
|
}
|
||||||
|
else -> TODO("pass parameter of type $paramDt in registers ${arg.second.registerOrPair}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1226,7 +1233,6 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
|||||||
else -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
|
else -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// todo: maybe if you assign byte or word to arrayspec, clear it with that value?
|
|
||||||
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
|
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
|
||||||
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W, DataType.ARRAY_F -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
|
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W, DataType.ARRAY_F -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
|
||||||
null -> throw CompilerException("could not determine targetdt")
|
null -> throw CompilerException("could not determine targetdt")
|
||||||
@ -1793,7 +1799,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
|||||||
val postIncr = PostIncrDecr(makeAssignmentTarget(), "--", range.position)
|
val postIncr = PostIncrDecr(makeAssignmentTarget(), "--", range.position)
|
||||||
postIncr.linkParents(range.parent)
|
postIncr.linkParents(range.parent)
|
||||||
translate(postIncr)
|
translate(postIncr)
|
||||||
TODO("signed numbers and/or special condition are needed for decreasing for loop. Try an increasing loop and/or constant loop values instead? At: ${range.position}")
|
TODO("signed numbers and/or special condition are needed for decreasing for loop. Try an increasing loop and/or constant loop values instead? At: ${range.position}") // fix with signed numbers
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
TODO("non-literal-const or other-than-one step increment code At: ${range.position}")
|
TODO("non-literal-const or other-than-one step increment code At: ${range.position}")
|
||||||
|
@ -13,7 +13,7 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
|
|||||||
var address: Int?,
|
var address: Int?,
|
||||||
val instructions: MutableList<Instruction> = mutableListOf(),
|
val instructions: MutableList<Instruction> = mutableListOf(),
|
||||||
val variables: MutableMap<String, Value> = mutableMapOf(),
|
val variables: MutableMap<String, Value> = mutableMapOf(),
|
||||||
val integerConstants: MutableMap<String, Int> = mutableMapOf(),
|
val memoryPointers: MutableMap<String, Pair<Int, DataType>> = mutableMapOf(),
|
||||||
val labels: MutableMap<String, Instruction> = mutableMapOf())
|
val labels: MutableMap<String, Instruction> = mutableMapOf())
|
||||||
{
|
{
|
||||||
val numVariables: Int
|
val numVariables: Int
|
||||||
@ -276,7 +276,10 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
|
|||||||
}
|
}
|
||||||
VarDeclType.CONST -> {} // constants are all folded away
|
VarDeclType.CONST -> {} // constants are all folded away
|
||||||
VarDeclType.MEMORY -> {
|
VarDeclType.MEMORY -> {
|
||||||
currentBlock.integerConstants[scopedname] = (decl.value as LiteralValue).asIntegerValue!!
|
val lv = decl.value as LiteralValue
|
||||||
|
if(lv.type!=DataType.UWORD && lv.type!=DataType.UBYTE)
|
||||||
|
throw CompilerException("expected integer memory address $lv")
|
||||||
|
currentBlock.memoryPointers[scopedname] = Pair(lv.asIntegerValue!!, decl.datatype)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -299,8 +302,8 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
|
|||||||
currentBlock.instructions.removeAt(currentBlock.instructions.lastIndex)
|
currentBlock.instructions.removeAt(currentBlock.instructions.lastIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun symbolDef(name: String, value: Int) {
|
fun memoryPointer(name: String, address: Int, datatype: DataType) {
|
||||||
currentBlock.integerConstants[name] = value
|
currentBlock.memoryPointers[name] = Pair(address, datatype)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun newBlock(scopedname: String, shortname: String, address: Int?) {
|
fun newBlock(scopedname: String, shortname: String, address: Int?) {
|
||||||
@ -337,6 +340,11 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
|
|||||||
out.println("${variable.key} ${variable.value.type.toString().toLowerCase()} $valuestr")
|
out.println("${variable.key} ${variable.value.type.toString().toLowerCase()} $valuestr")
|
||||||
}
|
}
|
||||||
out.println("%end_variables")
|
out.println("%end_variables")
|
||||||
|
out.println("%memorypointers")
|
||||||
|
for(iconst in blk.memoryPointers) {
|
||||||
|
out.println("${iconst.key} ${iconst.value.second.toString().toLowerCase()} uw:${iconst.value.first.toString(16)}")
|
||||||
|
}
|
||||||
|
out.println("%end_memorypointers")
|
||||||
out.println("%instructions")
|
out.println("%instructions")
|
||||||
val labels = blk.labels.entries.associateBy({it.value}) {it.key}
|
val labels = blk.labels.entries.associateBy({it.value}) {it.key}
|
||||||
for(instr in blk.instructions) {
|
for(instr in blk.instructions) {
|
||||||
|
@ -42,7 +42,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
|||||||
callLabel2 = if (it.callLabel2 != null) symname(it.callLabel2, block) else null)
|
callLabel2 = if (it.callLabel2 != null) symname(it.callLabel2, block) else null)
|
||||||
}
|
}
|
||||||
}.toMutableList()
|
}.toMutableList()
|
||||||
val newConstants = block.integerConstants.map { symname(it.key, block) to it.value }.toMap().toMutableMap()
|
val newConstants = block.memoryPointers.map { symname(it.key, block) to it.value }.toMap().toMutableMap()
|
||||||
newblocks.add(IntermediateProgram.ProgramBlock(
|
newblocks.add(IntermediateProgram.ProgramBlock(
|
||||||
block.scopedname,
|
block.scopedname,
|
||||||
block.shortname,
|
block.shortname,
|
||||||
@ -216,8 +216,8 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun memdefs2asm(block: IntermediateProgram.ProgramBlock) {
|
private fun memdefs2asm(block: IntermediateProgram.ProgramBlock) {
|
||||||
for(m in block.integerConstants) {
|
for(m in block.memoryPointers) {
|
||||||
out("\t${m.key} = ${m.value.toHex()}")
|
out("\t${m.key} = ${m.value.first.toHex()}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,10 +473,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Opcode.READ_INDEXED_VAR_BYTE -> {
|
Opcode.READ_INDEXED_VAR_BYTE -> {
|
||||||
TODO("$ins")
|
TODO("$ins") // byte[i]
|
||||||
}
|
}
|
||||||
Opcode.READ_INDEXED_VAR_WORD -> {
|
Opcode.READ_INDEXED_VAR_WORD -> {
|
||||||
TODO("$ins")
|
TODO("$ins") // word[i]
|
||||||
}
|
}
|
||||||
Opcode.READ_INDEXED_VAR_FLOAT -> {
|
Opcode.READ_INDEXED_VAR_FLOAT -> {
|
||||||
"""
|
"""
|
||||||
@ -486,10 +486,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
|||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
Opcode.WRITE_INDEXED_VAR_BYTE -> {
|
Opcode.WRITE_INDEXED_VAR_BYTE -> {
|
||||||
TODO("$ins")
|
TODO("$ins") // byte[i]=...
|
||||||
}
|
}
|
||||||
Opcode.WRITE_INDEXED_VAR_WORD -> {
|
Opcode.WRITE_INDEXED_VAR_WORD -> {
|
||||||
TODO("$ins")
|
TODO("$ins") // word[i]=...
|
||||||
}
|
}
|
||||||
Opcode.WRITE_INDEXED_VAR_FLOAT -> {
|
Opcode.WRITE_INDEXED_VAR_FLOAT -> {
|
||||||
"""
|
"""
|
||||||
|
@ -10,6 +10,7 @@ import java.util.regex.Pattern
|
|||||||
class Program (val name: String,
|
class Program (val name: String,
|
||||||
val program: MutableList<Instruction>,
|
val program: MutableList<Instruction>,
|
||||||
val variables: Map<String, Value>,
|
val variables: Map<String, Value>,
|
||||||
|
val memoryPointers: Map<String, Pair<Int, DataType>>,
|
||||||
val labels: Map<String, Instruction>,
|
val labels: Map<String, Instruction>,
|
||||||
val memory: Map<Int, List<Value>>,
|
val memory: Map<Int, List<Value>>,
|
||||||
val heap: HeapValues)
|
val heap: HeapValues)
|
||||||
@ -29,6 +30,7 @@ class Program (val name: String,
|
|||||||
val heap = HeapValues()
|
val heap = HeapValues()
|
||||||
val program = mutableListOf<Instruction>()
|
val program = mutableListOf<Instruction>()
|
||||||
val variables = mutableMapOf<String, Value>()
|
val variables = mutableMapOf<String, Value>()
|
||||||
|
val memoryPointers = mutableMapOf<String, Pair<Int, DataType>>()
|
||||||
val labels = mutableMapOf<String, Instruction>()
|
val labels = mutableMapOf<String, Instruction>()
|
||||||
|
|
||||||
while(lines.hasNext()) {
|
while(lines.hasNext()) {
|
||||||
@ -40,16 +42,17 @@ class Program (val name: String,
|
|||||||
else if(line=="%heap")
|
else if(line=="%heap")
|
||||||
loadHeap(lines, heap)
|
loadHeap(lines, heap)
|
||||||
else if(line.startsWith("%block "))
|
else if(line.startsWith("%block "))
|
||||||
loadBlock(lines, heap, program, variables, labels)
|
loadBlock(lines, heap, program, variables, memoryPointers, labels)
|
||||||
else throw VmExecutionException("syntax error at line ${lineNr + 1}")
|
else throw VmExecutionException("syntax error at line ${lineNr + 1}")
|
||||||
}
|
}
|
||||||
return Program(filename, program, variables, labels, memory, heap)
|
return Program(filename, program, variables, memoryPointers, labels, memory, heap)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadBlock(lines: Iterator<IndexedValue<String>>,
|
private fun loadBlock(lines: Iterator<IndexedValue<String>>,
|
||||||
heap: HeapValues,
|
heap: HeapValues,
|
||||||
program: MutableList<Instruction>,
|
program: MutableList<Instruction>,
|
||||||
variables: MutableMap<String, Value>,
|
variables: MutableMap<String, Value>,
|
||||||
|
memoryPointers: MutableMap<String, Pair<Int, DataType>>,
|
||||||
labels: MutableMap<String, Instruction>)
|
labels: MutableMap<String, Instruction>)
|
||||||
{
|
{
|
||||||
while(true) {
|
while(true) {
|
||||||
@ -60,6 +63,8 @@ class Program (val name: String,
|
|||||||
return
|
return
|
||||||
else if(line=="%variables")
|
else if(line=="%variables")
|
||||||
loadVars(lines, variables)
|
loadVars(lines, variables)
|
||||||
|
else if(line=="%memorypointers")
|
||||||
|
loadMemoryPointers(lines, memoryPointers, heap)
|
||||||
else if(line=="%instructions") {
|
else if(line=="%instructions") {
|
||||||
val (blockInstructions, blockLabels) = loadInstructions(lines, heap)
|
val (blockInstructions, blockLabels) = loadInstructions(lines, heap)
|
||||||
program.addAll(blockInstructions)
|
program.addAll(blockInstructions)
|
||||||
@ -177,12 +182,12 @@ class Program (val name: String,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun loadVars(lines: Iterator<IndexedValue<String>>,
|
private fun loadVars(lines: Iterator<IndexedValue<String>>,
|
||||||
vars: MutableMap<String, Value>): Map<String, Value> {
|
vars: MutableMap<String, Value>) {
|
||||||
val splitpattern = Pattern.compile("\\s+")
|
val splitpattern = Pattern.compile("\\s+")
|
||||||
while(true) {
|
while(true) {
|
||||||
val (_, line) = lines.next()
|
val (_, line) = lines.next()
|
||||||
if(line=="%end_variables")
|
if(line=="%end_variables")
|
||||||
return vars
|
return
|
||||||
val (name, typeStr, valueStr) = line.split(splitpattern, limit = 3)
|
val (name, typeStr, valueStr) = line.split(splitpattern, limit = 3)
|
||||||
if(valueStr[0] !='"' && ':' !in valueStr)
|
if(valueStr[0] !='"' && ':' !in valueStr)
|
||||||
throw VmExecutionException("missing value type character")
|
throw VmExecutionException("missing value type character")
|
||||||
@ -220,6 +225,23 @@ class Program (val name: String,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun loadMemoryPointers(lines: Iterator<IndexedValue<String>>,
|
||||||
|
pointers: MutableMap<String, Pair<Int, DataType>>,
|
||||||
|
heap: HeapValues) {
|
||||||
|
val splitpattern = Pattern.compile("\\s+")
|
||||||
|
while(true) {
|
||||||
|
val (_, line) = lines.next()
|
||||||
|
if(line=="%end_memorypointers")
|
||||||
|
return
|
||||||
|
val (name, typeStr, valueStr) = line.split(splitpattern, limit = 3)
|
||||||
|
if(valueStr[0] !='"' && ':' !in valueStr)
|
||||||
|
throw VmExecutionException("missing value type character")
|
||||||
|
val type = DataType.valueOf(typeStr.toUpperCase())
|
||||||
|
val value = getArgValue(valueStr, heap)!!.integerValue()
|
||||||
|
pointers[name] = Pair(value, type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun loadMemory(lines: Iterator<IndexedValue<String>>, memory: MutableMap<Int, List<Value>>): Map<Int, List<Value>> {
|
private fun loadMemory(lines: Iterator<IndexedValue<String>>, memory: MutableMap<Int, List<Value>>): Map<Int, List<Value>> {
|
||||||
while(true) {
|
while(true) {
|
||||||
val (lineNr, line) = lines.next()
|
val (lineNr, line) = lines.next()
|
||||||
|
@ -104,6 +104,8 @@ class StackVm(private var traceOutputFile: String?) {
|
|||||||
private set
|
private set
|
||||||
var variables = mutableMapOf<String, Value>() // all variables (set of all vars used by all blocks/subroutines) key = their fully scoped name
|
var variables = mutableMapOf<String, Value>() // all variables (set of all vars used by all blocks/subroutines) key = their fully scoped name
|
||||||
private set
|
private set
|
||||||
|
var memoryPointers = mutableMapOf<String, Pair<Int, DataType>>() // all named pointers
|
||||||
|
private set
|
||||||
var evalstack = MyStack<Value>()
|
var evalstack = MyStack<Value>()
|
||||||
private set
|
private set
|
||||||
var callstack = MyStack<Instruction>()
|
var callstack = MyStack<Instruction>()
|
||||||
@ -125,6 +127,7 @@ class StackVm(private var traceOutputFile: String?) {
|
|||||||
this.canvas = canvas
|
this.canvas = canvas
|
||||||
canvas?.requestFocusInWindow()
|
canvas?.requestFocusInWindow()
|
||||||
variables = program.variables.toMutableMap()
|
variables = program.variables.toMutableMap()
|
||||||
|
memoryPointers = program.memoryPointers.toMutableMap()
|
||||||
|
|
||||||
if("A" in variables || "X" in variables || "Y" in variables)
|
if("A" in variables || "X" in variables || "Y" in variables)
|
||||||
throw VmExecutionException("program contains variable(s) for the reserved registers A/X/Y")
|
throw VmExecutionException("program contains variable(s) for the reserved registers A/X/Y")
|
||||||
@ -218,6 +221,15 @@ class StackVm(private var traceOutputFile: String?) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun getVar(name: String): Value {
|
||||||
|
val result = variables[name]
|
||||||
|
if(result!=null)
|
||||||
|
return result
|
||||||
|
if(name in memoryPointers)
|
||||||
|
throw VmExecutionException("variable is memory-mapped: $name = ${memoryPointers[name]}")
|
||||||
|
throw VmExecutionException("unknown variable: $name")
|
||||||
|
}
|
||||||
|
|
||||||
private fun dispatch(ins: Instruction) : Instruction {
|
private fun dispatch(ins: Instruction) : Instruction {
|
||||||
traceOutput?.println("\n$ins")
|
traceOutput?.println("\n$ins")
|
||||||
when (ins.opcode) {
|
when (ins.opcode) {
|
||||||
@ -749,17 +761,17 @@ class StackVm(private var traceOutputFile: String?) {
|
|||||||
return callstack.pop()
|
return callstack.pop()
|
||||||
}
|
}
|
||||||
Opcode.PUSH_VAR_BYTE -> {
|
Opcode.PUSH_VAR_BYTE -> {
|
||||||
val value = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val value = getVar(ins.callLabel!!)
|
||||||
checkDt(value, DataType.UBYTE, DataType.BYTE)
|
checkDt(value, DataType.UBYTE, DataType.BYTE)
|
||||||
evalstack.push(value)
|
evalstack.push(value)
|
||||||
}
|
}
|
||||||
Opcode.PUSH_VAR_WORD -> {
|
Opcode.PUSH_VAR_WORD -> {
|
||||||
val value = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val value = getVar(ins.callLabel!!)
|
||||||
checkDt(value, *(setOf(DataType.UWORD, DataType.WORD) + IterableDatatypes).toTypedArray())
|
checkDt(value, *(setOf(DataType.UWORD, DataType.WORD) + IterableDatatypes).toTypedArray())
|
||||||
evalstack.push(value)
|
evalstack.push(value)
|
||||||
}
|
}
|
||||||
Opcode.PUSH_VAR_FLOAT -> {
|
Opcode.PUSH_VAR_FLOAT -> {
|
||||||
val value = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val value = getVar(ins.callLabel!!)
|
||||||
checkDt(value, DataType.FLOAT)
|
checkDt(value, DataType.FLOAT)
|
||||||
evalstack.push(value)
|
evalstack.push(value)
|
||||||
}
|
}
|
||||||
@ -796,145 +808,145 @@ class StackVm(private var traceOutputFile: String?) {
|
|||||||
Opcode.POP_VAR_BYTE -> {
|
Opcode.POP_VAR_BYTE -> {
|
||||||
val value = evalstack.pop()
|
val value = evalstack.pop()
|
||||||
checkDt(value, DataType.UBYTE, DataType.BYTE)
|
checkDt(value, DataType.UBYTE, DataType.BYTE)
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.UBYTE, DataType.BYTE)
|
checkDt(variable, DataType.UBYTE, DataType.BYTE)
|
||||||
if(value.type!=variable.type)
|
if(value.type!=variable.type)
|
||||||
throw VmExecutionException("datatype mismatch")
|
throw VmExecutionException("datatype mismatch")
|
||||||
variables[ins.callLabel!!] = value
|
variables[ins.callLabel] = value
|
||||||
}
|
}
|
||||||
Opcode.POP_VAR_WORD -> {
|
Opcode.POP_VAR_WORD -> {
|
||||||
val value = evalstack.pop()
|
val value = evalstack.pop()
|
||||||
checkDt(value, DataType.UWORD, DataType.WORD, DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS)
|
checkDt(value, DataType.UWORD, DataType.WORD, DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS)
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.UWORD, DataType.WORD, DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS)
|
checkDt(variable, DataType.UWORD, DataType.WORD, DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS)
|
||||||
if(value.type!=variable.type)
|
if(value.type!=variable.type)
|
||||||
throw VmExecutionException("datatype mismatch")
|
throw VmExecutionException("datatype mismatch")
|
||||||
variables[ins.callLabel!!] = value
|
variables[ins.callLabel] = value
|
||||||
}
|
}
|
||||||
Opcode.POP_VAR_FLOAT -> {
|
Opcode.POP_VAR_FLOAT -> {
|
||||||
val value = evalstack.pop()
|
val value = evalstack.pop()
|
||||||
checkDt(value, DataType.FLOAT)
|
checkDt(value, DataType.FLOAT)
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.FLOAT)
|
checkDt(variable, DataType.FLOAT)
|
||||||
variables[ins.callLabel!!] = value
|
variables[ins.callLabel] = value
|
||||||
}
|
}
|
||||||
Opcode.SHL_VAR_BYTE -> {
|
Opcode.SHL_VAR_BYTE -> {
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.UBYTE)
|
checkDt(variable, DataType.UBYTE)
|
||||||
variables[ins.callLabel!!] = variable.shl()
|
variables[ins.callLabel] =variable.shl()
|
||||||
}
|
}
|
||||||
Opcode.SHL_VAR_WORD -> {
|
Opcode.SHL_VAR_WORD -> {
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.UWORD)
|
checkDt(variable, DataType.UWORD)
|
||||||
variables[ins.callLabel!!] = variable.shl()
|
variables[ins.callLabel] =variable.shl()
|
||||||
}
|
}
|
||||||
Opcode.SHR_VAR_BYTE -> {
|
Opcode.SHR_VAR_BYTE -> {
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.UBYTE)
|
checkDt(variable, DataType.UBYTE)
|
||||||
variables[ins.callLabel!!] = variable.shr()
|
variables[ins.callLabel] =variable.shr()
|
||||||
}
|
}
|
||||||
Opcode.SHR_VAR_WORD -> {
|
Opcode.SHR_VAR_WORD -> {
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.UWORD)
|
checkDt(variable, DataType.UWORD)
|
||||||
variables[ins.callLabel!!] = variable.shr()
|
variables[ins.callLabel] =variable.shr()
|
||||||
}
|
}
|
||||||
Opcode.ROL_VAR_BYTE -> {
|
Opcode.ROL_VAR_BYTE -> {
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.UBYTE)
|
checkDt(variable, DataType.UBYTE)
|
||||||
val (newValue, newCarry) = variable.rol(P_carry)
|
val (newValue, newCarry) = variable.rol(P_carry)
|
||||||
variables[ins.callLabel!!] = newValue
|
variables[ins.callLabel] =newValue
|
||||||
P_carry = newCarry
|
P_carry = newCarry
|
||||||
}
|
}
|
||||||
Opcode.ROL_VAR_WORD -> {
|
Opcode.ROL_VAR_WORD -> {
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.UWORD)
|
checkDt(variable, DataType.UWORD)
|
||||||
val (newValue, newCarry) = variable.rol(P_carry)
|
val (newValue, newCarry) = variable.rol(P_carry)
|
||||||
variables[ins.callLabel!!] = newValue
|
variables[ins.callLabel] =newValue
|
||||||
P_carry = newCarry
|
P_carry = newCarry
|
||||||
}
|
}
|
||||||
Opcode.ROR_VAR_BYTE -> {
|
Opcode.ROR_VAR_BYTE -> {
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.UBYTE)
|
checkDt(variable, DataType.UBYTE)
|
||||||
val (newValue, newCarry) = variable.ror(P_carry)
|
val (newValue, newCarry) = variable.ror(P_carry)
|
||||||
variables[ins.callLabel!!] = newValue
|
variables[ins.callLabel] =newValue
|
||||||
P_carry = newCarry
|
P_carry = newCarry
|
||||||
}
|
}
|
||||||
Opcode.ROR_VAR_WORD -> {
|
Opcode.ROR_VAR_WORD -> {
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.UWORD)
|
checkDt(variable, DataType.UWORD)
|
||||||
val (newValue, newCarry) = variable.ror(P_carry)
|
val (newValue, newCarry) = variable.ror(P_carry)
|
||||||
variables[ins.callLabel!!] = newValue
|
variables[ins.callLabel] =newValue
|
||||||
P_carry = newCarry
|
P_carry = newCarry
|
||||||
}
|
}
|
||||||
Opcode.ROL2_VAR_BYTE -> {
|
Opcode.ROL2_VAR_BYTE -> {
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.UBYTE)
|
checkDt(variable, DataType.UBYTE)
|
||||||
variables[ins.callLabel!!] = variable.rol2()
|
variables[ins.callLabel] =variable.rol2()
|
||||||
}
|
}
|
||||||
Opcode.ROL2_VAR_WORD -> {
|
Opcode.ROL2_VAR_WORD -> {
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.UWORD)
|
checkDt(variable, DataType.UWORD)
|
||||||
variables[ins.callLabel!!] = variable.rol2()
|
variables[ins.callLabel] =variable.rol2()
|
||||||
}
|
}
|
||||||
Opcode.ROR2_VAR_BYTE -> {
|
Opcode.ROR2_VAR_BYTE -> {
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.UBYTE)
|
checkDt(variable, DataType.UBYTE)
|
||||||
variables[ins.callLabel!!] = variable.ror2()
|
variables[ins.callLabel] =variable.ror2()
|
||||||
}
|
}
|
||||||
Opcode.ROR2_VAR_WORD -> {
|
Opcode.ROR2_VAR_WORD -> {
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.UWORD)
|
checkDt(variable, DataType.UWORD)
|
||||||
variables[ins.callLabel!!] = variable.ror2()
|
variables[ins.callLabel] =variable.ror2()
|
||||||
}
|
}
|
||||||
Opcode.INC_VAR_UB -> {
|
Opcode.INC_VAR_UB -> {
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.UBYTE)
|
checkDt(variable, DataType.UBYTE)
|
||||||
variables[ins.callLabel!!] = variable.inc()
|
variables[ins.callLabel] =variable.inc()
|
||||||
}
|
}
|
||||||
Opcode.INC_VAR_B -> {
|
Opcode.INC_VAR_B -> {
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.BYTE)
|
checkDt(variable, DataType.BYTE)
|
||||||
variables[ins.callLabel!!] = variable.inc()
|
variables[ins.callLabel] =variable.inc()
|
||||||
}
|
}
|
||||||
Opcode.INC_VAR_UW -> {
|
Opcode.INC_VAR_UW -> {
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.UWORD)
|
checkDt(variable, DataType.UWORD)
|
||||||
variables[ins.callLabel!!] = variable.inc()
|
variables[ins.callLabel] =variable.inc()
|
||||||
}
|
}
|
||||||
Opcode.INC_VAR_W -> {
|
Opcode.INC_VAR_W -> {
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.WORD)
|
checkDt(variable, DataType.WORD)
|
||||||
variables[ins.callLabel!!] = variable.inc()
|
variables[ins.callLabel] =variable.inc()
|
||||||
}
|
}
|
||||||
Opcode.INC_VAR_F -> {
|
Opcode.INC_VAR_F -> {
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.FLOAT)
|
checkDt(variable, DataType.FLOAT)
|
||||||
variables[ins.callLabel!!] = variable.inc()
|
variables[ins.callLabel] =variable.inc()
|
||||||
}
|
}
|
||||||
Opcode.DEC_VAR_UB -> {
|
Opcode.DEC_VAR_UB -> {
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.UBYTE)
|
checkDt(variable, DataType.UBYTE)
|
||||||
variables[ins.callLabel!!] = variable.dec()
|
variables[ins.callLabel] =variable.dec()
|
||||||
}
|
}
|
||||||
Opcode.DEC_VAR_B -> {
|
Opcode.DEC_VAR_B -> {
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.BYTE)
|
checkDt(variable, DataType.BYTE)
|
||||||
variables[ins.callLabel!!] = variable.dec()
|
variables[ins.callLabel] =variable.dec()
|
||||||
}
|
}
|
||||||
Opcode.DEC_VAR_UW -> {
|
Opcode.DEC_VAR_UW -> {
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.UWORD)
|
checkDt(variable, DataType.UWORD)
|
||||||
variables[ins.callLabel!!] = variable.dec()
|
variables[ins.callLabel] =variable.dec()
|
||||||
}
|
}
|
||||||
Opcode.DEC_VAR_W -> {
|
Opcode.DEC_VAR_W -> {
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.WORD)
|
checkDt(variable, DataType.WORD)
|
||||||
variables[ins.callLabel!!] = variable.dec()
|
variables[ins.callLabel] =variable.dec()
|
||||||
}
|
}
|
||||||
Opcode.DEC_VAR_F -> {
|
Opcode.DEC_VAR_F -> {
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
checkDt(variable, DataType.FLOAT)
|
checkDt(variable, DataType.FLOAT)
|
||||||
variables[ins.callLabel!!] = variable.dec()
|
variables[ins.callLabel] =variable.dec()
|
||||||
}
|
}
|
||||||
Opcode.LSB -> {
|
Opcode.LSB -> {
|
||||||
val v = evalstack.pop()
|
val v = evalstack.pop()
|
||||||
@ -1194,7 +1206,7 @@ class StackVm(private var traceOutputFile: String?) {
|
|||||||
Opcode.READ_INDEXED_VAR_BYTE -> {
|
Opcode.READ_INDEXED_VAR_BYTE -> {
|
||||||
// put the byte value of variable[index] onto the stack
|
// put the byte value of variable[index] onto the stack
|
||||||
val index = evalstack.pop().integerValue()
|
val index = evalstack.pop().integerValue()
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
if(variable.type==DataType.UWORD) {
|
if(variable.type==DataType.UWORD) {
|
||||||
// assume the variable is a pointer (address) and get the ubyte value from that memory location
|
// assume the variable is a pointer (address) and get the ubyte value from that memory location
|
||||||
evalstack.push(Value(DataType.UBYTE, mem.getUByte(variable.integerValue())))
|
evalstack.push(Value(DataType.UBYTE, mem.getUByte(variable.integerValue())))
|
||||||
@ -1212,7 +1224,7 @@ class StackVm(private var traceOutputFile: String?) {
|
|||||||
Opcode.READ_INDEXED_VAR_WORD -> {
|
Opcode.READ_INDEXED_VAR_WORD -> {
|
||||||
// put the word value of variable[index] onto the stack
|
// put the word value of variable[index] onto the stack
|
||||||
val index = evalstack.pop().integerValue()
|
val index = evalstack.pop().integerValue()
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
if(variable.type==DataType.UWORD) {
|
if(variable.type==DataType.UWORD) {
|
||||||
// assume the variable is a pointer (address) and get the word value from that memory location
|
// assume the variable is a pointer (address) and get the word value from that memory location
|
||||||
evalstack.push(Value(DataType.UWORD, mem.getUWord(variable.integerValue())))
|
evalstack.push(Value(DataType.UWORD, mem.getUWord(variable.integerValue())))
|
||||||
@ -1229,7 +1241,7 @@ class StackVm(private var traceOutputFile: String?) {
|
|||||||
Opcode.READ_INDEXED_VAR_FLOAT -> {
|
Opcode.READ_INDEXED_VAR_FLOAT -> {
|
||||||
// put the f;pat value of variable[index] onto the stack
|
// put the f;pat value of variable[index] onto the stack
|
||||||
val index = evalstack.pop().integerValue()
|
val index = evalstack.pop().integerValue()
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val variable = getVar(ins.callLabel!!)
|
||||||
if(variable.type==DataType.UWORD) {
|
if(variable.type==DataType.UWORD) {
|
||||||
// assume the variable is a pointer (address) and get the float value from that memory location
|
// assume the variable is a pointer (address) and get the float value from that memory location
|
||||||
evalstack.push(Value(DataType.UWORD, mem.getFloat(variable.integerValue())))
|
evalstack.push(Value(DataType.UWORD, mem.getFloat(variable.integerValue())))
|
||||||
@ -1246,25 +1258,44 @@ class StackVm(private var traceOutputFile: String?) {
|
|||||||
val index = evalstack.pop().integerValue()
|
val index = evalstack.pop().integerValue()
|
||||||
val value = evalstack.pop()
|
val value = evalstack.pop()
|
||||||
checkDt(value, DataType.UBYTE, DataType.BYTE)
|
checkDt(value, DataType.UBYTE, DataType.BYTE)
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val varname = ins.callLabel!!
|
||||||
if(variable.type==DataType.UWORD) {
|
val memloc = memoryPointers[varname]
|
||||||
// assume the variable is a pointer (address) and write the byte value to that memory location
|
if(memloc!=null) {
|
||||||
mem.setUByte(variable.integerValue(), value.integerValue().toShort())
|
// variable is the name of a pointer, write the byte value to that memory location
|
||||||
|
if(value.type==DataType.UBYTE) {
|
||||||
|
if(memloc.second!=DataType.ARRAY_UB)
|
||||||
|
throw VmExecutionException("invalid memory pointer type $memloc")
|
||||||
|
mem.setUByte(memloc.first, value.integerValue().toShort())
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(memloc.second!=DataType.ARRAY_B)
|
||||||
|
throw VmExecutionException("invalid memory pointer type $memloc")
|
||||||
|
mem.setSByte(memloc.first, value.integerValue().toShort())
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// set indexed byte element in the arrayspec
|
val variable = getVar(varname)
|
||||||
val array = heap.get(variable.heapId)
|
if (variable.type == DataType.UWORD) {
|
||||||
when(array.type) {
|
// assume the variable is a pointer (address) and write the byte value to that memory location
|
||||||
DataType.ARRAY_UB -> array.array!![index] = value.integerValue()
|
if(value.type==DataType.UBYTE)
|
||||||
DataType.ARRAY_B -> array.array!![index] = value.integerValue()
|
mem.setUByte(variable.integerValue(), value.integerValue().toShort())
|
||||||
DataType.STR,
|
else
|
||||||
DataType.STR_P,
|
mem.setSByte(variable.integerValue(), value.integerValue().toShort())
|
||||||
DataType.STR_S,
|
} else {
|
||||||
DataType.STR_PS -> {
|
// set indexed byte element in the arrayspec
|
||||||
val chars = array.str!!.toCharArray()
|
val array = heap.get(variable.heapId)
|
||||||
chars[index] = Petscii.decodePetscii(listOf(value.integerValue().toShort()), true)[0]
|
when (array.type) {
|
||||||
heap.update(variable.heapId, chars.joinToString(""))
|
DataType.ARRAY_UB -> array.array!![index] = value.integerValue()
|
||||||
|
DataType.ARRAY_B -> array.array!![index] = value.integerValue()
|
||||||
|
DataType.STR,
|
||||||
|
DataType.STR_P,
|
||||||
|
DataType.STR_S,
|
||||||
|
DataType.STR_PS -> {
|
||||||
|
val chars = array.str!!.toCharArray()
|
||||||
|
chars[index] = Petscii.decodePetscii(listOf(value.integerValue().toShort()), true)[0]
|
||||||
|
heap.update(variable.heapId, chars.joinToString(""))
|
||||||
|
}
|
||||||
|
else -> throw VmExecutionException("not a proper array/string var with byte elements")
|
||||||
}
|
}
|
||||||
else -> throw VmExecutionException("not a proper array/string var with byte elements")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1273,19 +1304,37 @@ class StackVm(private var traceOutputFile: String?) {
|
|||||||
val index = evalstack.pop().integerValue()
|
val index = evalstack.pop().integerValue()
|
||||||
val value = evalstack.pop()
|
val value = evalstack.pop()
|
||||||
checkDt(value, DataType.UWORD, DataType.WORD)
|
checkDt(value, DataType.UWORD, DataType.WORD)
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val varname = ins.callLabel!!
|
||||||
if(variable.type==DataType.UWORD) {
|
val memloc = memoryPointers[varname]
|
||||||
// assume the variable is a pointer (address) and write the word value to that memory location
|
if(memloc!=null) {
|
||||||
mem.setUWord(variable.integerValue(), value.integerValue())
|
// variable is the name of a pointer, write the word value to that memory location
|
||||||
} else {
|
if(value.type==DataType.UWORD) {
|
||||||
// set indexed word element in the arrayspec
|
if(memloc.second!=DataType.ARRAY_UW)
|
||||||
val array = heap.get(variable.heapId)
|
throw VmExecutionException("invalid memory pointer type $memloc")
|
||||||
when(array.type) {
|
mem.setUWord(memloc.first, value.integerValue())
|
||||||
DataType.ARRAY_UW -> array.array!![index] = value.integerValue()
|
}
|
||||||
DataType.ARRAY_W -> array.array!![index] = value.integerValue()
|
else {
|
||||||
else -> throw VmExecutionException("not a proper arrayspec var with word elements")
|
if(memloc.second!=DataType.ARRAY_W)
|
||||||
|
throw VmExecutionException("invalid memory pointer type $memloc")
|
||||||
|
mem.setSWord(memloc.first, value.integerValue())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val variable = getVar(varname)
|
||||||
|
if (variable.type == DataType.UWORD) {
|
||||||
|
// assume the variable is a pointer (address) and write the word value to that memory location
|
||||||
|
if(value.type==DataType.UWORD)
|
||||||
|
mem.setUWord(variable.integerValue(), value.integerValue())
|
||||||
|
else
|
||||||
|
mem.setSWord(variable.integerValue(), value.integerValue())
|
||||||
|
} else {
|
||||||
|
// set indexed word element in the arrayspec
|
||||||
|
val array = heap.get(variable.heapId)
|
||||||
|
when (array.type) {
|
||||||
|
DataType.ARRAY_UW -> array.array!![index] = value.integerValue()
|
||||||
|
DataType.ARRAY_W -> array.array!![index] = value.integerValue()
|
||||||
|
else -> throw VmExecutionException("not a proper arrayspec var with word elements")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Opcode.WRITE_INDEXED_VAR_FLOAT -> {
|
Opcode.WRITE_INDEXED_VAR_FLOAT -> {
|
||||||
@ -1293,16 +1342,25 @@ class StackVm(private var traceOutputFile: String?) {
|
|||||||
val index = evalstack.pop().integerValue()
|
val index = evalstack.pop().integerValue()
|
||||||
val value = evalstack.pop()
|
val value = evalstack.pop()
|
||||||
checkDt(value, DataType.FLOAT)
|
checkDt(value, DataType.FLOAT)
|
||||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
val varname = ins.callLabel!!
|
||||||
if(variable.type==DataType.UWORD) {
|
val memloc = memoryPointers[varname]
|
||||||
// assume the variable is a pointer (address) and write the float value to that memory location
|
if(memloc!=null) {
|
||||||
mem.setFloat(variable.integerValue(), value.numericValue().toDouble())
|
// variable is the name of a pointer, write the float value to that memory location
|
||||||
|
if(memloc.second!=DataType.ARRAY_F)
|
||||||
|
throw VmExecutionException("invalid memory pointer type $memloc")
|
||||||
|
mem.setFloat(memloc.first, value.numericValue().toDouble())
|
||||||
} else {
|
} else {
|
||||||
// set indexed float element in the arrayspec
|
val variable = getVar(varname)
|
||||||
val array = heap.get(variable.heapId)
|
if (variable.type == DataType.UWORD) {
|
||||||
if(array.type!=DataType.ARRAY_F)
|
// assume the variable is a pointer (address) and write the float value to that memory location
|
||||||
throw VmExecutionException("not a proper arrayspec var with float elements")
|
mem.setFloat(variable.integerValue(), value.numericValue().toDouble())
|
||||||
array.doubleArray!![index] = value.numericValue().toDouble()
|
} else {
|
||||||
|
// set indexed float element in the arrayspec
|
||||||
|
val array = heap.get(variable.heapId)
|
||||||
|
if (array.type != DataType.ARRAY_F)
|
||||||
|
throw VmExecutionException("not a proper arrayspec var with float elements")
|
||||||
|
array.doubleArray!![index] = value.numericValue().toDouble()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Opcode.RSAVE -> {
|
Opcode.RSAVE -> {
|
||||||
|
@ -51,12 +51,13 @@ class TestStackVmOpcodes {
|
|||||||
|
|
||||||
private val vm = StackVm(null)
|
private val vm = StackVm(null)
|
||||||
|
|
||||||
fun makeProg(ins: MutableList<Instruction>,
|
private fun makeProg(ins: MutableList<Instruction>,
|
||||||
vars: Map<String, Value>?=null,
|
vars: Map<String, Value>?=null,
|
||||||
|
memoryPointers: Map<String, Pair<Int, DataType>>?=null,
|
||||||
labels: Map<String, Instruction>?=null,
|
labels: Map<String, Instruction>?=null,
|
||||||
mem: Map<Int, List<Value>>?=null) : Program {
|
mem: Map<Int, List<Value>>?=null) : Program {
|
||||||
val heap = HeapValues()
|
val heap = HeapValues()
|
||||||
return Program("test", ins, vars ?: mapOf(), labels ?: mapOf(), mem ?: mapOf(), heap)
|
return Program("test", ins, vars ?: mapOf(), memoryPointers ?: mapOf(), labels ?: mapOf(), mem ?: mapOf(), heap)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -46,9 +46,15 @@ w2float
|
|||||||
push_float
|
push_float
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
push_float_from_indexed_var
|
||||||
|
rts
|
||||||
|
|
||||||
pop_var_float
|
pop_var_float
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
pop_float_to_indexed_var
|
||||||
|
rts
|
||||||
|
|
||||||
pop_mem_float
|
pop_mem_float
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user