mirror of
https://github.com/irmen/prog8.git
synced 2024-11-22 15:33:02 +00:00
taking care of memory mapped vars
This commit is contained in:
parent
060e05c868
commit
595e58ec46
@ -29,6 +29,7 @@ dependencies {
|
||||
compileKotlin {
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
// freeCompilerArgs += "-XXLanguage:+NewInference"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,9 +21,20 @@ class RuntimeVariables {
|
||||
vars[scope] = where
|
||||
}
|
||||
|
||||
fun defineMemory(scope: INameScope, name: String, address: Int) {
|
||||
val where = memvars.getValue(scope)
|
||||
where[name] = address
|
||||
memvars[scope] = where
|
||||
}
|
||||
|
||||
fun set(scope: INameScope, name: String, value: RuntimeValue) {
|
||||
val where = vars.getValue(scope)
|
||||
val existing = where[name] ?: throw NoSuchElementException("no such runtime variable: ${scope.name}.$name")
|
||||
val existing = where[name]
|
||||
if(existing==null) {
|
||||
if(memvars.getValue(scope)[name]!=null)
|
||||
throw NoSuchElementException("this is a memory mapped var, not a normal var: ${scope.name}.$name")
|
||||
throw NoSuchElementException("no such runtime variable: ${scope.name}.$name")
|
||||
}
|
||||
if(existing.type!=value.type)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} expected ${existing.type} for $name")
|
||||
where[name] = value
|
||||
@ -32,13 +43,18 @@ class RuntimeVariables {
|
||||
|
||||
fun get(scope: INameScope, name: String): RuntimeValue {
|
||||
val where = vars.getValue(scope)
|
||||
val value = where[name]
|
||||
if(value!=null)
|
||||
return value
|
||||
throw NoSuchElementException("no such runtime variable: ${scope.name}.$name")
|
||||
val value = where[name] ?: throw NoSuchElementException("no such runtime variable: ${scope.name}.$name")
|
||||
return value
|
||||
}
|
||||
|
||||
fun getMemoryAddress(scope: INameScope, name: String): Int {
|
||||
val where = memvars.getValue(scope)
|
||||
val address = where[name] ?: throw NoSuchElementException("no such runtime memory-variable: ${scope.name}.$name")
|
||||
return address
|
||||
}
|
||||
|
||||
private val vars = mutableMapOf<INameScope, MutableMap<String, RuntimeValue>>().withDefault { mutableMapOf() }
|
||||
private val memvars = mutableMapOf<INameScope, MutableMap<String, Int>>().withDefault { mutableMapOf() }
|
||||
}
|
||||
|
||||
|
||||
@ -133,7 +149,7 @@ class AstVm(val program: Program) {
|
||||
}
|
||||
|
||||
private fun executeStatement(sub: INameScope, stmt: IStatement) {
|
||||
val evalCtx = EvalContext(program, runtimeVariables, functions, ::executeSubroutine)
|
||||
val evalCtx = EvalContext(program, mem, runtimeVariables, functions, ::executeSubroutine)
|
||||
instructionCounter++
|
||||
if(instructionCounter % 100 == 0)
|
||||
Thread.sleep(1)
|
||||
@ -185,10 +201,22 @@ class AstVm(val program: Program) {
|
||||
val value = evaluate(stmt.value, evalCtx)
|
||||
when {
|
||||
target.identifier!=null -> {
|
||||
val ident = stmt.definingScope().lookup(target.identifier.nameInSource, stmt) as? VarDecl
|
||||
val decl = stmt.definingScope().lookup(target.identifier.nameInSource, stmt) as? VarDecl
|
||||
?: throw VmExecutionException("can't find assignment target ${target.identifier}")
|
||||
val identScope = ident.definingScope()
|
||||
runtimeVariables.set(identScope, ident.name, value)
|
||||
if(decl.type==VarDeclType.MEMORY) {
|
||||
val address = runtimeVariables.getMemoryAddress(decl.definingScope(), decl.name)
|
||||
when(decl.datatype) {
|
||||
DataType.UBYTE -> mem.setUByte(address, value.byteval!!)
|
||||
DataType.BYTE -> mem.setSByte(address, value.byteval!!)
|
||||
DataType.UWORD -> mem.setUWord(address, value.wordval!!)
|
||||
DataType.WORD -> mem.setSWord(address, value.wordval!!)
|
||||
DataType.FLOAT -> mem.setFloat(address, value.floatval!!)
|
||||
DataType.STR -> mem.setString(address, value.str!!)
|
||||
DataType.STR_S -> mem.setScreencodeString(address, value.str!!)
|
||||
else -> TODO("set memvar $decl")
|
||||
}
|
||||
} else
|
||||
runtimeVariables.set(decl.definingScope(), decl.name, value)
|
||||
}
|
||||
target.memoryAddress!=null -> {
|
||||
TODO("assign memory $stmt")
|
||||
@ -196,7 +224,6 @@ class AstVm(val program: Program) {
|
||||
target.arrayindexed!=null -> {
|
||||
val array = evaluate(target.arrayindexed.identifier, evalCtx)
|
||||
val index = evaluate(target.arrayindexed.arrayspec.index, evalCtx)
|
||||
val value = evaluate(stmt.value, evalCtx)
|
||||
when(array.type) {
|
||||
DataType.ARRAY_UB -> {
|
||||
if(value.type!=DataType.UBYTE)
|
||||
@ -227,9 +254,9 @@ class AstVm(val program: Program) {
|
||||
if(array.type in ArrayDatatypes)
|
||||
array.array!![index.integerValue()] = value.numericValue()
|
||||
else if(array.type in StringDatatypes) {
|
||||
val index = index.integerValue()
|
||||
val indexInt = index.integerValue()
|
||||
val newchr = Petscii.decodePetscii(listOf(value.numericValue().toShort()), true)
|
||||
val newstr = array.str!!.replaceRange(index, index+1, newchr)
|
||||
val newstr = array.str!!.replaceRange(indexInt, indexInt+1, newchr)
|
||||
val ident = stmt.definingScope().lookup(target.arrayindexed.identifier.nameInSource, stmt) as? VarDecl
|
||||
?: throw VmExecutionException("can't find assignment target ${target.identifier}")
|
||||
val identScope = ident.definingScope()
|
||||
@ -367,7 +394,7 @@ class AstVm(val program: Program) {
|
||||
}
|
||||
|
||||
private fun evaluate(args: List<IExpression>): List<RuntimeValue> = args.map {
|
||||
evaluate(it, EvalContext(program, runtimeVariables, functions, ::executeSubroutine))
|
||||
evaluate(it, EvalContext(program, mem, runtimeVariables, functions, ::executeSubroutine))
|
||||
}
|
||||
|
||||
private fun performSyscall(sub: Subroutine, args: List<RuntimeValue>) {
|
||||
|
@ -5,8 +5,8 @@ import prog8.compiler.RuntimeValue
|
||||
import prog8.compiler.RuntimeValueRange
|
||||
import kotlin.math.abs
|
||||
|
||||
class EvalContext(val program: Program, val runtimeVars: RuntimeVariables,
|
||||
val functions: BuiltinFunctions,
|
||||
class EvalContext(val program: Program, val mem: Memory,
|
||||
val runtimeVars: RuntimeVariables, val functions: BuiltinFunctions,
|
||||
val executeSubroutine: (sub: Subroutine, args: List<RuntimeValue>) -> List<RuntimeValue>)
|
||||
|
||||
fun evaluate(expr: IExpression, ctx: EvalContext): RuntimeValue {
|
||||
@ -31,14 +31,24 @@ fun evaluate(expr: IExpression, ctx: EvalContext): RuntimeValue {
|
||||
">=" -> RuntimeValue(DataType.UBYTE, if (left >= right) 1 else 0)
|
||||
"==" -> RuntimeValue(DataType.UBYTE, if (left == right) 1 else 0)
|
||||
"!=" -> RuntimeValue(DataType.UBYTE, if (left != right) 1 else 0)
|
||||
"+" -> {
|
||||
val result = left.add(right)
|
||||
RuntimeValue(result.type, result.numericValue())
|
||||
"+" -> left.add(right)
|
||||
"-" -> left.sub(right)
|
||||
"*" -> left.mul(right)
|
||||
"/" -> left.div(right)
|
||||
"<<" -> {
|
||||
var result = left
|
||||
repeat(right.integerValue()) {result = result.shl()}
|
||||
result
|
||||
}
|
||||
"-" -> {
|
||||
val result = left.sub(right)
|
||||
RuntimeValue(result.type, result.numericValue())
|
||||
">>" -> {
|
||||
var result = left
|
||||
repeat(right.integerValue()) {result = result.shr()}
|
||||
result
|
||||
}
|
||||
"%" -> left.remainder(right)
|
||||
"|" -> left.or(right)
|
||||
"&" -> left.and(right)
|
||||
"^" -> left.xor(right)
|
||||
else -> TODO("binexpression operator ${expr.operator}")
|
||||
}
|
||||
}
|
||||
@ -74,8 +84,21 @@ fun evaluate(expr: IExpression, ctx: EvalContext): RuntimeValue {
|
||||
val scope = expr.definingScope()
|
||||
val variable = scope.lookup(expr.nameInSource, expr)
|
||||
if(variable is VarDecl) {
|
||||
val stmt = scope.lookup(listOf(variable.name), expr)!!
|
||||
return ctx.runtimeVars.get(stmt.definingScope(), variable.name)
|
||||
if(variable.type==VarDeclType.VAR)
|
||||
return ctx.runtimeVars.get(variable.definingScope(), variable.name)
|
||||
else {
|
||||
val address = ctx.runtimeVars.getMemoryAddress(variable.definingScope(), variable.name)
|
||||
return when(variable.datatype) {
|
||||
DataType.UBYTE -> RuntimeValue(DataType.UBYTE, ctx.mem.getUByte(address))
|
||||
DataType.BYTE -> RuntimeValue(DataType.BYTE, ctx.mem.getSByte(address))
|
||||
DataType.UWORD -> RuntimeValue(DataType.UWORD, ctx.mem.getUWord(address))
|
||||
DataType.WORD -> RuntimeValue(DataType.WORD, ctx.mem.getSWord(address))
|
||||
DataType.FLOAT -> RuntimeValue(DataType.FLOAT, ctx.mem.getFloat(address))
|
||||
DataType.STR -> RuntimeValue(DataType.STR, str=ctx.mem.getString(address))
|
||||
DataType.STR_S -> RuntimeValue(DataType.STR_S, str=ctx.mem.getScreencodeString(address))
|
||||
else -> TODO("memvar $variable")
|
||||
}
|
||||
}
|
||||
} else
|
||||
TODO("weird ref $variable")
|
||||
}
|
||||
|
@ -99,4 +99,24 @@ class Memory {
|
||||
for(i in 0 until numbytes)
|
||||
mem[to+i] = mem[from+i]
|
||||
}
|
||||
|
||||
fun getScreencodeString(strAddress: Int): String? {
|
||||
// lowercase Screencodes
|
||||
val screencodes = mutableListOf<Short>()
|
||||
var addr = strAddress
|
||||
while(true) {
|
||||
val byte = mem[addr++]
|
||||
if(byte==0.toShort()) break
|
||||
screencodes.add(byte)
|
||||
}
|
||||
return Petscii.decodeScreencode(screencodes, true)
|
||||
}
|
||||
|
||||
fun setScreencodeString(address: Int, str: String) {
|
||||
// lowercase screencodes
|
||||
val screencodes = Petscii.encodeScreencode(str, true)
|
||||
var addr = address
|
||||
for (c in screencodes) mem[addr++] = c
|
||||
mem[addr] = 0
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,12 @@ class VariablesCreator(private val runtimeVariables: RuntimeVariables, private v
|
||||
runtimeVariables.define(decl.definingScope(), decl.name, value)
|
||||
}
|
||||
VarDeclType.MEMORY -> {
|
||||
// TODO register memory mapped vars?
|
||||
if(decl.value !is LiteralValue) {
|
||||
TODO("evaluate vardecl expression $decl")
|
||||
//RuntimeValue(decl.datatype, num = evaluate(decl.value!!, program, runtimeVariables, executeSubroutine).numericValue())
|
||||
} else {
|
||||
runtimeVariables.defineMemory(decl.definingScope(), decl.name, (decl.value as LiteralValue).asIntegerValue!!)
|
||||
}
|
||||
}
|
||||
VarDeclType.CONST -> {
|
||||
// consts should have been const-folded away
|
||||
|
@ -236,7 +236,7 @@ open class RuntimeValue(val type: DataType, num: Number?=null, val str: String?=
|
||||
}
|
||||
}
|
||||
|
||||
fun remainder(other: RuntimeValue): RuntimeValue? {
|
||||
fun remainder(other: RuntimeValue): RuntimeValue {
|
||||
val v1 = numericValue()
|
||||
val v2 = other.numericValue()
|
||||
val result = v1.toDouble() % v2.toDouble()
|
||||
|
@ -6,20 +6,16 @@
|
||||
~ main {
|
||||
|
||||
sub start() {
|
||||
uword uw = $ab34
|
||||
str name = "irmen de jong"
|
||||
ubyte u1 = 100
|
||||
ubyte u2 = 30
|
||||
|
||||
c64scr.print_ub(len(name))
|
||||
c64scr.print_ub(u1 % u2)
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print_ub(strlen(name))
|
||||
c64scr.print_ub(u1 / u2)
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print(name)
|
||||
c64scr.print_ub(u2 * 2)
|
||||
c64.CHROUT('\n')
|
||||
name[6] = 0
|
||||
c64scr.print_ub(strlen(name))
|
||||
c64scr.print_ub(u2 * 7)
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print(name)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user