mirror of
https://github.com/irmen/prog8.git
synced 2025-01-12 04:30:03 +00:00
fix some initial value datatypes and type casting in assignments
This commit is contained in:
parent
a079e44b02
commit
eb25b4c800
@ -107,6 +107,7 @@ private class StatementReorderer(private val program: Program): IAstProcessor {
|
||||
|
||||
sortConstantAssignments(block.statements)
|
||||
|
||||
// create subroutine that initializes the block's variables (if any)
|
||||
val varInits = block.statements.withIndex().filter { it.value is VariableInitializationAssignment }
|
||||
if(varInits.isNotEmpty()) {
|
||||
val statements = varInits.map{it.value}.toMutableList()
|
||||
|
@ -65,10 +65,30 @@ class AstVm(val program: Program) {
|
||||
|
||||
fun run() {
|
||||
try {
|
||||
val init = VariablesInitializer(runtimeVariables, program.heap)
|
||||
val init = VariablesCreator(runtimeVariables, program.heap)
|
||||
init.process(program)
|
||||
|
||||
// initialize all global variables
|
||||
for(m in program.modules) {
|
||||
for (b in m.statements.filterIsInstance<Block>()) {
|
||||
for (s in b.statements.filterIsInstance<Subroutine>()) {
|
||||
if (s.name == initvarsSubName) {
|
||||
try {
|
||||
executeSubroutine(s, emptyList())
|
||||
} catch (x: LoopControlReturn) {
|
||||
// regular return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val entrypoint = program.entrypoint() ?: throw VmTerminationException("no valid entrypoint found")
|
||||
executeSubroutine(entrypoint, emptyList())
|
||||
try {
|
||||
executeSubroutine(entrypoint, emptyList())
|
||||
} catch (x: LoopControlReturn) {
|
||||
// regular return
|
||||
}
|
||||
println("PROGRAM EXITED!")
|
||||
dialog.title = "PROGRAM EXITED"
|
||||
} catch(bp: VmBreakpointException) {
|
||||
@ -84,18 +104,24 @@ class AstVm(val program: Program) {
|
||||
|
||||
private val runtimeVariables = RuntimeVariables()
|
||||
|
||||
class LoopControlBreak: Exception()
|
||||
class LoopControlContinue: Exception()
|
||||
class LoopControlReturn(val returnvalues: List<RuntimeValue>): Exception()
|
||||
|
||||
internal fun executeSubroutine(sub: INameScope, arguments: List<RuntimeValue>): List<RuntimeValue> {
|
||||
if (sub.statements.isEmpty())
|
||||
throw VmTerminationException("scope contains no statements: $sub")
|
||||
if(sub !is AnonymousScope)
|
||||
throw VmTerminationException("scope contains no statements: $sub")
|
||||
if(sub is Subroutine) {
|
||||
assert(!sub.isAsmSubroutine)
|
||||
// TODO process arguments if it's a subroutine
|
||||
}
|
||||
for (s in sub.statements) {
|
||||
if(s is Return) {
|
||||
return s.values.map { evaluate(it, program, runtimeVariables, ::executeSubroutine) }
|
||||
try {
|
||||
for (s in sub.statements) {
|
||||
executeStatement(sub, s)
|
||||
}
|
||||
executeStatement(sub, s)
|
||||
} catch (r: LoopControlReturn) {
|
||||
return r.returnvalues
|
||||
}
|
||||
if(sub !is AnonymousScope)
|
||||
throw VmTerminationException("instruction pointer overflow, is a return missing? $sub")
|
||||
@ -103,6 +129,7 @@ class AstVm(val program: Program) {
|
||||
}
|
||||
|
||||
private fun executeStatement(sub: INameScope, stmt: IStatement) {
|
||||
Thread.sleep(10)
|
||||
when (stmt) {
|
||||
is NopStatement, is Label, is Subroutine -> {
|
||||
// do nothing, skip this instruction
|
||||
@ -140,62 +167,56 @@ class AstVm(val program: Program) {
|
||||
is BuiltinFunctionStatementPlaceholder -> {
|
||||
TODO("$stmt")
|
||||
}
|
||||
is Return -> {
|
||||
throw VmExecutionException("return statement should have been handled by the subroutine loop")
|
||||
}
|
||||
is Continue -> {
|
||||
TODO("$stmt")
|
||||
}
|
||||
is Break -> {
|
||||
TODO("$stmt")
|
||||
}
|
||||
is Return -> throw LoopControlReturn(stmt.values.map { evaluate(it, program, runtimeVariables, ::executeSubroutine) })
|
||||
is Continue -> throw LoopControlContinue()
|
||||
is Break -> throw LoopControlBreak()
|
||||
is Assignment -> {
|
||||
if(stmt.aug_op==null) {
|
||||
val target = stmt.singleTarget
|
||||
if(target!=null) {
|
||||
when {
|
||||
target.identifier!=null -> {
|
||||
val ident = stmt.definingScope().lookup(target.identifier.nameInSource, stmt) as VarDecl
|
||||
val value = evaluate(stmt.value, program, runtimeVariables, ::executeSubroutine)
|
||||
val identScope = ident.definingScope()
|
||||
runtimeVariables.set(identScope, ident.name, value)
|
||||
}
|
||||
target.memoryAddress!=null -> {
|
||||
TODO("$stmt")
|
||||
}
|
||||
target.arrayindexed!=null -> {
|
||||
val array = evaluate(target.arrayindexed.identifier, program, runtimeVariables, ::executeSubroutine)
|
||||
val index = evaluate(target.arrayindexed.arrayspec.index, program, runtimeVariables, ::executeSubroutine)
|
||||
val value = evaluate(stmt.value, program, runtimeVariables, ::executeSubroutine)
|
||||
when(array.type) {
|
||||
DataType.ARRAY_UB -> {
|
||||
if(value.type!=DataType.UBYTE)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
||||
}
|
||||
DataType.ARRAY_B -> {
|
||||
if(value.type!=DataType.BYTE)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
||||
}
|
||||
DataType.ARRAY_UW -> {
|
||||
if(value.type!=DataType.UWORD)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
||||
}
|
||||
DataType.ARRAY_W -> {
|
||||
if(value.type!=DataType.WORD)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
||||
}
|
||||
DataType.ARRAY_F -> {
|
||||
if(value.type!=DataType.FLOAT)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
||||
}
|
||||
else -> throw VmExecutionException("strange array type ${array.type}")
|
||||
if(stmt.aug_op!=null)
|
||||
throw VmExecutionException("augmented assignment should have been converted into regular one $stmt")
|
||||
val target = stmt.singleTarget
|
||||
if(target!=null) {
|
||||
when {
|
||||
target.identifier!=null -> {
|
||||
val ident = stmt.definingScope().lookup(target.identifier.nameInSource, stmt) as VarDecl
|
||||
val value = evaluate(stmt.value, program, runtimeVariables, ::executeSubroutine)
|
||||
val identScope = ident.definingScope()
|
||||
runtimeVariables.set(identScope, ident.name, value)
|
||||
}
|
||||
target.memoryAddress!=null -> {
|
||||
TODO("$stmt")
|
||||
}
|
||||
target.arrayindexed!=null -> {
|
||||
val array = evaluate(target.arrayindexed.identifier, program, runtimeVariables, ::executeSubroutine)
|
||||
val index = evaluate(target.arrayindexed.arrayspec.index, program, runtimeVariables, ::executeSubroutine)
|
||||
val value = evaluate(stmt.value, program, runtimeVariables, ::executeSubroutine)
|
||||
when(array.type) {
|
||||
DataType.ARRAY_UB -> {
|
||||
if(value.type!=DataType.UBYTE)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
||||
}
|
||||
array.array!![index.integerValue()] = value.numericValue()
|
||||
DataType.ARRAY_B -> {
|
||||
if(value.type!=DataType.BYTE)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
||||
}
|
||||
DataType.ARRAY_UW -> {
|
||||
if(value.type!=DataType.UWORD)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
||||
}
|
||||
DataType.ARRAY_W -> {
|
||||
if(value.type!=DataType.WORD)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
||||
}
|
||||
DataType.ARRAY_F -> {
|
||||
if(value.type!=DataType.FLOAT)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
||||
}
|
||||
else -> throw VmExecutionException("strange array type ${array.type}")
|
||||
}
|
||||
array.array!![index.integerValue()] = value.numericValue()
|
||||
}
|
||||
}
|
||||
else TODO("$stmt")
|
||||
} else TODO("$stmt")
|
||||
}
|
||||
else TODO("$stmt")
|
||||
}
|
||||
is PostIncrDecr -> {
|
||||
when {
|
||||
@ -228,27 +249,50 @@ class AstVm(val program: Program) {
|
||||
throw VmExecutionException("anonymous scopes should have been flattened")
|
||||
}
|
||||
is IfStatement -> {
|
||||
TODO("$stmt")
|
||||
val condition = evaluate(stmt.condition, program, runtimeVariables, ::executeSubroutine)
|
||||
if(condition.asBooleanRuntimeValue)
|
||||
executeSubroutine(stmt.truepart, emptyList())
|
||||
else
|
||||
executeSubroutine(stmt.elsepart, emptyList())
|
||||
}
|
||||
is BranchStatement -> {
|
||||
TODO("$stmt")
|
||||
}
|
||||
is ForLoop -> {
|
||||
TODO("$stmt")
|
||||
// try {
|
||||
//
|
||||
// } catch(b: LoopControlBreak) {
|
||||
// break
|
||||
// } catch(c: LoopControlContinue){
|
||||
// continue
|
||||
// }
|
||||
}
|
||||
is WhileLoop -> {
|
||||
var condition = evaluate(stmt.condition, program, runtimeVariables, ::executeSubroutine)
|
||||
while(condition.asBooleanRuntimeValue) {
|
||||
println("STILL IN WHILE LOOP ${stmt.position}")
|
||||
executeSubroutine(stmt.body, emptyList())
|
||||
condition = evaluate(stmt.condition, program, runtimeVariables, ::executeSubroutine)
|
||||
while (condition.asBooleanRuntimeValue) {
|
||||
try {
|
||||
println("STILL IN WHILE LOOP ${stmt.position}")
|
||||
executeSubroutine(stmt.body, emptyList())
|
||||
condition = evaluate(stmt.condition, program, runtimeVariables, ::executeSubroutine)
|
||||
} catch(b: LoopControlBreak) {
|
||||
break
|
||||
} catch(c: LoopControlContinue){
|
||||
continue
|
||||
}
|
||||
}
|
||||
println(">>>>WHILE LOOP EXITED")
|
||||
}
|
||||
is RepeatLoop -> {
|
||||
do {
|
||||
val condition = evaluate(stmt.untilCondition, program, runtimeVariables, ::executeSubroutine)
|
||||
executeSubroutine(stmt.body, emptyList())
|
||||
try {
|
||||
executeSubroutine(stmt.body, emptyList())
|
||||
} catch(b: LoopControlBreak) {
|
||||
break
|
||||
} catch(c: LoopControlContinue){
|
||||
continue
|
||||
}
|
||||
} while(!condition.asBooleanRuntimeValue)
|
||||
}
|
||||
else -> {
|
||||
|
@ -3,7 +3,7 @@ package prog8.astvm
|
||||
import prog8.ast.*
|
||||
import prog8.compiler.HeapValues
|
||||
|
||||
class VariablesInitializer(private val runtimeVariables: RuntimeVariables, private val heap: HeapValues) : IAstProcessor {
|
||||
class VariablesCreator(private val runtimeVariables: RuntimeVariables, private val heap: HeapValues) : IAstProcessor {
|
||||
|
||||
override fun process(decl: VarDecl): IStatement {
|
||||
if(decl.type==VarDeclType.VAR) {
|
@ -43,8 +43,8 @@
|
||||
while multiple < len(sieve) {
|
||||
sieve[lsb(multiple)] = true
|
||||
multiple += candidate_prime
|
||||
c64scr.print_uw(multiple) ; TODO
|
||||
c64.CHROUT('\n') ; TODO
|
||||
; c64scr.print_uw(multiple) ; TODO
|
||||
; c4.CHROUT('\n') ; TODO
|
||||
}
|
||||
return candidate_prime
|
||||
}
|
||||
|
@ -1,20 +1,51 @@
|
||||
%import c64utils
|
||||
%zeropage basicsafe
|
||||
|
||||
~ main {
|
||||
|
||||
ubyte[256] sieve
|
||||
ubyte candidate_prime = 2 ; is increased in the loop
|
||||
|
||||
sub start() {
|
||||
memset(sieve, 256, false) ; clear the sieve, to reset starting situation on subsequent runs
|
||||
|
||||
uword multiple
|
||||
|
||||
while multiple < 5 {
|
||||
multiple += 2
|
||||
c64scr.print_uw(multiple) ; TODO
|
||||
c64.CHROUT('\n') ; TODO
|
||||
; calculate primes
|
||||
c64scr.print("prime numbers up to 255:\n\n")
|
||||
ubyte amount=0
|
||||
while true {
|
||||
ubyte prime = find_next_prime()
|
||||
if prime==0
|
||||
break
|
||||
c64scr.print_ub(prime)
|
||||
c64scr.print(", ")
|
||||
amount++
|
||||
}
|
||||
|
||||
c64scr.print("done!\n")
|
||||
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print("number of primes (expected 54): ")
|
||||
c64scr.print_ub(amount)
|
||||
c64.CHROUT('\n')
|
||||
}
|
||||
|
||||
|
||||
sub find_next_prime() -> ubyte {
|
||||
|
||||
while sieve[candidate_prime] {
|
||||
candidate_prime++
|
||||
if candidate_prime==0
|
||||
return 0 ; we wrapped; no more primes available in the sieve
|
||||
}
|
||||
|
||||
; found next one, mark the multiples and return it.
|
||||
sieve[candidate_prime] = true
|
||||
uword multiple = candidate_prime
|
||||
|
||||
|
||||
while multiple < len(sieve) {
|
||||
sieve[lsb(multiple)] = true
|
||||
multiple += candidate_prime
|
||||
; c64scr.print_uw(multiple) ; TODO
|
||||
; c4.CHROUT('\n') ; TODO
|
||||
}
|
||||
return candidate_prime
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user