mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 16:29:21 +00:00
assignment to array-indexed
This commit is contained in:
parent
38e7d48492
commit
af0d52b5c2
@ -117,6 +117,7 @@ assign_target:
|
||||
register
|
||||
| identifier
|
||||
| scoped_identifier
|
||||
| arrayindexed
|
||||
;
|
||||
|
||||
postincrdecr : assign_target operator = ('++' | '--') ;
|
||||
|
@ -16,81 +16,61 @@
|
||||
const word width = 320
|
||||
const word height = 200
|
||||
|
||||
float x1 = -1.0
|
||||
float y1 = 1.0
|
||||
float[6] xcoor = [-1.0, 1.0, 1.0, 0.5, 0.2, -1.0]
|
||||
float[6] ycoor = [1.0, 1.0, -1.0, -0.3, -0.6, -1.0]
|
||||
|
||||
float x2 = 1.0
|
||||
float y2 = 1.0
|
||||
|
||||
float x3 = 1.0
|
||||
float y3 = -1.0
|
||||
|
||||
float x4 = -1.0
|
||||
float y4 = -1.0
|
||||
|
||||
|
||||
float rx1
|
||||
float rx2
|
||||
float rx3
|
||||
float rx4
|
||||
float ry1
|
||||
float ry2
|
||||
float ry3
|
||||
float ry4
|
||||
float[len(xcoor)] rotatedx
|
||||
float[len(ycoor)] rotatedy
|
||||
|
||||
sub start() {
|
||||
float t
|
||||
_vm_gfx_clearscr(0)
|
||||
byte i
|
||||
|
||||
while(1) {
|
||||
if irq.time_changed {
|
||||
irq.time_changed = 0
|
||||
_vm_gfx_clearscr(0)
|
||||
_vm_gfx_text(130, 80, 5, "Spin !!!")
|
||||
t = flt(irq.global_time) / 60.0
|
||||
rotate_all(t)
|
||||
plot_pixels()
|
||||
_vm_gfx_text(120, 40, 5, "Spin to Win !!!")
|
||||
|
||||
for i in 0 to width//10 {
|
||||
_vm_gfx_line(i*2+100, 100, i*10, 199, 6)
|
||||
}
|
||||
|
||||
rotate_points(flt(irq.global_time) / 30.0)
|
||||
draw_lines()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub rotate_all(t: float) {
|
||||
rx1 = x1 * cos(t) - y1 * sin(t)
|
||||
ry1 = x1 * sin(t) + y1 * cos(t)
|
||||
sub rotate_points(t: float) {
|
||||
|
||||
rx2 = x2 * cos(t) - y2 * sin(t)
|
||||
ry2 = x2 * sin(t) + y2 * cos(t)
|
||||
; rotate around origin (0,0) and zoom a bit
|
||||
byte i
|
||||
float zoom
|
||||
zoom = (0.6 + sin(t*1.4)/2.2)
|
||||
|
||||
rx3 = x3 * cos(t) - y3 * sin(t)
|
||||
ry3 = x3 * sin(t) + y3 * cos(t)
|
||||
|
||||
rx4 = x4 * cos(t) - y4 * sin(t)
|
||||
ry4 = x4 * sin(t) + y4 * cos(t)
|
||||
for i in 0 to len(xcoor)-1 {
|
||||
rotatedx[i] = xcoor[i] * cos(t) - ycoor[i] * sin(t)
|
||||
rotatedy[i] = xcoor[i] * sin(t) + ycoor[i] * cos(t)
|
||||
rotatedx[i] *= zoom
|
||||
rotatedy[i] *= zoom
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub plot_pixels() {
|
||||
word sx1
|
||||
word sx2
|
||||
word sx3
|
||||
word sx4
|
||||
word sy1
|
||||
word sy2
|
||||
word sy3
|
||||
word sy4
|
||||
sub draw_lines() {
|
||||
byte i
|
||||
|
||||
sx1 = floor(rx1 * height/3 + width/2)
|
||||
sx2 = floor(rx2 * height/3 + width/2)
|
||||
sx3 = floor(rx3 * height/3 + width/2)
|
||||
sx4 = floor(rx4 * height/3 + width/2)
|
||||
sy1 = floor(ry1 * height/3 + height/2)
|
||||
sy2 = floor(ry2 * height/3 + height/2)
|
||||
sy3 = floor(ry3 * height/3 + height/2)
|
||||
sy4 = floor(ry4 * height/3 + height/2)
|
||||
sub toscreenx(x: float) -> word {
|
||||
return floor(x * height/3 + width /2)
|
||||
}
|
||||
|
||||
_vm_gfx_line(sx1, sy1, sx2, sy2, 1)
|
||||
_vm_gfx_line(sx2, sy2, sx3, sy3, 7)
|
||||
_vm_gfx_line(sx3, sy3, sx4, sy4, 10)
|
||||
_vm_gfx_line(sx4, sy4, sx1, sy1, 14)
|
||||
sub toscreeny(y: float) -> word {
|
||||
return floor(y * height/3 + height /2)
|
||||
}
|
||||
|
||||
for i in 0 to len(xcoor)-2 {
|
||||
_vm_gfx_line(toscreenx(rotatedx[i]), toscreeny(rotatedy[i]), toscreenx(rotatedx[i+1]), toscreeny(rotatedy[i+1]), i+7)
|
||||
}
|
||||
_vm_gfx_line(toscreenx(rotatedx[len(xcoor)-1]), toscreeny(rotatedy[len(xcoor)-1]), toscreenx(rotatedx[0]), toscreeny(rotatedy[0]), 14)
|
||||
}
|
||||
}
|
||||
|
@ -27,30 +27,36 @@ sub start() {
|
||||
byte i
|
||||
word w
|
||||
|
||||
for i in 0 to 2 {
|
||||
_vm_write_num(farray5[i])
|
||||
_vm_write_char('\n')
|
||||
}
|
||||
;warray3[1] = warray3[1] + 1
|
||||
warray3[1] += 1
|
||||
;warray3[1] ++
|
||||
|
||||
for w in [1,2,3777] { ;@todo loop over array literal
|
||||
_vm_write_num(w)
|
||||
_vm_write_char('\n')
|
||||
}
|
||||
|
||||
for i in barray3 { ; @todo loop over symbol
|
||||
_vm_write_num(i)
|
||||
_vm_write_char('\n')
|
||||
}
|
||||
|
||||
for i in "hello" { ; @todo loop over string
|
||||
_vm_write_num(i)
|
||||
_vm_write_char('\n')
|
||||
}
|
||||
; for i in 0 to 2 {
|
||||
; _vm_write_num(farray5[i])
|
||||
; _vm_write_char('\n')
|
||||
; }
|
||||
|
||||
for w in "hello" { ; @todo loop over string
|
||||
_vm_write_num(w)
|
||||
_vm_write_char('\n')
|
||||
}
|
||||
; for w in [1,2,3777] { ;@todo loop over array literal
|
||||
; _vm_write_num(w)
|
||||
; _vm_write_char('\n')
|
||||
; }
|
||||
;
|
||||
; for i in barray3 { ; @todo loop over symbol
|
||||
; _vm_write_num(i)
|
||||
; _vm_write_char('\n')
|
||||
; }
|
||||
;
|
||||
; for i in "hello" { ; @todo loop over string
|
||||
; _vm_write_num(i)
|
||||
; _vm_write_char('\n')
|
||||
; }
|
||||
;
|
||||
; for w in "hello" { ; @todo loop over string
|
||||
; _vm_write_num(w)
|
||||
; _vm_write_char('\n')
|
||||
; }
|
||||
|
||||
return
|
||||
|
||||
|
@ -226,6 +226,12 @@ interface IAstProcessor {
|
||||
arrayIndexedExpression.array.process(this)
|
||||
return arrayIndexedExpression
|
||||
}
|
||||
|
||||
fun process(assignTarget: AssignTarget): AssignTarget {
|
||||
assignTarget.arrayindexed?.process(this)
|
||||
assignTarget.identifier?.process(this)
|
||||
return assignTarget
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -674,25 +680,39 @@ class Assignment(var target: AssignTarget, val aug_op : String?, var value: IExp
|
||||
}
|
||||
}
|
||||
|
||||
data class AssignTarget(val register: Register?, val identifier: IdentifierReference?, override val position: Position) : Node {
|
||||
data class AssignTarget(val register: Register?,
|
||||
val identifier: IdentifierReference?,
|
||||
val arrayindexed: ArrayIndexedExpression?,
|
||||
override val position: Position) : Node {
|
||||
override lateinit var parent: Node
|
||||
|
||||
override fun linkParents(parent: Node) {
|
||||
this.parent = parent
|
||||
identifier?.linkParents(this)
|
||||
arrayindexed?.linkParents(this)
|
||||
}
|
||||
|
||||
fun process(processor: IAstProcessor) = this
|
||||
fun process(processor: IAstProcessor) = processor.process(this)
|
||||
|
||||
fun determineDatatype(namespace: INameScope, stmt: IStatement): DataType {
|
||||
fun determineDatatype(namespace: INameScope, heap: HeapValues, stmt: IStatement): DataType {
|
||||
if(register!=null)
|
||||
return when(register){
|
||||
Register.A, Register.X, Register.Y -> DataType.BYTE
|
||||
Register.AX, Register.AY, Register.XY -> DataType.WORD
|
||||
}
|
||||
|
||||
val symbol = namespace.lookup(identifier!!.nameInSource, stmt) ?: throw FatalAstException("symbol lookup failed: ${identifier.nameInSource}")
|
||||
if(symbol is VarDecl) return symbol.datatype
|
||||
if(identifier!=null) {
|
||||
val symbol = namespace.lookup(identifier.nameInSource, stmt)
|
||||
?: throw FatalAstException("symbol lookup failed: ${identifier.nameInSource}")
|
||||
if (symbol is VarDecl) return symbol.datatype
|
||||
}
|
||||
|
||||
if(arrayindexed!=null) {
|
||||
val dt = arrayindexed.resultingDatatype(namespace, heap)
|
||||
if(dt!=null)
|
||||
return dt
|
||||
}
|
||||
|
||||
throw FatalAstException("cannot determine datatype of assignment target $this")
|
||||
}
|
||||
}
|
||||
@ -1685,10 +1705,12 @@ private fun prog8Parser.Sub_paramsContext.toAst(): List<SubroutineParameter> =
|
||||
private fun prog8Parser.Assign_targetContext.toAst() : AssignTarget {
|
||||
val register = register()?.toAst()
|
||||
val identifier = identifier()
|
||||
return if(identifier!=null)
|
||||
AssignTarget(register, identifier.toAst(), toPosition())
|
||||
else
|
||||
AssignTarget(register, scoped_identifier()?.toAst(), toPosition())
|
||||
return when {
|
||||
register!=null -> AssignTarget(register, null, null, toPosition())
|
||||
identifier!=null -> AssignTarget(null, identifier.toAst(), null, toPosition())
|
||||
arrayindexed()!=null -> AssignTarget(null, null, arrayindexed().toAst(), toPosition())
|
||||
else -> AssignTarget(null, scoped_identifier()?.toAst(), null, toPosition())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1810,7 +1832,7 @@ private fun prog8Parser.ExpressionContext.toAst() : IExpression {
|
||||
throw FatalAstException(text)
|
||||
}
|
||||
|
||||
private fun prog8Parser.ArrayindexedContext.toAst(): IExpression {
|
||||
private fun prog8Parser.ArrayindexedContext.toAst(): ArrayIndexedExpression {
|
||||
return ArrayIndexedExpression(identifier()?.toAst() ?: scoped_identifier()?.toAst(),
|
||||
register()?.toAst(),
|
||||
arrayspec().toAst(),
|
||||
|
@ -251,6 +251,8 @@ class AstChecker(private val namespace: INameScope,
|
||||
* Also check data type compatibility
|
||||
*/
|
||||
override fun process(assignment: Assignment): IStatement {
|
||||
// todo deal with target.arrayindexed
|
||||
|
||||
if(assignment.target.identifier!=null) {
|
||||
val targetName = assignment.target.identifier!!.nameInSource
|
||||
val targetSymbol = namespace.lookup(targetName, assignment)
|
||||
@ -276,8 +278,13 @@ class AstChecker(private val namespace: INameScope,
|
||||
val target: IExpression =
|
||||
if(assignment.target.register!=null)
|
||||
RegisterExpr(assignment.target.register!!, assignment.target.position)
|
||||
else
|
||||
else if(assignment.target.identifier!=null)
|
||||
assignment.target.identifier!!
|
||||
else if(assignment.target.arrayindexed!=null) {
|
||||
// todo deal with target.arrayindexed
|
||||
assignment.target.arrayindexed!!
|
||||
} else throw FatalAstException("strange assignment")
|
||||
|
||||
val expression = BinaryExpression(target, assignment.aug_op.substringBeforeLast('='), assignment.value, assignment.position)
|
||||
expression.linkParents(assignment.parent)
|
||||
val assignment2 = Assignment(assignment.target, null, expression, assignment.position)
|
||||
@ -285,7 +292,7 @@ class AstChecker(private val namespace: INameScope,
|
||||
return process(assignment2)
|
||||
}
|
||||
|
||||
val targetDatatype = assignment.target.determineDatatype(namespace, assignment)
|
||||
val targetDatatype = assignment.target.determineDatatype(namespace, heap, assignment)
|
||||
val constVal = assignment.value.constValue(namespace, heap)
|
||||
if(constVal!=null) {
|
||||
checkValueTypeAndRange(targetDatatype, null, constVal, heap)
|
||||
@ -550,7 +557,7 @@ class AstChecker(private val namespace: INameScope,
|
||||
}
|
||||
|
||||
override fun process(postIncrDecr: PostIncrDecr): IStatement {
|
||||
if(postIncrDecr.target.register==null) {
|
||||
if(postIncrDecr.target.identifier!=null) {
|
||||
val targetName = postIncrDecr.target.identifier!!.nameInSource
|
||||
val target = namespace.lookup(targetName, postIncrDecr)
|
||||
if(target==null) {
|
||||
@ -562,6 +569,8 @@ class AstChecker(private val namespace: INameScope,
|
||||
checkResult.add(SyntaxError("can only increment or decrement a byte/float/word variable", postIncrDecr.position))
|
||||
}
|
||||
}
|
||||
} else if(postIncrDecr.target.arrayindexed!=null) {
|
||||
// todo deal with target.arrayindexed
|
||||
}
|
||||
return super.process(postIncrDecr)
|
||||
}
|
||||
|
@ -444,7 +444,7 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
|
||||
}
|
||||
}
|
||||
is IdentifierReference -> translate(expr)
|
||||
is ArrayIndexedExpression -> translate(expr)
|
||||
is ArrayIndexedExpression -> translate(expr, false)
|
||||
is RangeExpr -> {
|
||||
TODO("TRANSLATE range $expr")
|
||||
}
|
||||
@ -592,7 +592,7 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
|
||||
stackvmProg.instr(opcode)
|
||||
}
|
||||
|
||||
private fun translate(arrayindexed: ArrayIndexedExpression) {
|
||||
private fun translate(arrayindexed: ArrayIndexedExpression, write: Boolean) {
|
||||
val variable = arrayindexed.identifier?.targetStatement(namespace) as? VarDecl
|
||||
val variableName =
|
||||
if(arrayindexed.register!=null) {
|
||||
@ -615,7 +615,11 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
|
||||
stackvmProg.instr(Opcode.MUL)
|
||||
stackvmProg.instr(Opcode.ADD)
|
||||
}
|
||||
stackvmProg.instr(Opcode.PUSH_INDEXED_VAR, callLabel = variableName)
|
||||
|
||||
if(write)
|
||||
stackvmProg.instr(Opcode.WRITE_INDEXED_VAR, callLabel = variableName)
|
||||
else
|
||||
stackvmProg.instr(Opcode.READ_INDEXED_VAR, callLabel = variableName)
|
||||
}
|
||||
|
||||
|
||||
@ -652,17 +656,29 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
|
||||
|
||||
private fun translate(stmt: PostIncrDecr) {
|
||||
stackvmProg.line(stmt.position)
|
||||
if(stmt.target.register!=null) {
|
||||
when(stmt.operator) {
|
||||
when {
|
||||
stmt.target.register!=null -> when(stmt.operator) {
|
||||
"++" -> stackvmProg.instr(Opcode.INC_VAR, callLabel = stmt.target.register.toString())
|
||||
"--" -> stackvmProg.instr(Opcode.DEC_VAR, callLabel = stmt.target.register.toString())
|
||||
}
|
||||
} else {
|
||||
val targetStatement = stmt.target.identifier!!.targetStatement(namespace) as VarDecl
|
||||
when(stmt.operator) {
|
||||
"++" -> stackvmProg.instr(Opcode.INC_VAR, callLabel = targetStatement.scopedname)
|
||||
"--" -> stackvmProg.instr(Opcode.DEC_VAR, callLabel = targetStatement.scopedname)
|
||||
stmt.target.identifier!=null -> {
|
||||
val targetStatement = stmt.target.identifier!!.targetStatement(namespace) as VarDecl
|
||||
when(stmt.operator) {
|
||||
"++" -> stackvmProg.instr(Opcode.INC_VAR, callLabel = targetStatement.scopedname)
|
||||
"--" -> stackvmProg.instr(Opcode.DEC_VAR, callLabel = targetStatement.scopedname)
|
||||
}
|
||||
}
|
||||
stmt.target.arrayindexed!=null -> {
|
||||
// todo: generate more efficient bytecode for this?
|
||||
translate(stmt.target.arrayindexed!!, false)
|
||||
stackvmProg.instr(Opcode.PUSH, Value(stmt.target.arrayindexed!!.resultingDatatype(namespace, heap)!!, 1))
|
||||
when(stmt.operator) {
|
||||
"++" -> stackvmProg.instr(Opcode.ADD)
|
||||
"--" -> stackvmProg.instr(Opcode.SUB)
|
||||
}
|
||||
translate(stmt.target.arrayindexed!!, true)
|
||||
}
|
||||
else -> throw CompilerException("very strange postincrdecr")
|
||||
}
|
||||
}
|
||||
|
||||
@ -670,7 +686,7 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
|
||||
stackvmProg.line(stmt.position)
|
||||
translate(stmt.value)
|
||||
val valueDt = stmt.value.resultingDatatype(namespace, heap)
|
||||
val targetDt = stmt.target.determineDatatype(namespace, stmt)
|
||||
val targetDt = stmt.target.determineDatatype(namespace, heap, stmt)
|
||||
if(valueDt!=targetDt) {
|
||||
// convert value to target datatype if possible
|
||||
when(targetDt) {
|
||||
@ -696,27 +712,32 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
|
||||
|
||||
if(stmt.aug_op!=null) {
|
||||
// augmented assignment
|
||||
if(stmt.target.identifier!=null) {
|
||||
val target = stmt.target.identifier!!.targetStatement(namespace)!!
|
||||
when(target) {
|
||||
is VarDecl -> stackvmProg.instr(Opcode.PUSH_VAR, callLabel = target.scopedname)
|
||||
else -> throw CompilerException("invalid assignment target type ${target::class}")
|
||||
when {
|
||||
stmt.target.identifier!=null -> {
|
||||
val target = stmt.target.identifier!!.targetStatement(namespace)!!
|
||||
when(target) {
|
||||
is VarDecl -> stackvmProg.instr(Opcode.PUSH_VAR, callLabel = target.scopedname)
|
||||
else -> throw CompilerException("invalid assignment target type ${target::class}")
|
||||
}
|
||||
}
|
||||
} else if(stmt.target.register!=null) {
|
||||
stackvmProg.instr(Opcode.PUSH_VAR, callLabel = stmt.target.register.toString())
|
||||
stmt.target.register!=null -> stackvmProg.instr(Opcode.PUSH_VAR, callLabel = stmt.target.register.toString())
|
||||
stmt.target.arrayindexed!=null -> translate(stmt.target.arrayindexed!!, false)
|
||||
}
|
||||
|
||||
translateAugAssignOperator(stmt.aug_op)
|
||||
}
|
||||
|
||||
// pop the result value back into the assignment target
|
||||
if(stmt.target.identifier!=null) {
|
||||
val target = stmt.target.identifier!!.targetStatement(namespace)!!
|
||||
when(target) {
|
||||
is VarDecl -> stackvmProg.instr(Opcode.POP_VAR, callLabel = target.scopedname)
|
||||
else -> throw CompilerException("invalid assignment target type ${target::class}")
|
||||
when {
|
||||
stmt.target.identifier!=null -> {
|
||||
val target = stmt.target.identifier!!.targetStatement(namespace)!!
|
||||
when(target) {
|
||||
is VarDecl -> stackvmProg.instr(Opcode.POP_VAR, callLabel = target.scopedname)
|
||||
else -> throw CompilerException("invalid assignment target type ${target::class}")
|
||||
}
|
||||
}
|
||||
} else if(stmt.target.register!=null) {
|
||||
stackvmProg.instr(Opcode.POP_VAR, callLabel = stmt.target.register.toString())
|
||||
stmt.target.register!=null -> stackvmProg.instr(Opcode.POP_VAR, callLabel = stmt.target.register.toString())
|
||||
stmt.target.arrayindexed!=null -> translate(stmt.target.arrayindexed!!, true) // write value to it
|
||||
}
|
||||
}
|
||||
|
||||
@ -915,9 +936,9 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
|
||||
*/
|
||||
fun makeAssignmentTarget(): AssignTarget {
|
||||
return if(varname!=null)
|
||||
AssignTarget(null, IdentifierReference(varname, range.position), range.position)
|
||||
AssignTarget(null, IdentifierReference(varname, range.position), null, range.position)
|
||||
else
|
||||
AssignTarget(register, null, range.position)
|
||||
AssignTarget(register, null, null, range.position)
|
||||
}
|
||||
|
||||
val startAssignment = Assignment(makeAssignmentTarget(), null, range.from, range.position)
|
||||
@ -970,6 +991,8 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
|
||||
} else {
|
||||
null
|
||||
}
|
||||
// todo deal with target.arrayindexed?
|
||||
|
||||
|
||||
when (literalStepValue) {
|
||||
1 -> {
|
||||
|
@ -67,7 +67,7 @@ class StatementOptimizer(private val globalNamespace: INameScope, private val he
|
||||
if(range.size()==1) {
|
||||
// for loop over a (constant) range of just a single value-- optimize the loop away
|
||||
// loopvar/reg = range value , follow by block
|
||||
val assignment = Assignment(AssignTarget(forLoop.loopRegister, forLoop.loopVar, forLoop.position), null, range.from, forLoop.position)
|
||||
val assignment = Assignment(AssignTarget(forLoop.loopRegister, forLoop.loopVar, null, forLoop.position), null, range.from, forLoop.position)
|
||||
forLoop.body.add(0, assignment)
|
||||
return AnonymousStatementList(forLoop.parent, forLoop.body, forLoop.position)
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -107,7 +107,7 @@ class Program (val name: String,
|
||||
Opcode.INC_VAR, Opcode.DEC_VAR,
|
||||
Opcode.SHR_VAR, Opcode.SHL_VAR, Opcode.ROL_VAR, Opcode.ROR_VAR,
|
||||
Opcode.ROL2_VAR, Opcode.ROR2_VAR, Opcode.POP_VAR, Opcode.PUSH_VAR,
|
||||
Opcode.PUSH_INDEXED_VAR -> {
|
||||
Opcode.READ_INDEXED_VAR, Opcode.WRITE_INDEXED_VAR -> {
|
||||
val withoutQuotes =
|
||||
if(args!!.startsWith('"') && args.endsWith('"'))
|
||||
args.substring(1, args.length-1) else args
|
||||
|
@ -94,7 +94,8 @@ enum class Opcode {
|
||||
NOTEQUAL,
|
||||
|
||||
// array access
|
||||
PUSH_INDEXED_VAR,
|
||||
READ_INDEXED_VAR,
|
||||
WRITE_INDEXED_VAR,
|
||||
|
||||
// branching
|
||||
JUMP,
|
||||
@ -911,7 +912,8 @@ class StackVm(private var traceOutputFile: String?) {
|
||||
Opcode.LINE -> {
|
||||
sourceLine = ins.callLabel!!
|
||||
}
|
||||
Opcode.PUSH_INDEXED_VAR -> {
|
||||
Opcode.READ_INDEXED_VAR -> {
|
||||
// put the value of variable[index] onto the stack
|
||||
val index = evalstack.pop().integerValue()
|
||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
||||
if(variable.type==DataType.WORD) {
|
||||
@ -930,7 +932,46 @@ class StackVm(private var traceOutputFile: String?) {
|
||||
DataType.STR,
|
||||
DataType.STR_P,
|
||||
DataType.STR_S,
|
||||
DataType.STR_PS -> throw VmExecutionException("not a proper array/matrix var")
|
||||
DataType.STR_PS -> throw VmExecutionException("not a proper array/matrix var") // todo: allow strings
|
||||
}
|
||||
}
|
||||
}
|
||||
Opcode.WRITE_INDEXED_VAR -> {
|
||||
// store value on the stack in variable[index] (index is on the stack as well)
|
||||
val index = evalstack.pop().integerValue()
|
||||
val value = evalstack.pop()
|
||||
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
|
||||
if(variable.type==DataType.WORD) {
|
||||
// assume the variable is a pointer (address) and write the byte value to that memory location
|
||||
if(value.type!=DataType.BYTE)
|
||||
throw VmExecutionException("writing a non-byte value to memory location")
|
||||
mem.setByte(variable.integerValue(), value.integerValue().toShort())
|
||||
} else {
|
||||
// set indexed element in the array
|
||||
val array = heap.get(variable.heapId)
|
||||
when(array.type) {
|
||||
DataType.ARRAY, DataType.MATRIX -> {
|
||||
if(value.type!=DataType.BYTE)
|
||||
throw VmExecutionException("writing a non-byte value into byte array/matrix")
|
||||
array.array!![index] = value.integerValue()
|
||||
}
|
||||
DataType.ARRAY_W -> {
|
||||
if(value.type!=DataType.WORD)
|
||||
throw VmExecutionException("writing a non-word value into word array")
|
||||
array.array!![index] = value.integerValue()
|
||||
}
|
||||
DataType.ARRAY_F -> {
|
||||
if(value.type!=DataType.FLOAT)
|
||||
throw VmExecutionException("writing a non-float value into float array")
|
||||
array.doubleArray!![index] = value.numericValue().toDouble()
|
||||
}
|
||||
DataType.BYTE,
|
||||
DataType.WORD,
|
||||
DataType.FLOAT,
|
||||
DataType.STR,
|
||||
DataType.STR_P,
|
||||
DataType.STR_S,
|
||||
DataType.STR_PS -> throw VmExecutionException("not a proper array/matrix var") // todo: allow strings
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user