mirror of
https://github.com/irmen/prog8.git
synced 2025-02-13 03:30:28 +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)
|
sortConstantAssignments(block.statements)
|
||||||
|
|
||||||
|
// create subroutine that initializes the block's variables (if any)
|
||||||
val varInits = block.statements.withIndex().filter { it.value is VariableInitializationAssignment }
|
val varInits = block.statements.withIndex().filter { it.value is VariableInitializationAssignment }
|
||||||
if(varInits.isNotEmpty()) {
|
if(varInits.isNotEmpty()) {
|
||||||
val statements = varInits.map{it.value}.toMutableList()
|
val statements = varInits.map{it.value}.toMutableList()
|
||||||
|
@ -65,10 +65,30 @@ class AstVm(val program: Program) {
|
|||||||
|
|
||||||
fun run() {
|
fun run() {
|
||||||
try {
|
try {
|
||||||
val init = VariablesInitializer(runtimeVariables, program.heap)
|
val init = VariablesCreator(runtimeVariables, program.heap)
|
||||||
init.process(program)
|
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")
|
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!")
|
println("PROGRAM EXITED!")
|
||||||
dialog.title = "PROGRAM EXITED"
|
dialog.title = "PROGRAM EXITED"
|
||||||
} catch(bp: VmBreakpointException) {
|
} catch(bp: VmBreakpointException) {
|
||||||
@ -84,18 +104,24 @@ class AstVm(val program: Program) {
|
|||||||
|
|
||||||
private val runtimeVariables = RuntimeVariables()
|
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> {
|
internal fun executeSubroutine(sub: INameScope, arguments: List<RuntimeValue>): List<RuntimeValue> {
|
||||||
if (sub.statements.isEmpty())
|
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) {
|
if(sub is Subroutine) {
|
||||||
assert(!sub.isAsmSubroutine)
|
assert(!sub.isAsmSubroutine)
|
||||||
// TODO process arguments if it's a subroutine
|
// TODO process arguments if it's a subroutine
|
||||||
}
|
}
|
||||||
for (s in sub.statements) {
|
try {
|
||||||
if(s is Return) {
|
for (s in sub.statements) {
|
||||||
return s.values.map { evaluate(it, program, runtimeVariables, ::executeSubroutine) }
|
executeStatement(sub, s)
|
||||||
}
|
}
|
||||||
executeStatement(sub, s)
|
} catch (r: LoopControlReturn) {
|
||||||
|
return r.returnvalues
|
||||||
}
|
}
|
||||||
if(sub !is AnonymousScope)
|
if(sub !is AnonymousScope)
|
||||||
throw VmTerminationException("instruction pointer overflow, is a return missing? $sub")
|
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) {
|
private fun executeStatement(sub: INameScope, stmt: IStatement) {
|
||||||
|
Thread.sleep(10)
|
||||||
when (stmt) {
|
when (stmt) {
|
||||||
is NopStatement, is Label, is Subroutine -> {
|
is NopStatement, is Label, is Subroutine -> {
|
||||||
// do nothing, skip this instruction
|
// do nothing, skip this instruction
|
||||||
@ -140,62 +167,56 @@ class AstVm(val program: Program) {
|
|||||||
is BuiltinFunctionStatementPlaceholder -> {
|
is BuiltinFunctionStatementPlaceholder -> {
|
||||||
TODO("$stmt")
|
TODO("$stmt")
|
||||||
}
|
}
|
||||||
is Return -> {
|
is Return -> throw LoopControlReturn(stmt.values.map { evaluate(it, program, runtimeVariables, ::executeSubroutine) })
|
||||||
throw VmExecutionException("return statement should have been handled by the subroutine loop")
|
is Continue -> throw LoopControlContinue()
|
||||||
}
|
is Break -> throw LoopControlBreak()
|
||||||
is Continue -> {
|
|
||||||
TODO("$stmt")
|
|
||||||
}
|
|
||||||
is Break -> {
|
|
||||||
TODO("$stmt")
|
|
||||||
}
|
|
||||||
is Assignment -> {
|
is Assignment -> {
|
||||||
if(stmt.aug_op==null) {
|
if(stmt.aug_op!=null)
|
||||||
val target = stmt.singleTarget
|
throw VmExecutionException("augmented assignment should have been converted into regular one $stmt")
|
||||||
if(target!=null) {
|
val target = stmt.singleTarget
|
||||||
when {
|
if(target!=null) {
|
||||||
target.identifier!=null -> {
|
when {
|
||||||
val ident = stmt.definingScope().lookup(target.identifier.nameInSource, stmt) as VarDecl
|
target.identifier!=null -> {
|
||||||
val value = evaluate(stmt.value, program, runtimeVariables, ::executeSubroutine)
|
val ident = stmt.definingScope().lookup(target.identifier.nameInSource, stmt) as VarDecl
|
||||||
val identScope = ident.definingScope()
|
val value = evaluate(stmt.value, program, runtimeVariables, ::executeSubroutine)
|
||||||
runtimeVariables.set(identScope, ident.name, value)
|
val identScope = ident.definingScope()
|
||||||
}
|
runtimeVariables.set(identScope, ident.name, value)
|
||||||
target.memoryAddress!=null -> {
|
}
|
||||||
TODO("$stmt")
|
target.memoryAddress!=null -> {
|
||||||
}
|
TODO("$stmt")
|
||||||
target.arrayindexed!=null -> {
|
}
|
||||||
val array = evaluate(target.arrayindexed.identifier, program, runtimeVariables, ::executeSubroutine)
|
target.arrayindexed!=null -> {
|
||||||
val index = evaluate(target.arrayindexed.arrayspec.index, program, runtimeVariables, ::executeSubroutine)
|
val array = evaluate(target.arrayindexed.identifier, program, runtimeVariables, ::executeSubroutine)
|
||||||
val value = evaluate(stmt.value, program, runtimeVariables, ::executeSubroutine)
|
val index = evaluate(target.arrayindexed.arrayspec.index, program, runtimeVariables, ::executeSubroutine)
|
||||||
when(array.type) {
|
val value = evaluate(stmt.value, program, runtimeVariables, ::executeSubroutine)
|
||||||
DataType.ARRAY_UB -> {
|
when(array.type) {
|
||||||
if(value.type!=DataType.UBYTE)
|
DataType.ARRAY_UB -> {
|
||||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
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}")
|
|
||||||
}
|
}
|
||||||
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 -> {
|
is PostIncrDecr -> {
|
||||||
when {
|
when {
|
||||||
@ -228,27 +249,50 @@ class AstVm(val program: Program) {
|
|||||||
throw VmExecutionException("anonymous scopes should have been flattened")
|
throw VmExecutionException("anonymous scopes should have been flattened")
|
||||||
}
|
}
|
||||||
is IfStatement -> {
|
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 -> {
|
is BranchStatement -> {
|
||||||
TODO("$stmt")
|
TODO("$stmt")
|
||||||
}
|
}
|
||||||
is ForLoop -> {
|
is ForLoop -> {
|
||||||
TODO("$stmt")
|
TODO("$stmt")
|
||||||
|
// try {
|
||||||
|
//
|
||||||
|
// } catch(b: LoopControlBreak) {
|
||||||
|
// break
|
||||||
|
// } catch(c: LoopControlContinue){
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
is WhileLoop -> {
|
is WhileLoop -> {
|
||||||
var condition = evaluate(stmt.condition, program, runtimeVariables, ::executeSubroutine)
|
var condition = evaluate(stmt.condition, program, runtimeVariables, ::executeSubroutine)
|
||||||
while(condition.asBooleanRuntimeValue) {
|
while (condition.asBooleanRuntimeValue) {
|
||||||
println("STILL IN WHILE LOOP ${stmt.position}")
|
try {
|
||||||
executeSubroutine(stmt.body, emptyList())
|
println("STILL IN WHILE LOOP ${stmt.position}")
|
||||||
condition = evaluate(stmt.condition, program, runtimeVariables, ::executeSubroutine)
|
executeSubroutine(stmt.body, emptyList())
|
||||||
|
condition = evaluate(stmt.condition, program, runtimeVariables, ::executeSubroutine)
|
||||||
|
} catch(b: LoopControlBreak) {
|
||||||
|
break
|
||||||
|
} catch(c: LoopControlContinue){
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
println(">>>>WHILE LOOP EXITED")
|
println(">>>>WHILE LOOP EXITED")
|
||||||
}
|
}
|
||||||
is RepeatLoop -> {
|
is RepeatLoop -> {
|
||||||
do {
|
do {
|
||||||
val condition = evaluate(stmt.untilCondition, program, runtimeVariables, ::executeSubroutine)
|
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)
|
} while(!condition.asBooleanRuntimeValue)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
@ -3,7 +3,7 @@ package prog8.astvm
|
|||||||
import prog8.ast.*
|
import prog8.ast.*
|
||||||
import prog8.compiler.HeapValues
|
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 {
|
override fun process(decl: VarDecl): IStatement {
|
||||||
if(decl.type==VarDeclType.VAR) {
|
if(decl.type==VarDeclType.VAR) {
|
@ -43,8 +43,8 @@
|
|||||||
while multiple < len(sieve) {
|
while multiple < len(sieve) {
|
||||||
sieve[lsb(multiple)] = true
|
sieve[lsb(multiple)] = true
|
||||||
multiple += candidate_prime
|
multiple += candidate_prime
|
||||||
c64scr.print_uw(multiple) ; TODO
|
; c64scr.print_uw(multiple) ; TODO
|
||||||
c64.CHROUT('\n') ; TODO
|
; c4.CHROUT('\n') ; TODO
|
||||||
}
|
}
|
||||||
return candidate_prime
|
return candidate_prime
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,51 @@
|
|||||||
|
%import c64utils
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
~ main {
|
~ main {
|
||||||
|
|
||||||
|
ubyte[256] sieve
|
||||||
|
ubyte candidate_prime = 2 ; is increased in the loop
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
|
memset(sieve, 256, false) ; clear the sieve, to reset starting situation on subsequent runs
|
||||||
|
|
||||||
uword multiple
|
; calculate primes
|
||||||
|
c64scr.print("prime numbers up to 255:\n\n")
|
||||||
while multiple < 5 {
|
ubyte amount=0
|
||||||
multiple += 2
|
while true {
|
||||||
c64scr.print_uw(multiple) ; TODO
|
ubyte prime = find_next_prime()
|
||||||
c64.CHROUT('\n') ; TODO
|
if prime==0
|
||||||
|
break
|
||||||
|
c64scr.print_ub(prime)
|
||||||
|
c64scr.print(", ")
|
||||||
|
amount++
|
||||||
}
|
}
|
||||||
|
c64.CHROUT('\n')
|
||||||
c64scr.print("done!\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