fixed some problems with builtin functions

This commit is contained in:
Irmen de Jong 2018-10-20 23:45:03 +02:00
parent c01114db9f
commit 79462b3448
15 changed files with 265 additions and 150 deletions

View File

@ -33,12 +33,12 @@
while(1) { while(1) {
if irq.time_changed { if irq.time_changed {
irq.time_changed = 0 irq.time_changed = 0
_vm_gfx_clearscr(0) vm_gfx_clearscr(0)
_vm_gfx_text(8, 6, 1, "Spin") vm_gfx_text(8, 6, 1, "Spin")
_vm_gfx_text(29, 11, 1, "to Win !") vm_gfx_text(29, 11, 1, "to Win !")
for uword i in 0 to width//10 { for uword i in 0 to width//10 {
_vm_gfx_line(i*2+width//2-width//10, 130, i*10.w, 199, 6) vm_gfx_line(i*2+width//2-width//10, 130, i*10.w, 199, 6)
} }
rotate_vertices(flt(irq.global_time) / 30.0) rotate_vertices(flt(irq.global_time) / 30.0)
@ -90,7 +90,7 @@
for uword edge in edges { for uword edge in edges {
ubyte e_from = msb(edge) ubyte e_from = msb(edge)
ubyte e_to = lsb(edge) ubyte e_to = lsb(edge)
_vm_gfx_line(toscreenx(rotatedx[e_from], rotatedz[e_from]), toscreeny(rotatedy[e_from], rotatedz[e_from]), vm_gfx_line(toscreenx(rotatedx[e_from], rotatedz[e_from]), toscreeny(rotatedy[e_from], rotatedz[e_from]),
toscreenx(rotatedx[e_to], rotatedz[e_to]), toscreeny(rotatedy[e_to], rotatedz[e_to]), e_from+e_to) toscreenx(rotatedx[e_to], rotatedz[e_to]), toscreeny(rotatedy[e_to], rotatedz[e_to]), e_from+e_to)
} }
@ -99,19 +99,19 @@
word sx = toscreenx(rotatedx[i], rotatedz[i]) word sx = toscreenx(rotatedx[i], rotatedz[i])
word sy = toscreeny(rotatedy[i], rotatedz[i]) word sy = toscreeny(rotatedy[i], rotatedz[i])
ubyte color=i+2 ubyte color=i+2
_vm_gfx_pixel(sx-1, sy-1, color) vm_gfx_pixel(sx-1, sy-1, color)
_vm_gfx_pixel(sx, sy-1, color) vm_gfx_pixel(sx, sy-1, color)
_vm_gfx_pixel(sx+1, sy-1, color) vm_gfx_pixel(sx+1, sy-1, color)
_vm_gfx_pixel(sx-1, sy, color) vm_gfx_pixel(sx-1, sy, color)
_vm_gfx_pixel(sx, sy, color) vm_gfx_pixel(sx, sy, color)
_vm_gfx_pixel(sx+1, sy, color) vm_gfx_pixel(sx+1, sy, color)
_vm_gfx_pixel(sx-1, sy+1, color) vm_gfx_pixel(sx-1, sy+1, color)
_vm_gfx_pixel(sx, sy+1, color) vm_gfx_pixel(sx, sy+1, color)
_vm_gfx_pixel(sx+1, sy+1, color) vm_gfx_pixel(sx+1, sy+1, color)
_vm_gfx_pixel(sx, sy-2, color) vm_gfx_pixel(sx, sy-2, color)
_vm_gfx_pixel(sx+2, sy, color) vm_gfx_pixel(sx+2, sy, color)
_vm_gfx_pixel(sx, sy+2, color) vm_gfx_pixel(sx, sy+2, color)
_vm_gfx_pixel(sx-2, sy, color) vm_gfx_pixel(sx-2, sy, color)
} }
} }
} }

View File

@ -7,8 +7,8 @@
const uword yoffset = 30 const uword yoffset = 30
sub start() { sub start() {
_vm_gfx_clearscr(11) vm_gfx_clearscr(11)
_vm_gfx_text(2, 1, 1, "Calculating Mandelbrot Fractal...") vm_gfx_text(2, 1, 1, "Calculating Mandelbrot Fractal...")
for ubyte pixely in yoffset to yoffset+height-1 { for ubyte pixely in yoffset to yoffset+height-1 {
float yy = flt((pixely-yoffset))/height/3.6+0.4 float yy = flt((pixely-yoffset))/height/3.6+0.4
@ -30,10 +30,10 @@
iter++ iter++
} }
_vm_gfx_pixel(pixelx, pixely, iter) vm_gfx_pixel(pixelx, pixely, iter)
} }
} }
_vm_gfx_text(11, 21, 1, "Finished!") vm_gfx_text(11, 21, 1, "Finished!")
} }
} }
@ -47,9 +47,9 @@
memory ubyte jiffyclockLo = $a2 memory ubyte jiffyclockLo = $a2
sub irq() { sub irq() {
_vm_gfx_pixel(jiffyclockLo,190,jiffyclockHi) vm_gfx_pixel(jiffyclockLo,190,jiffyclockHi)
_vm_gfx_pixel(jiffyclockLo,191,jiffyclockMid) vm_gfx_pixel(jiffyclockLo,191,jiffyclockMid)
_vm_gfx_pixel(jiffyclockLo,192,jiffyclockLo) vm_gfx_pixel(jiffyclockLo,192,jiffyclockLo)
return return
} }
} }

View File

@ -4,37 +4,37 @@
str guess = "000000" str guess = "000000"
ubyte secretnumber = rnd() % 100 ubyte secretnumber = rnd() % 100
_vm_write_str("Let's play a number guessing game!\n") vm_write_str("Let's play a number guessing game!\n")
_vm_write_str("Enter your name: ") vm_write_str("Enter your name: ")
_vm_input_str(name) vm_input_str(name)
_vm_write_str("\nHello, ") vm_write_str("\nHello, ")
_vm_write_str(name) vm_write_str(name)
_vm_write_str(".\nI am thinking of a number from 1 to 100! You'll have to guess it!\n") vm_write_str(".\nI am thinking of a number from 1 to 100! You'll have to guess it!\n")
for ubyte attempts_left in 10 to 1 step -1 { for ubyte attempts_left in 10 to 1 step -1 {
_vm_write_str("\nYou have ") vm_write_str("\nYou have ")
_vm_write_num(attempts_left) vm_write_num(attempts_left)
_vm_write_str(" guess") vm_write_str(" guess")
if attempts_left>1 _vm_write_str("es") if attempts_left>1 vm_write_str("es")
_vm_write_str(" left. What is your next guess? ") vm_write_str(" left. What is your next guess? ")
_vm_input_str(guess) vm_input_str(guess)
ubyte guessednumber = str2ubyte(guess) ubyte guessednumber = str2ubyte(guess)
if guessednumber==secretnumber { if guessednumber==secretnumber {
_vm_write_str("\nYou guessed it, impressive!\n") vm_write_str("\nYou guessed it, impressive!\n")
_vm_write_str("Thanks for playing.\n") vm_write_str("Thanks for playing.\n")
return return
} else { } else {
_vm_write_str("That is too ") vm_write_str("That is too ")
if guessednumber<secretnumber if guessednumber<secretnumber
_vm_write_str("low!\n") vm_write_str("low!\n")
else else
_vm_write_str("high!\n") vm_write_str("high!\n")
} }
} }
_vm_write_str("\nToo bad! My number was: ") vm_write_str("\nToo bad! My number was: ")
_vm_write_num(secretnumber) vm_write_num(secretnumber)
_vm_write_str(".\n") vm_write_str(".\n")
return return
} }
} }

View File

@ -7,7 +7,7 @@
sub start() { sub start() {
_vm_gfx_clearscr(0) vm_gfx_clearscr(0)
float t float t
ubyte color ubyte color
@ -15,7 +15,7 @@
while(1) { while(1) {
float x = sin(t*1.01) + cos(t*1.1234) float x = sin(t*1.01) + cos(t*1.1234)
float y = cos(t) + sin(t*0.03456) float y = cos(t) + sin(t*0.03456)
_vm_gfx_pixel(screenx(x), screeny(y), color//16) vm_gfx_pixel(screenx(x), screeny(y), color//16)
t += 0.01 t += 0.01
color++ color++
} }

View File

@ -1,11 +1,60 @@
%import c64utils ;%import c64utils
%import mathlib %option enable_floats
~ main { ~ main {
sub start() { sub start() {
c64utils.init_system() memory word mword = $c000
memory word mword2 = $c200
memory uword muword = $c100
memory uword muword2 = $c300
ubyte ubvar
byte bvar
memory ubyte mubvar = $c400
float fvar
uword uwvar
ubyte[10] barray
lsl(Y)
lsl(ubvar)
lsl(mubvar)
lsl(uwvar)
lsl(barray[2])
; lsr(Y)
; rol(Y)
; ror(Y)
; ror2(Y)
;
; lsl(bvar)
; lsr(bvar)
; rol(bvar)
; ror(bvar)
; ror2(bvar)
;
; lsl(mubvar)
; lsr(mubvar)
; rol(mubvar)
; ror(mubvar)
; ror2(mubvar)
; lsl(XY)
; lsr(XY)
; rol(XY)
; ror(XY)
; ror2(XY)
;
; lsl(uwvar)
; lsr(uwvar)
; rol(uwvar)
; ror(uwvar)
; ror2(uwvar)
return return

View File

@ -57,9 +57,11 @@ fun main(args: Array<String>) {
// error will be printed by the astchecker // error will be printed by the astchecker
} }
val zpReserved = moduleAst.statements val zpReserved = moduleAst.statements
.asSequence()
.filter{it is Directive && it.directive=="%zpreserved"} .filter{it is Directive && it.directive=="%zpreserved"}
.map{ (it as Directive).args } .map{ (it as Directive).args }
.map{ it[0].int!! .. it[1].int!! } .map{ it[0].int!! .. it[1].int!! }
.toList()
val compilerOptions = CompilationOptions( val compilerOptions = CompilationOptions(
if(outputType==null) OutputType.PRG else OutputType.valueOf(outputType), if(outputType==null) OutputType.PRG else OutputType.valueOf(outputType),

View File

@ -693,6 +693,17 @@ data class AssignTarget(val register: Register?,
fun process(processor: IAstProcessor) = processor.process(this) fun process(processor: IAstProcessor) = processor.process(this)
companion object {
fun fromExpr(expr: IExpression): AssignTarget {
return when (expr) {
is RegisterExpr -> AssignTarget(expr.register, null, null, expr.position)
is IdentifierReference -> AssignTarget(null, expr, null, expr.position)
is ArrayIndexedExpression -> AssignTarget(null, null, expr, expr.position)
else -> throw FatalAstException("invalid expression object $expr")
}
}
}
fun determineDatatype(namespace: INameScope, heap: HeapValues, stmt: IStatement): DataType? { fun determineDatatype(namespace: INameScope, heap: HeapValues, stmt: IStatement): DataType? {
if(register!=null) if(register!=null)
return when(register){ return when(register){

View File

@ -335,13 +335,12 @@ class AstChecker(private val namespace: INameScope,
// check augmented assignment: // check augmented assignment:
// A /= 3 -> check as if it was A = A / 3 // A /= 3 -> check as if it was A = A / 3
val target: IExpression = val target: IExpression =
if(assignment.target.register!=null) when {
RegisterExpr(assignment.target.register!!, assignment.target.position) assignment.target.register!=null -> RegisterExpr(assignment.target.register!!, assignment.target.position)
else if(assignment.target.identifier!=null) assignment.target.identifier!=null -> assignment.target.identifier!!
assignment.target.identifier!! assignment.target.arrayindexed!=null -> assignment.target.arrayindexed!!
else if(assignment.target.arrayindexed!=null) { else -> throw FatalAstException("strange assignment")
assignment.target.arrayindexed!! }
} else throw FatalAstException("strange assignment")
val expression = BinaryExpression(target, assignment.aug_op.substringBeforeLast('='), assignment.value, assignment.position) val expression = BinaryExpression(target, assignment.aug_op.substringBeforeLast('='), assignment.value, assignment.position)
expression.linkParents(assignment.parent) expression.linkParents(assignment.parent)
@ -883,7 +882,7 @@ class AstChecker(private val namespace: INameScope,
if(arraySpecSize!=null && arraySpecSize>0) { if(arraySpecSize!=null && arraySpecSize>0) {
val constX = arrayspec.x.constValue(namespace, heap) val constX = arrayspec.x.constValue(namespace, heap)
val constY = arrayspec.y?.constValue(namespace, heap) val constY = arrayspec.y?.constValue(namespace, heap)
if (constX?.asIntegerValue == null || (constY!=null && constY?.asIntegerValue == null)) if (constX?.asIntegerValue == null || (constY!=null && constY.asIntegerValue == null))
return err("matrix size specifiers must be constant integer values") return err("matrix size specifiers must be constant integer values")
val matrix = heap.get(value.heapId!!).array!! val matrix = heap.get(value.heapId!!).array!!
val expectedSize = val expectedSize =

View File

@ -21,7 +21,7 @@ class StatementReorderer(private val namespace: INameScope, private val heap: He
super.process(module) super.process(module)
val (blocks, other) = module.statements.partition { it is Block } val (blocks, other) = module.statements.partition { it is Block }
module.statements = other.plus(blocks.sortedBy { (it as Block).address ?: Int.MAX_VALUE }).toMutableList() module.statements = other.asSequence().plus(blocks.sortedBy { (it as Block).address ?: Int.MAX_VALUE }).toMutableList()
val mainBlock = module.statements.single { it is Block && it.name=="main" } val mainBlock = module.statements.single { it is Block && it.name=="main" }
if((mainBlock as Block).address==null) { if((mainBlock as Block).address==null) {

View File

@ -593,7 +593,6 @@ private class StatementTranslator(private val prog: IntermediateProgram,
val target = expr.target.targetStatement(namespace) val target = expr.target.targetStatement(namespace)
if(target is BuiltinFunctionStatementPlaceholder) { if(target is BuiltinFunctionStatementPlaceholder) {
// call to a builtin function (some will just be an opcode!) // call to a builtin function (some will just be an opcode!)
expr.arglist.forEach { translate(it) }
val funcname = expr.target.nameInSource[0] val funcname = expr.target.nameInSource[0]
translateFunctionCall(funcname, expr.arglist) translateFunctionCall(funcname, expr.arglist)
} else { } else {
@ -696,7 +695,6 @@ private class StatementTranslator(private val prog: IntermediateProgram,
prog.line(stmt.position) prog.line(stmt.position)
val targetStmt = stmt.target.targetStatement(namespace)!! val targetStmt = stmt.target.targetStatement(namespace)!!
if(targetStmt is BuiltinFunctionStatementPlaceholder) { if(targetStmt is BuiltinFunctionStatementPlaceholder) {
stmt.arglist.forEach { translate(it) }
val funcname = stmt.target.nameInSource[0] val funcname = stmt.target.nameInSource[0]
translateFunctionCall(funcname, stmt.arglist) translateFunctionCall(funcname, stmt.arglist)
return return
@ -720,9 +718,9 @@ private class StatementTranslator(private val prog: IntermediateProgram,
private fun translateFunctionCall(funcname: String, args: List<IExpression>) { private fun translateFunctionCall(funcname: String, args: List<IExpression>) {
// some functions are implemented as vm opcodes // some functions are implemented as vm opcodes
// note: the arguments of the call have already been translated and put on the eval stack! args.forEach { translate(it) } // place function argument(s) on the stack
when (funcname) { when (funcname) {
"flt" -> { "flt" -> { // todo: this is translated ok!
// 1 argument, type determines the exact opcode to use // 1 argument, type determines the exact opcode to use
val arg = args.single() val arg = args.single()
when (arg.resultingDatatype(namespace, heap)) { when (arg.resultingDatatype(namespace, heap)) {
@ -734,64 +732,82 @@ private class StatementTranslator(private val prog: IntermediateProgram,
else -> throw CompilerException("wrong datatype for flt()") else -> throw CompilerException("wrong datatype for flt()")
} }
} }
"msb" -> prog.instr(Opcode.MSB) "msb" -> prog.instr(Opcode.MSB) // todo: is translated ok!
"lsb" -> prog.instr(Opcode.LSB) "lsb" -> prog.instr(Opcode.LSB) // todo: is translated ok!
"b2ub" -> prog.instr(Opcode.B2UB) "b2ub" -> prog.instr(Opcode.B2UB) // todo: is translated ok!
"ub2b" -> prog.instr(Opcode.UB2B) "ub2b" -> prog.instr(Opcode.UB2B) // todo: is translated ok!
"lsl" -> { "lsl" -> {
val arg = args.single() val arg = args.single()
when (arg.resultingDatatype(namespace, heap)) { val dt = arg.resultingDatatype(namespace, heap)
when (dt) {
DataType.UBYTE -> prog.instr(Opcode.SHL_BYTE) DataType.UBYTE -> prog.instr(Opcode.SHL_BYTE)
DataType.UWORD -> prog.instr(Opcode.SHL_WORD) DataType.UWORD -> prog.instr(Opcode.SHL_WORD)
else -> throw CompilerException("wrong datatype") else -> throw CompilerException("wrong datatype")
} }
// this function doesn't return a value on the stack so we pop it directly into the argument register/variable again
popValueIntoTarget(AssignTarget.fromExpr(arg), dt)
} }
"lsr" -> { "lsr" -> {
val arg = args.single() val arg = args.single()
when (arg.resultingDatatype(namespace, heap)) { val dt = arg.resultingDatatype(namespace, heap)
when (dt) {
DataType.UBYTE -> prog.instr(Opcode.SHR_BYTE) DataType.UBYTE -> prog.instr(Opcode.SHR_BYTE)
DataType.UWORD -> prog.instr(Opcode.SHR_WORD) DataType.UWORD -> prog.instr(Opcode.SHR_WORD)
else -> throw CompilerException("wrong datatype") else -> throw CompilerException("wrong datatype")
} }
// this function doesn't return a value on the stack so we pop it directly into the argument register/variable again
popValueIntoTarget(AssignTarget.fromExpr(arg), dt)
} }
"rol" -> { "rol" -> {
val arg = args.single() val arg = args.single()
when (arg.resultingDatatype(namespace, heap)) { val dt = arg.resultingDatatype(namespace, heap)
when (dt) {
DataType.UBYTE -> prog.instr(Opcode.ROL_BYTE) DataType.UBYTE -> prog.instr(Opcode.ROL_BYTE)
DataType.UWORD -> prog.instr(Opcode.ROL_WORD) DataType.UWORD -> prog.instr(Opcode.ROL_WORD)
else -> throw CompilerException("wrong datatype") else -> throw CompilerException("wrong datatype")
} }
// this function doesn't return a value on the stack so we pop it directly into the argument register/variable again
popValueIntoTarget(AssignTarget.fromExpr(arg), dt)
} }
"ror" -> { "ror" -> {
val arg = args.single() val arg = args.single()
when (arg.resultingDatatype(namespace, heap)) { val dt = arg.resultingDatatype(namespace, heap)
when (dt) {
DataType.UBYTE, DataType.BYTE -> prog.instr(Opcode.ROR_BYTE) DataType.UBYTE, DataType.BYTE -> prog.instr(Opcode.ROR_BYTE)
DataType.UWORD, DataType.WORD -> prog.instr(Opcode.ROR_WORD) DataType.UWORD, DataType.WORD -> prog.instr(Opcode.ROR_WORD)
else -> throw CompilerException("wrong datatype") else -> throw CompilerException("wrong datatype")
} }
// this function doesn't return a value on the stack so we pop it directly into the argument register/variable again
popValueIntoTarget(AssignTarget.fromExpr(arg), dt)
} }
"rol2" -> { "rol2" -> {
val arg = args.single() val arg = args.single()
when (arg.resultingDatatype(namespace, heap)) { val dt = arg.resultingDatatype(namespace, heap)
when (dt) {
DataType.UBYTE, DataType.BYTE -> prog.instr(Opcode.ROL2_BYTE) DataType.UBYTE, DataType.BYTE -> prog.instr(Opcode.ROL2_BYTE)
DataType.UWORD, DataType.WORD -> prog.instr(Opcode.ROL2_WORD) DataType.UWORD, DataType.WORD -> prog.instr(Opcode.ROL2_WORD)
else -> throw CompilerException("wrong datatype") else -> throw CompilerException("wrong datatype")
} }
// this function doesn't return a value on the stack so we pop it directly into the argument register/variable again
popValueIntoTarget(AssignTarget.fromExpr(arg), dt)
} }
"ror2" -> { "ror2" -> {
val arg = args.single() val arg = args.single()
when (arg.resultingDatatype(namespace, heap)) { val dt = arg.resultingDatatype(namespace, heap)
when (dt) {
DataType.UBYTE, DataType.BYTE -> prog.instr(Opcode.ROR2_BYTE) DataType.UBYTE, DataType.BYTE -> prog.instr(Opcode.ROR2_BYTE)
DataType.UWORD, DataType.WORD -> prog.instr(Opcode.ROR2_WORD) DataType.UWORD, DataType.WORD -> prog.instr(Opcode.ROR2_WORD)
else -> throw CompilerException("wrong datatype") else -> throw CompilerException("wrong datatype")
} }
// this function doesn't return a value on the stack so we pop it directly into the argument register/variable again
popValueIntoTarget(AssignTarget.fromExpr(arg), dt)
} }
"set_carry" -> prog.instr(Opcode.SEC) "set_carry" -> prog.instr(Opcode.SEC) // todo: compiled ok!!
"clear_carry" -> prog.instr(Opcode.CLC) "clear_carry" -> prog.instr(Opcode.CLC)// todo: compiled ok!!
"set_irqd" -> prog.instr(Opcode.SEI) "set_irqd" -> prog.instr(Opcode.SEI)// todo: compiled ok!!
"clear_irqd" -> prog.instr(Opcode.CLI) "clear_irqd" -> prog.instr(Opcode.CLI)// todo: compiled ok!!
"rsave" -> prog.instr(Opcode.RSAVE) "rsave" -> prog.instr(Opcode.RSAVE)// todo: compiled ok!!
"rrestore" -> prog.instr(Opcode.RRESTORE) "rrestore" -> prog.instr(Opcode.RRESTORE)// todo: compiled ok!!
else -> createSyscall(funcname) // call builtin function else -> createSyscall(funcname) // call builtin function
} }
} }
@ -1056,8 +1072,8 @@ private class StatementTranslator(private val prog: IntermediateProgram,
private fun createSyscall(funcname: String) { private fun createSyscall(funcname: String) {
val function = ( val function = (
if (funcname.startsWith("_vm_")) if (funcname.startsWith("vm_"))
funcname.substring(4) funcname
else else
"FUNC_$funcname" "FUNC_$funcname"
).toUpperCase() ).toUpperCase()
@ -1181,30 +1197,34 @@ private class StatementTranslator(private val prog: IntermediateProgram,
} }
// pop the result value back into the assignment target // pop the result value back into the assignment target
val datatype = stmt.target.determineDatatype(namespace, heap, stmt)!!
popValueIntoTarget(stmt.target, datatype)
}
private fun popValueIntoTarget(assignTarget: AssignTarget, datatype: DataType) {
when { when {
stmt.target.identifier!=null -> { assignTarget.identifier != null -> {
val target = stmt.target.identifier!!.targetStatement(namespace)!! val target = assignTarget.identifier.targetStatement(namespace)!!
if (target is VarDecl) { if (target is VarDecl) {
when(target.type) { when (target.type) {
VarDeclType.VAR -> { VarDeclType.VAR -> {
val opcode = opcodePopvar(stmt.target.determineDatatype(namespace, heap, stmt)!!) val opcode = opcodePopvar(datatype)
prog.instr(opcode, callLabel = target.scopedname) prog.instr(opcode, callLabel = target.scopedname)
} }
VarDeclType.MEMORY -> { VarDeclType.MEMORY -> {
val opcode = opcodePopmem(stmt.target.determineDatatype(namespace, heap, stmt)!!) val opcode = opcodePopmem(datatype)
val address = target.value?.constValue(namespace, heap)!!.asIntegerValue!! val address = target.value?.constValue(namespace, heap)!!.asIntegerValue!!
prog.instr(opcode, Value(DataType.UWORD, address)) prog.instr(opcode, Value(DataType.UWORD, address))
} }
VarDeclType.CONST -> throw CompilerException("cannot assign to const") VarDeclType.CONST -> throw CompilerException("cannot assign to const")
} }
} else throw CompilerException("invalid assignment target type ${target::class}")
} }
else throw CompilerException("invalid assignment target type ${target::class}") assignTarget.register != null -> {
val opcode = opcodePopvar(assignTarget.register)
prog.instr(opcode, callLabel = assignTarget.register.toString())
} }
stmt.target.register!=null -> { assignTarget.arrayindexed != null -> translate(assignTarget.arrayindexed, true) // write value to it
val opcode=opcodePopvar(stmt.target.register!!)
prog.instr(opcode, callLabel = stmt.target.register.toString())
}
stmt.target.arrayindexed!=null -> translate(stmt.target.arrayindexed!!, true) // write value to it
} }
} }

View File

@ -1,8 +1,10 @@
package prog8.compiler.target.c64 package prog8.compiler.target.c64
import prog8.ast.DataType import prog8.ast.DataType
import prog8.ast.StringDatatypes
import prog8.compiler.* import prog8.compiler.*
import prog8.compiler.intermediate.* import prog8.compiler.intermediate.*
import prog8.stackvm.syscallsForStackVm
import java.io.File import java.io.File
import java.io.PrintWriter import java.io.PrintWriter
import java.util.* import java.util.*
@ -15,6 +17,7 @@ class AssemblyError(msg: String) : RuntimeException(msg)
class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, val heap: HeapValues) { class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, val heap: HeapValues) {
private val globalFloatConsts = mutableMapOf<Double, String>() private val globalFloatConsts = mutableMapOf<Double, String>()
private lateinit var output: PrintWriter private lateinit var output: PrintWriter
private var breakpointCounter = 0
init { init {
// Because 64tass understands scoped names via .proc / .block, // Because 64tass understands scoped names via .proc / .block,
@ -638,7 +641,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
out("\tsta ${(nextIns.arg.integerValue()+1).toHex()}") out("\tsta ${(nextIns.arg.integerValue()+1).toHex()}")
return 1 // skip 1 return 1 // skip 1
} }
pushWord(ins.arg!!.integerValue()) if(ins.arg!!.type in StringDatatypes) {
TODO("strings from heap")
}
pushWord(ins.arg.integerValue())
} }
Opcode.PUSH_MEM_UW, Opcode.PUSH_MEM_W -> { Opcode.PUSH_MEM_UW, Opcode.PUSH_MEM_W -> {
val nextIns = block.getIns(insIdx+1) val nextIns = block.getIns(insIdx+1)
@ -878,12 +884,40 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
out("+\tsta ${(ESTACK_LO+1).toHex()},x") out("+\tsta ${(ESTACK_LO+1).toHex()},x")
out("\tsta ${(ESTACK_HI+1).toHex()},x") out("\tsta ${(ESTACK_HI+1).toHex()},x")
} }
Opcode.SYSCALL -> {
if(ins.arg!!.numericValue() in syscallsForStackVm.map { it.callNr })
throw CompilerException("cannot translate vm syscalls to real assembly calls - use *real* subroutine calls instead. Syscall ${ins.arg.numericValue()}")
TODO("syscall $ins")
}
Opcode.BREAKPOINT -> {
breakpointCounter++
out("_prog8_breakpoint_$breakpointCounter\tnop")
}
Opcode.BCS -> out("\tbcs ${ins.callLabel}")
Opcode.BCC -> out("\tbcc ${ins.callLabel}")
Opcode.BZ -> out("\tbeq ${ins.callLabel}")
Opcode.BNZ -> out("\tbne ${ins.callLabel}")
Opcode.BNEG -> out("\tbmi ${ins.callLabel}")
Opcode.BPOS -> out("\tbpl ${ins.callLabel}")
Opcode.POP_MEM_W, Opcode.POP_MEM_UW -> {
popWordAY()
out("\tsta ${ins.callLabel}")
out("\tsty ${ins.callLabel}+1")
}
Opcode.SHL_BYTE -> out("\tasl ${ESTACK_LO.toHex()},x")
Opcode.SHR_BYTE -> out("\tlsr ${ESTACK_LO.toHex()},x")
Opcode.ROL_BYTE -> out("\trol ${ESTACK_LO.toHex()},x") // 9-bit rotate (w/carry)
Opcode.ROR_BYTE -> out("\tror ${ESTACK_LO.toHex()},x") // 9-bit rotate (w/carry)
Opcode.ROL2_BYTE -> out("\tcmp #$80\n\trol") // 8-bit rotate
Opcode.ROR2_BYTE -> { // 8 bit rotate
out("\tlsr a")
out("\tbcc +")
out("\tora #$80")
out("+")
}
else-> TODO("asm for $ins") else-> TODO("asm for $ins")
// Opcode.POP_MEM_W -> TODO()
// Opcode.POP_MEM_UW -> TODO()
// Opcode.POP_MEM_FLOAT -> TODO() // Opcode.POP_MEM_FLOAT -> TODO()
// Opcode.POP_VAR_WORD -> TODO()
// Opcode.POP_VAR_FLOAT -> TODO() // Opcode.POP_VAR_FLOAT -> TODO()
// Opcode.COPY_VAR_FLOAT -> TODO() // Opcode.COPY_VAR_FLOAT -> TODO()
// Opcode.INC_VAR_W -> TODO() // Opcode.INC_VAR_W -> TODO()
@ -923,37 +957,31 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
// Opcode.POW_F -> TODO() // Opcode.POW_F -> TODO()
// Opcode.NEG_W -> TODO() // Opcode.NEG_W -> TODO()
// Opcode.NEG_F -> TODO() // Opcode.NEG_F -> TODO()
// Opcode.SHL_BYTE -> TODO()
// Opcode.SHL_WORD -> TODO() // Opcode.SHL_WORD -> TODO()
// Opcode.SHL_MEM_BYTE -> TODO() // Opcode.SHL_MEM_BYTE -> TODO()
// Opcode.SHL_MEM_WORD -> TODO() // Opcode.SHL_MEM_WORD -> TODO()
// Opcode.SHL_VAR_BYTE -> TODO() // Opcode.SHL_VAR_BYTE -> TODO()
// Opcode.SHL_VAR_WORD -> TODO() // Opcode.SHL_VAR_WORD -> TODO()
// Opcode.SHR_BYTE -> TODO()
// Opcode.SHR_WORD -> TODO() // Opcode.SHR_WORD -> TODO()
// Opcode.SHR_MEM_BYTE -> TODO() // Opcode.SHR_MEM_BYTE -> TODO()
// Opcode.SHR_MEM_WORD -> TODO() // Opcode.SHR_MEM_WORD -> TODO()
// Opcode.SHR_VAR_BYTE -> TODO() // Opcode.SHR_VAR_BYTE -> TODO()
// Opcode.SHR_VAR_WORD -> TODO() // Opcode.SHR_VAR_WORD -> TODO()
// Opcode.ROL_BYTE -> TODO()
// Opcode.ROL_WORD -> TODO() // Opcode.ROL_WORD -> TODO()
// Opcode.ROL_MEM_BYTE -> TODO() // Opcode.ROL_MEM_BYTE -> TODO()
// Opcode.ROL_MEM_WORD -> TODO() // Opcode.ROL_MEM_WORD -> TODO()
// Opcode.ROL_VAR_BYTE -> TODO() // Opcode.ROL_VAR_BYTE -> TODO()
// Opcode.ROL_VAR_WORD -> TODO() // Opcode.ROL_VAR_WORD -> TODO()
// Opcode.ROR_BYTE -> TODO()
// Opcode.ROR_WORD -> TODO() // Opcode.ROR_WORD -> TODO()
// Opcode.ROR_MEM_BYTE -> TODO() // Opcode.ROR_MEM_BYTE -> TODO()
// Opcode.ROR_MEM_WORD -> TODO() // Opcode.ROR_MEM_WORD -> TODO()
// Opcode.ROR_VAR_BYTE -> TODO() // Opcode.ROR_VAR_BYTE -> TODO()
// Opcode.ROR_VAR_WORD -> TODO() // Opcode.ROR_VAR_WORD -> TODO()
// Opcode.ROL2_BYTE -> TODO()
// Opcode.ROL2_WORD -> TODO() // Opcode.ROL2_WORD -> TODO()
// Opcode.ROL2_MEM_BYTE -> TODO() // Opcode.ROL2_MEM_BYTE -> TODO()
// Opcode.ROL2_MEM_WORD -> TODO() // Opcode.ROL2_MEM_WORD -> TODO()
// Opcode.ROL2_VAR_BYTE -> TODO() // Opcode.ROL2_VAR_BYTE -> TODO()
// Opcode.ROL2_VAR_WORD -> TODO() // Opcode.ROL2_VAR_WORD -> TODO()
// Opcode.ROR2_BYTE -> TODO()
// Opcode.ROR2_WORD -> TODO() // Opcode.ROR2_WORD -> TODO()
// Opcode.ROR2_MEM_BYTE -> TODO() // Opcode.ROR2_MEM_BYTE -> TODO()
// Opcode.ROR2_MEM_WORD -> TODO() // Opcode.ROR2_MEM_WORD -> TODO()
@ -1012,14 +1040,6 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
// Opcode.WRITE_INDEXED_VAR_BYTE -> TODO() // Opcode.WRITE_INDEXED_VAR_BYTE -> TODO()
// Opcode.WRITE_INDEXED_VAR_WORD -> TODO() // Opcode.WRITE_INDEXED_VAR_WORD -> TODO()
// Opcode.WRITE_INDEXED_VAR_FLOAT -> TODO() // Opcode.WRITE_INDEXED_VAR_FLOAT -> TODO()
// Opcode.BCS -> TODO()
// Opcode.BCC -> TODO()
// Opcode.BZ -> TODO()
// Opcode.BNZ -> TODO()
// Opcode.BNEG -> TODO()
// Opcode.BPOS -> TODO()
// Opcode.SYSCALL -> TODO()
// Opcode.BREAKPOINT -> TODO()
} }
return 0 return 0
} }

View File

@ -42,11 +42,11 @@ class AssemblyProgram(val name: String) {
private fun generateBreakpointList() { private fun generateBreakpointList() {
// builds list of breakpoints, appends to monitor list file // builds list of breakpoints, appends to monitor list file
val breakpoints = mutableListOf<String>() val breakpoints = mutableListOf<String>()
val pattern = Regex("""al (\w+) \S+_prog8_breakpoint_\d+.?""") // todo what's with the _prog8_breakpoint_? how to find breakpoint? val pattern = Regex("""al (\w+) \S+_prog8_breakpoint_\d+.?""") // gather breakpoints by the source label that's generated for them
for(line in File(viceMonListFile).readLines()) { for(line in File(viceMonListFile).readLines()) {
val match = pattern.matchEntire(line) val match = pattern.matchEntire(line)
if(match!=null) if(match!=null)
breakpoints.add("break \$" + match.groupValues[0]) // todo check breakpoints.add("break \$" + match.groupValues[0]) // todo check this
} }
val num = breakpoints.size val num = breakpoints.size
breakpoints.add(0, "; vice monitor breakpoint list now follows") breakpoints.add(0, "; vice monitor breakpoint list now follows")

View File

@ -5,7 +5,6 @@ import prog8.compiler.HeapValues
import kotlin.math.log2 import kotlin.math.log2
class BuiltinFunctionParam(val name: String, val possibleDatatypes: Set<DataType>) class BuiltinFunctionParam(val name: String, val possibleDatatypes: Set<DataType>)
class FunctionSignature(val pure: Boolean, // does it have side effects? class FunctionSignature(val pure: Boolean, // does it have side effects?
@ -15,12 +14,18 @@ class FunctionSignature(val pure: Boolean, // does it have side effects?
val BuiltinFunctions = mapOf( val BuiltinFunctions = mapOf(
// this set of function have no return value and operate in-place:
"rol" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null), "rol" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null),
"ror" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null), "ror" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null),
"rol2" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null), "rol2" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null),
"ror2" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null), "ror2" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null),
"lsl" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null), "lsl" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null),
"lsr" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null), "lsr" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", setOf(DataType.UBYTE, DataType.UWORD))), null),
// these few have a return value depending on the argument list:
"max" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.max()!! }}, // type depends on args
"min" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.min()!! }}, // type depends on args
"sum" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.sum() }}, // type depends on args
// normal functions follow:
"sin" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::sin) }, "sin" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::sin) },
"cos" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::cos) }, "cos" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::cos) },
"acos" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::acos) }, "acos" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::acos) },
@ -38,9 +43,6 @@ val BuiltinFunctions = mapOf(
"round" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.WORD) { a, p, n, h -> oneDoubleArgOutputWord(a, p, n, h, Math::round) }, "round" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.WORD) { a, p, n, h -> oneDoubleArgOutputWord(a, p, n, h, Math::round) },
"floor" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.WORD) { a, p, n, h -> oneDoubleArgOutputWord(a, p, n, h, Math::floor) }, "floor" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.WORD) { a, p, n, h -> oneDoubleArgOutputWord(a, p, n, h, Math::floor) },
"ceil" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.WORD) { a, p, n, h -> oneDoubleArgOutputWord(a, p, n, h, Math::ceil) }, "ceil" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.WORD) { a, p, n, h -> oneDoubleArgOutputWord(a, p, n, h, Math::ceil) },
"max" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.max()!! }}, // type depends on args
"min" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.min()!! }}, // type depends on args
"sum" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.sum() }}, // type depends on args
"len" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", IterableDatatypes)), DataType.UWORD, ::builtinLen), "len" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", IterableDatatypes)), DataType.UWORD, ::builtinLen),
"any" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), DataType.UBYTE) { a, p, n, h -> collectionArgOutputBoolean(a, p, n, h) { it.any { v -> v != 0.0} }}, "any" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), DataType.UBYTE) { a, p, n, h -> collectionArgOutputBoolean(a, p, n, h) { it.any { v -> v != 0.0} }},
"all" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), DataType.UBYTE) { a, p, n, h -> collectionArgOutputBoolean(a, p, n, h) { it.all { v -> v != 0.0} }}, "all" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), DataType.UBYTE) { a, p, n, h -> collectionArgOutputBoolean(a, p, n, h) { it.all { v -> v != 0.0} }},
@ -65,24 +67,24 @@ val BuiltinFunctions = mapOf(
"str2word" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes)), DataType.WORD), "str2word" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes)), DataType.WORD),
"str2uword" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes)), DataType.UWORD), "str2uword" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes)), DataType.UWORD),
"str2float" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes)), DataType.FLOAT), "str2float" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes)), DataType.FLOAT),
"_vm_write_memchr" to FunctionSignature(false, listOf(BuiltinFunctionParam("address", setOf(DataType.UWORD))), null), "vm_write_memchr" to FunctionSignature(false, listOf(BuiltinFunctionParam("address", setOf(DataType.UWORD))), null),
"_vm_write_memstr" to FunctionSignature(false, listOf(BuiltinFunctionParam("address", setOf(DataType.UWORD))), null), "vm_write_memstr" to FunctionSignature(false, listOf(BuiltinFunctionParam("address", setOf(DataType.UWORD))), null),
"_vm_write_num" to FunctionSignature(false, listOf(BuiltinFunctionParam("number", NumericDatatypes)), null), "vm_write_num" to FunctionSignature(false, listOf(BuiltinFunctionParam("number", NumericDatatypes)), null),
"_vm_write_char" to FunctionSignature(false, listOf(BuiltinFunctionParam("char", setOf(DataType.UBYTE))), null), "vm_write_char" to FunctionSignature(false, listOf(BuiltinFunctionParam("char", setOf(DataType.UBYTE))), null),
"_vm_write_str" to FunctionSignature(false, listOf(BuiltinFunctionParam("string", StringDatatypes)), null), "vm_write_str" to FunctionSignature(false, listOf(BuiltinFunctionParam("string", StringDatatypes)), null),
"_vm_input_str" to FunctionSignature(false, listOf(BuiltinFunctionParam("intovar", StringDatatypes)), null), "vm_input_str" to FunctionSignature(false, listOf(BuiltinFunctionParam("intovar", StringDatatypes)), null),
"_vm_gfx_clearscr" to FunctionSignature(false, listOf(BuiltinFunctionParam("color", setOf(DataType.UBYTE))), null), "vm_gfx_clearscr" to FunctionSignature(false, listOf(BuiltinFunctionParam("color", setOf(DataType.UBYTE))), null),
"_vm_gfx_pixel" to FunctionSignature(false, listOf( "vm_gfx_pixel" to FunctionSignature(false, listOf(
BuiltinFunctionParam("x", IntegerDatatypes), BuiltinFunctionParam("x", IntegerDatatypes),
BuiltinFunctionParam("y", IntegerDatatypes), BuiltinFunctionParam("y", IntegerDatatypes),
BuiltinFunctionParam("color", IntegerDatatypes)), null), BuiltinFunctionParam("color", IntegerDatatypes)), null),
"_vm_gfx_line" to FunctionSignature(false, listOf( "vm_gfx_line" to FunctionSignature(false, listOf(
BuiltinFunctionParam("x1", IntegerDatatypes), BuiltinFunctionParam("x1", IntegerDatatypes),
BuiltinFunctionParam("y1", IntegerDatatypes), BuiltinFunctionParam("y1", IntegerDatatypes),
BuiltinFunctionParam("x2", IntegerDatatypes), BuiltinFunctionParam("x2", IntegerDatatypes),
BuiltinFunctionParam("y2", IntegerDatatypes), BuiltinFunctionParam("y2", IntegerDatatypes),
BuiltinFunctionParam("color", IntegerDatatypes)), null), BuiltinFunctionParam("color", IntegerDatatypes)), null),
"_vm_gfx_text" to FunctionSignature(false, listOf( "vm_gfx_text" to FunctionSignature(false, listOf(
BuiltinFunctionParam("x", IntegerDatatypes), BuiltinFunctionParam("x", IntegerDatatypes),
BuiltinFunctionParam("y", IntegerDatatypes), BuiltinFunctionParam("y", IntegerDatatypes),
BuiltinFunctionParam("color", IntegerDatatypes), BuiltinFunctionParam("color", IntegerDatatypes),
@ -157,7 +159,7 @@ fun builtinFunctionReturnType(function: String, args: List<IExpression>, namespa
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> DataType.UWORD DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> DataType.UWORD
} }
} }
else -> throw FatalAstException("unknown result type for builtin function $function") else -> return null
} }
} }

View File

@ -54,7 +54,7 @@ class Program (val name: String,
labels: MutableMap<String, Instruction>) labels: MutableMap<String, Instruction>)
{ {
while(true) { while(true) {
val (lineNr, line) = lines.next() val (_, line) = lines.next()
if(line.isEmpty()) if(line.isEmpty())
continue continue
else if(line=="%end_block") else if(line=="%end_block")
@ -73,7 +73,7 @@ class Program (val name: String,
val splitpattern = Pattern.compile("\\s+") val splitpattern = Pattern.compile("\\s+")
val heapvalues = mutableListOf<Triple<Int, DataType, String>>() val heapvalues = mutableListOf<Triple<Int, DataType, String>>()
while(true) { while(true) {
val (lineNr, line) = lines.next() val (_, line) = lines.next()
if (line == "%end_heap") if (line == "%end_heap")
break break
val parts = line.split(splitpattern, limit=3) val parts = line.split(splitpattern, limit=3)
@ -185,7 +185,7 @@ class Program (val name: String,
vars: MutableMap<String, Value>): Map<String, Value> { vars: MutableMap<String, Value>): Map<String, Value> {
val splitpattern = Pattern.compile("\\s+") val splitpattern = Pattern.compile("\\s+")
while(true) { while(true) {
val (lineNr, line) = lines.next() val (_, line) = lines.next()
if(line=="%end_variables") if(line=="%end_variables")
return vars return vars
val (name, typeStr, valueStr) = line.split(splitpattern, limit = 3) val (name, typeStr, valueStr) = line.split(splitpattern, limit = 3)

View File

@ -15,16 +15,16 @@ import kotlin.math.*
enum class Syscall(val callNr: Short) { enum class Syscall(val callNr: Short) {
WRITE_MEMCHR(10), // print a single char from the memory address popped from stack VM_WRITE_MEMCHR(10), // print a single char from the memory address popped from stack
WRITE_MEMSTR(11), // print a 0-terminated petscii string from the memory address popped from stack VM_WRITE_MEMSTR(11), // print a 0-terminated petscii string from the memory address popped from stack
WRITE_NUM(12), // pop from the evaluation stack and print it as a number VM_WRITE_NUM(12), // pop from the evaluation stack and print it as a number
WRITE_CHAR(13), // pop from the evaluation stack and print it as a single petscii character VM_WRITE_CHAR(13), // pop from the evaluation stack and print it as a single petscii character
WRITE_STR(14), // pop from the evaluation stack and print it as a string VM_WRITE_STR(14), // pop from the evaluation stack and print it as a string
INPUT_STR(15), // user input a string onto the stack, with max length (truncated) given by value on stack VM_INPUT_STR(15), // user input a string onto the stack, with max length (truncated) given by value on stack
GFX_PIXEL(16), // plot a pixel at (x,y,color) pushed on stack in that order VM_GFX_PIXEL(16), // plot a pixel at (x,y,color) pushed on stack in that order
GFX_CLEARSCR(17), // clear the screen with color pushed on stack VM_GFX_CLEARSCR(17), // clear the screen with color pushed on stack
GFX_TEXT(18), // write text on screen at cursor position (x,y,color,text) pushed on stack in that order (pixel pos= x*8, y*8) VM_GFX_TEXT(18), // write text on screen at cursor position (x,y,color,text) pushed on stack in that order (pixel pos= x*8, y*8)
GFX_LINE(19), // draw line on screen at (x1,y1,x2,y2,color) pushed on stack in that order VM_GFX_LINE(19), // draw line on screen at (x1,y1,x2,y2,color) pushed on stack in that order
FUNC_SIN(66), FUNC_SIN(66),
FUNC_COS(67), FUNC_COS(67),
@ -64,6 +64,18 @@ enum class Syscall(val callNr: Short) {
// some of them are straight opcodes (such as MSB, LSB, LSL, LSR, ROL_BYTE, ROR, ROL2, ROR2, and FLT)! // some of them are straight opcodes (such as MSB, LSB, LSL, LSR, ROL_BYTE, ROR, ROL2, ROR2, and FLT)!
} }
val syscallsForStackVm = setOf(
Syscall.VM_WRITE_MEMCHR,
Syscall.VM_WRITE_MEMSTR,
Syscall.VM_WRITE_NUM,
Syscall.VM_WRITE_CHAR,
Syscall.VM_WRITE_STR,
Syscall.VM_INPUT_STR,
Syscall.VM_GFX_PIXEL,
Syscall.VM_GFX_CLEARSCR,
Syscall.VM_GFX_TEXT,
Syscall.VM_GFX_LINE
)
class VmExecutionException(msg: String?) : Exception(msg) class VmExecutionException(msg: String?) : Exception(msg)
@ -1329,21 +1341,21 @@ class StackVm(private var traceOutputFile: String?) {
val callId = ins.arg!!.integerValue().toShort() val callId = ins.arg!!.integerValue().toShort()
val syscall = Syscall.values().first { it.callNr == callId } val syscall = Syscall.values().first { it.callNr == callId }
when (syscall) { when (syscall) {
Syscall.WRITE_MEMCHR -> { Syscall.VM_WRITE_MEMCHR -> {
val address = evalstack.pop().integerValue() val address = evalstack.pop().integerValue()
print(Petscii.decodePetscii(listOf(mem.getUByte(address)), true)) print(Petscii.decodePetscii(listOf(mem.getUByte(address)), true))
} }
Syscall.WRITE_MEMSTR -> { Syscall.VM_WRITE_MEMSTR -> {
val address = evalstack.pop().integerValue() val address = evalstack.pop().integerValue()
print(mem.getString(address)) print(mem.getString(address))
} }
Syscall.WRITE_NUM -> { Syscall.VM_WRITE_NUM -> {
print(evalstack.pop().numericValue()) print(evalstack.pop().numericValue())
} }
Syscall.WRITE_CHAR -> { Syscall.VM_WRITE_CHAR -> {
print(Petscii.decodePetscii(listOf(evalstack.pop().integerValue().toShort()), true)) print(Petscii.decodePetscii(listOf(evalstack.pop().integerValue().toShort()), true))
} }
Syscall.WRITE_STR -> { Syscall.VM_WRITE_STR -> {
val value = evalstack.pop() val value = evalstack.pop()
when(value.type){ when(value.type){
DataType.UBYTE, DataType.BYTE, DataType.UWORD, DataType.WORD, DataType.FLOAT -> print(value.numericValue()) DataType.UBYTE, DataType.BYTE, DataType.UWORD, DataType.WORD, DataType.FLOAT -> print(value.numericValue())
@ -1353,31 +1365,31 @@ class StackVm(private var traceOutputFile: String?) {
DataType.ARRAY_F -> print(heap.get(value.heapId).doubleArray!!.toList()) DataType.ARRAY_F -> print(heap.get(value.heapId).doubleArray!!.toList())
} }
} }
Syscall.INPUT_STR -> { Syscall.VM_INPUT_STR -> {
val variable = evalstack.pop() val variable = evalstack.pop()
val value = heap.get(variable.heapId) val value = heap.get(variable.heapId)
val maxlen = value.str!!.length val maxlen = value.str!!.length
val input = readLine() ?: "" val input = readLine() ?: ""
heap.update(variable.heapId, input.padEnd(maxlen, '\u0000').substring(0, maxlen)) heap.update(variable.heapId, input.padEnd(maxlen, '\u0000').substring(0, maxlen))
} }
Syscall.GFX_PIXEL -> { Syscall.VM_GFX_PIXEL -> {
// plot pixel at (x, y, color) from stack // plot pixel at (x, y, color) from stack
val color = evalstack.pop() val color = evalstack.pop()
val (y, x) = evalstack.pop2() val (y, x) = evalstack.pop2()
canvas?.setPixel(x.integerValue(), y.integerValue(), color.integerValue()) canvas?.setPixel(x.integerValue(), y.integerValue(), color.integerValue())
} }
Syscall.GFX_LINE -> { Syscall.VM_GFX_LINE -> {
// draw line at (x1, y1, x2, y2, color) from stack // draw line at (x1, y1, x2, y2, color) from stack
val color = evalstack.pop() val color = evalstack.pop()
val (y2, x2) = evalstack.pop2() val (y2, x2) = evalstack.pop2()
val (y1, x1) = evalstack.pop2() val (y1, x1) = evalstack.pop2()
canvas?.drawLine(x1.integerValue(), y1.integerValue(), x2.integerValue(), y2.integerValue(), color.integerValue()) canvas?.drawLine(x1.integerValue(), y1.integerValue(), x2.integerValue(), y2.integerValue(), color.integerValue())
} }
Syscall.GFX_CLEARSCR -> { Syscall.VM_GFX_CLEARSCR -> {
val color = evalstack.pop() val color = evalstack.pop()
canvas?.clearScreen(color.integerValue()) canvas?.clearScreen(color.integerValue())
} }
Syscall.GFX_TEXT -> { Syscall.VM_GFX_TEXT -> {
val textPtr = evalstack.pop() val textPtr = evalstack.pop()
val color = evalstack.pop() val color = evalstack.pop()
val (cy, cx) = evalstack.pop2() val (cy, cx) = evalstack.pop2()