mirror of
https://github.com/irmen/prog8.git
synced 2024-11-25 19:31:36 +00:00
fixed some problems with builtin functions
This commit is contained in:
parent
c01114db9f
commit
79462b3448
@ -33,12 +33,12 @@
|
||||
while(1) {
|
||||
if irq.time_changed {
|
||||
irq.time_changed = 0
|
||||
_vm_gfx_clearscr(0)
|
||||
_vm_gfx_text(8, 6, 1, "Spin")
|
||||
_vm_gfx_text(29, 11, 1, "to Win !")
|
||||
vm_gfx_clearscr(0)
|
||||
vm_gfx_text(8, 6, 1, "Spin")
|
||||
vm_gfx_text(29, 11, 1, "to Win !")
|
||||
|
||||
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)
|
||||
@ -90,7 +90,7 @@
|
||||
for uword edge in edges {
|
||||
ubyte e_from = msb(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)
|
||||
}
|
||||
|
||||
@ -99,19 +99,19 @@
|
||||
word sx = toscreenx(rotatedx[i], rotatedz[i])
|
||||
word sy = toscreeny(rotatedy[i], rotatedz[i])
|
||||
ubyte color=i+2
|
||||
_vm_gfx_pixel(sx-1, sy-1, color)
|
||||
_vm_gfx_pixel(sx, sy-1, color)
|
||||
_vm_gfx_pixel(sx+1, sy-1, color)
|
||||
_vm_gfx_pixel(sx-1, sy, color)
|
||||
_vm_gfx_pixel(sx, sy, color)
|
||||
_vm_gfx_pixel(sx+1, sy, color)
|
||||
_vm_gfx_pixel(sx-1, sy+1, color)
|
||||
_vm_gfx_pixel(sx, sy+1, color)
|
||||
_vm_gfx_pixel(sx+1, sy+1, color)
|
||||
_vm_gfx_pixel(sx, sy-2, color)
|
||||
_vm_gfx_pixel(sx+2, sy, color)
|
||||
_vm_gfx_pixel(sx, sy+2, color)
|
||||
_vm_gfx_pixel(sx-2, sy, color)
|
||||
vm_gfx_pixel(sx-1, sy-1, color)
|
||||
vm_gfx_pixel(sx, sy-1, color)
|
||||
vm_gfx_pixel(sx+1, sy-1, color)
|
||||
vm_gfx_pixel(sx-1, sy, color)
|
||||
vm_gfx_pixel(sx, sy, color)
|
||||
vm_gfx_pixel(sx+1, sy, color)
|
||||
vm_gfx_pixel(sx-1, sy+1, color)
|
||||
vm_gfx_pixel(sx, sy+1, color)
|
||||
vm_gfx_pixel(sx+1, sy+1, color)
|
||||
vm_gfx_pixel(sx, sy-2, color)
|
||||
vm_gfx_pixel(sx+2, sy, color)
|
||||
vm_gfx_pixel(sx, sy+2, color)
|
||||
vm_gfx_pixel(sx-2, sy, color)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,8 +7,8 @@
|
||||
const uword yoffset = 30
|
||||
|
||||
sub start() {
|
||||
_vm_gfx_clearscr(11)
|
||||
_vm_gfx_text(2, 1, 1, "Calculating Mandelbrot Fractal...")
|
||||
vm_gfx_clearscr(11)
|
||||
vm_gfx_text(2, 1, 1, "Calculating Mandelbrot Fractal...")
|
||||
|
||||
for ubyte pixely in yoffset to yoffset+height-1 {
|
||||
float yy = flt((pixely-yoffset))/height/3.6+0.4
|
||||
@ -30,10 +30,10 @@
|
||||
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
|
||||
|
||||
sub irq() {
|
||||
_vm_gfx_pixel(jiffyclockLo,190,jiffyclockHi)
|
||||
_vm_gfx_pixel(jiffyclockLo,191,jiffyclockMid)
|
||||
_vm_gfx_pixel(jiffyclockLo,192,jiffyclockLo)
|
||||
vm_gfx_pixel(jiffyclockLo,190,jiffyclockHi)
|
||||
vm_gfx_pixel(jiffyclockLo,191,jiffyclockMid)
|
||||
vm_gfx_pixel(jiffyclockLo,192,jiffyclockLo)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -4,37 +4,37 @@
|
||||
str guess = "000000"
|
||||
ubyte secretnumber = rnd() % 100
|
||||
|
||||
_vm_write_str("Let's play a number guessing game!\n")
|
||||
_vm_write_str("Enter your name: ")
|
||||
_vm_input_str(name)
|
||||
_vm_write_str("\nHello, ")
|
||||
_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("Let's play a number guessing game!\n")
|
||||
vm_write_str("Enter your name: ")
|
||||
vm_input_str(name)
|
||||
vm_write_str("\nHello, ")
|
||||
vm_write_str(name)
|
||||
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 {
|
||||
_vm_write_str("\nYou have ")
|
||||
_vm_write_num(attempts_left)
|
||||
_vm_write_str(" guess")
|
||||
if attempts_left>1 _vm_write_str("es")
|
||||
_vm_write_str(" left. What is your next guess? ")
|
||||
_vm_input_str(guess)
|
||||
vm_write_str("\nYou have ")
|
||||
vm_write_num(attempts_left)
|
||||
vm_write_str(" guess")
|
||||
if attempts_left>1 vm_write_str("es")
|
||||
vm_write_str(" left. What is your next guess? ")
|
||||
vm_input_str(guess)
|
||||
ubyte guessednumber = str2ubyte(guess)
|
||||
if guessednumber==secretnumber {
|
||||
_vm_write_str("\nYou guessed it, impressive!\n")
|
||||
_vm_write_str("Thanks for playing.\n")
|
||||
vm_write_str("\nYou guessed it, impressive!\n")
|
||||
vm_write_str("Thanks for playing.\n")
|
||||
return
|
||||
} else {
|
||||
_vm_write_str("That is too ")
|
||||
vm_write_str("That is too ")
|
||||
if guessednumber<secretnumber
|
||||
_vm_write_str("low!\n")
|
||||
vm_write_str("low!\n")
|
||||
else
|
||||
_vm_write_str("high!\n")
|
||||
vm_write_str("high!\n")
|
||||
}
|
||||
}
|
||||
|
||||
_vm_write_str("\nToo bad! My number was: ")
|
||||
_vm_write_num(secretnumber)
|
||||
_vm_write_str(".\n")
|
||||
vm_write_str("\nToo bad! My number was: ")
|
||||
vm_write_num(secretnumber)
|
||||
vm_write_str(".\n")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
sub start() {
|
||||
|
||||
_vm_gfx_clearscr(0)
|
||||
vm_gfx_clearscr(0)
|
||||
|
||||
float t
|
||||
ubyte color
|
||||
@ -15,7 +15,7 @@
|
||||
while(1) {
|
||||
float x = sin(t*1.01) + cos(t*1.1234)
|
||||
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
|
||||
color++
|
||||
}
|
||||
|
@ -1,11 +1,60 @@
|
||||
%import c64utils
|
||||
%import mathlib
|
||||
;%import c64utils
|
||||
%option enable_floats
|
||||
|
||||
~ main {
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
@ -57,9 +57,11 @@ fun main(args: Array<String>) {
|
||||
// error will be printed by the astchecker
|
||||
}
|
||||
val zpReserved = moduleAst.statements
|
||||
.asSequence()
|
||||
.filter{it is Directive && it.directive=="%zpreserved"}
|
||||
.map{ (it as Directive).args }
|
||||
.map{ it[0].int!! .. it[1].int!! }
|
||||
.toList()
|
||||
|
||||
val compilerOptions = CompilationOptions(
|
||||
if(outputType==null) OutputType.PRG else OutputType.valueOf(outputType),
|
||||
|
@ -693,6 +693,17 @@ data class AssignTarget(val register: Register?,
|
||||
|
||||
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? {
|
||||
if(register!=null)
|
||||
return when(register){
|
||||
|
@ -335,13 +335,12 @@ class AstChecker(private val namespace: INameScope,
|
||||
// check augmented assignment:
|
||||
// A /= 3 -> check as if it was A = A / 3
|
||||
val target: IExpression =
|
||||
if(assignment.target.register!=null)
|
||||
RegisterExpr(assignment.target.register!!, assignment.target.position)
|
||||
else if(assignment.target.identifier!=null)
|
||||
assignment.target.identifier!!
|
||||
else if(assignment.target.arrayindexed!=null) {
|
||||
assignment.target.arrayindexed!!
|
||||
} else throw FatalAstException("strange assignment")
|
||||
when {
|
||||
assignment.target.register!=null -> RegisterExpr(assignment.target.register!!, assignment.target.position)
|
||||
assignment.target.identifier!=null -> assignment.target.identifier!!
|
||||
assignment.target.arrayindexed!=null -> assignment.target.arrayindexed!!
|
||||
else -> throw FatalAstException("strange assignment")
|
||||
}
|
||||
|
||||
val expression = BinaryExpression(target, assignment.aug_op.substringBeforeLast('='), assignment.value, assignment.position)
|
||||
expression.linkParents(assignment.parent)
|
||||
@ -883,7 +882,7 @@ class AstChecker(private val namespace: INameScope,
|
||||
if(arraySpecSize!=null && arraySpecSize>0) {
|
||||
val constX = arrayspec.x.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")
|
||||
val matrix = heap.get(value.heapId!!).array!!
|
||||
val expectedSize =
|
||||
|
@ -21,7 +21,7 @@ class StatementReorderer(private val namespace: INameScope, private val heap: He
|
||||
super.process(module)
|
||||
|
||||
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" }
|
||||
if((mainBlock as Block).address==null) {
|
||||
|
@ -593,7 +593,6 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
val target = expr.target.targetStatement(namespace)
|
||||
if(target is BuiltinFunctionStatementPlaceholder) {
|
||||
// call to a builtin function (some will just be an opcode!)
|
||||
expr.arglist.forEach { translate(it) }
|
||||
val funcname = expr.target.nameInSource[0]
|
||||
translateFunctionCall(funcname, expr.arglist)
|
||||
} else {
|
||||
@ -696,7 +695,6 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
prog.line(stmt.position)
|
||||
val targetStmt = stmt.target.targetStatement(namespace)!!
|
||||
if(targetStmt is BuiltinFunctionStatementPlaceholder) {
|
||||
stmt.arglist.forEach { translate(it) }
|
||||
val funcname = stmt.target.nameInSource[0]
|
||||
translateFunctionCall(funcname, stmt.arglist)
|
||||
return
|
||||
@ -720,9 +718,9 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
|
||||
private fun translateFunctionCall(funcname: String, args: List<IExpression>) {
|
||||
// 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) {
|
||||
"flt" -> {
|
||||
"flt" -> { // todo: this is translated ok!
|
||||
// 1 argument, type determines the exact opcode to use
|
||||
val arg = args.single()
|
||||
when (arg.resultingDatatype(namespace, heap)) {
|
||||
@ -734,64 +732,82 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
else -> throw CompilerException("wrong datatype for flt()")
|
||||
}
|
||||
}
|
||||
"msb" -> prog.instr(Opcode.MSB)
|
||||
"lsb" -> prog.instr(Opcode.LSB)
|
||||
"b2ub" -> prog.instr(Opcode.B2UB)
|
||||
"ub2b" -> prog.instr(Opcode.UB2B)
|
||||
"msb" -> prog.instr(Opcode.MSB) // todo: is translated ok!
|
||||
"lsb" -> prog.instr(Opcode.LSB) // todo: is translated ok!
|
||||
"b2ub" -> prog.instr(Opcode.B2UB) // todo: is translated ok!
|
||||
"ub2b" -> prog.instr(Opcode.UB2B) // todo: is translated ok!
|
||||
"lsl" -> {
|
||||
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.UWORD -> prog.instr(Opcode.SHL_WORD)
|
||||
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" -> {
|
||||
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.UWORD -> prog.instr(Opcode.SHR_WORD)
|
||||
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" -> {
|
||||
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.UWORD -> prog.instr(Opcode.ROL_WORD)
|
||||
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" -> {
|
||||
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.UWORD, DataType.WORD -> prog.instr(Opcode.ROR_WORD)
|
||||
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" -> {
|
||||
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.UWORD, DataType.WORD -> prog.instr(Opcode.ROL2_WORD)
|
||||
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" -> {
|
||||
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.UWORD, DataType.WORD -> prog.instr(Opcode.ROR2_WORD)
|
||||
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)
|
||||
"clear_carry" -> prog.instr(Opcode.CLC)
|
||||
"set_irqd" -> prog.instr(Opcode.SEI)
|
||||
"clear_irqd" -> prog.instr(Opcode.CLI)
|
||||
"rsave" -> prog.instr(Opcode.RSAVE)
|
||||
"rrestore" -> prog.instr(Opcode.RRESTORE)
|
||||
"set_carry" -> prog.instr(Opcode.SEC) // todo: compiled ok!!
|
||||
"clear_carry" -> prog.instr(Opcode.CLC)// todo: compiled ok!!
|
||||
"set_irqd" -> prog.instr(Opcode.SEI)// todo: compiled ok!!
|
||||
"clear_irqd" -> prog.instr(Opcode.CLI)// todo: compiled ok!!
|
||||
"rsave" -> prog.instr(Opcode.RSAVE)// todo: compiled ok!!
|
||||
"rrestore" -> prog.instr(Opcode.RRESTORE)// todo: compiled ok!!
|
||||
else -> createSyscall(funcname) // call builtin function
|
||||
}
|
||||
}
|
||||
@ -1056,8 +1072,8 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
|
||||
private fun createSyscall(funcname: String) {
|
||||
val function = (
|
||||
if (funcname.startsWith("_vm_"))
|
||||
funcname.substring(4)
|
||||
if (funcname.startsWith("vm_"))
|
||||
funcname
|
||||
else
|
||||
"FUNC_$funcname"
|
||||
).toUpperCase()
|
||||
@ -1181,30 +1197,34 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
}
|
||||
|
||||
// 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 {
|
||||
stmt.target.identifier!=null -> {
|
||||
val target = stmt.target.identifier!!.targetStatement(namespace)!!
|
||||
assignTarget.identifier != null -> {
|
||||
val target = assignTarget.identifier.targetStatement(namespace)!!
|
||||
if (target is VarDecl) {
|
||||
when(target.type) {
|
||||
when (target.type) {
|
||||
VarDeclType.VAR -> {
|
||||
val opcode = opcodePopvar(stmt.target.determineDatatype(namespace, heap, stmt)!!)
|
||||
val opcode = opcodePopvar(datatype)
|
||||
prog.instr(opcode, callLabel = target.scopedname)
|
||||
}
|
||||
VarDeclType.MEMORY -> {
|
||||
val opcode = opcodePopmem(stmt.target.determineDatatype(namespace, heap, stmt)!!)
|
||||
val opcode = opcodePopmem(datatype)
|
||||
val address = target.value?.constValue(namespace, heap)!!.asIntegerValue!!
|
||||
prog.instr(opcode, Value(DataType.UWORD, address))
|
||||
}
|
||||
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}")
|
||||
}
|
||||
stmt.target.register!=null -> {
|
||||
val opcode=opcodePopvar(stmt.target.register!!)
|
||||
prog.instr(opcode, callLabel = stmt.target.register.toString())
|
||||
assignTarget.register != null -> {
|
||||
val opcode = opcodePopvar(assignTarget.register)
|
||||
prog.instr(opcode, callLabel = assignTarget.register.toString())
|
||||
}
|
||||
stmt.target.arrayindexed!=null -> translate(stmt.target.arrayindexed!!, true) // write value to it
|
||||
assignTarget.arrayindexed != null -> translate(assignTarget.arrayindexed, true) // write value to it
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,10 @@
|
||||
package prog8.compiler.target.c64
|
||||
|
||||
import prog8.ast.DataType
|
||||
import prog8.ast.StringDatatypes
|
||||
import prog8.compiler.*
|
||||
import prog8.compiler.intermediate.*
|
||||
import prog8.stackvm.syscallsForStackVm
|
||||
import java.io.File
|
||||
import java.io.PrintWriter
|
||||
import java.util.*
|
||||
@ -15,6 +17,7 @@ class AssemblyError(msg: String) : RuntimeException(msg)
|
||||
class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, val heap: HeapValues) {
|
||||
private val globalFloatConsts = mutableMapOf<Double, String>()
|
||||
private lateinit var output: PrintWriter
|
||||
private var breakpointCounter = 0
|
||||
|
||||
init {
|
||||
// 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()}")
|
||||
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 -> {
|
||||
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_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")
|
||||
// Opcode.POP_MEM_W -> TODO()
|
||||
// Opcode.POP_MEM_UW -> TODO()
|
||||
// Opcode.POP_MEM_FLOAT -> TODO()
|
||||
// Opcode.POP_VAR_WORD -> TODO()
|
||||
// Opcode.POP_VAR_FLOAT -> TODO()
|
||||
// Opcode.COPY_VAR_FLOAT -> TODO()
|
||||
// Opcode.INC_VAR_W -> TODO()
|
||||
@ -923,37 +957,31 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
// Opcode.POW_F -> TODO()
|
||||
// Opcode.NEG_W -> TODO()
|
||||
// Opcode.NEG_F -> TODO()
|
||||
// Opcode.SHL_BYTE -> TODO()
|
||||
// Opcode.SHL_WORD -> TODO()
|
||||
// Opcode.SHL_MEM_BYTE -> TODO()
|
||||
// Opcode.SHL_MEM_WORD -> TODO()
|
||||
// Opcode.SHL_VAR_BYTE -> TODO()
|
||||
// Opcode.SHL_VAR_WORD -> TODO()
|
||||
// Opcode.SHR_BYTE -> TODO()
|
||||
// Opcode.SHR_WORD -> TODO()
|
||||
// Opcode.SHR_MEM_BYTE -> TODO()
|
||||
// Opcode.SHR_MEM_WORD -> TODO()
|
||||
// Opcode.SHR_VAR_BYTE -> TODO()
|
||||
// Opcode.SHR_VAR_WORD -> TODO()
|
||||
// Opcode.ROL_BYTE -> TODO()
|
||||
// Opcode.ROL_WORD -> TODO()
|
||||
// Opcode.ROL_MEM_BYTE -> TODO()
|
||||
// Opcode.ROL_MEM_WORD -> TODO()
|
||||
// Opcode.ROL_VAR_BYTE -> TODO()
|
||||
// Opcode.ROL_VAR_WORD -> TODO()
|
||||
// Opcode.ROR_BYTE -> TODO()
|
||||
// Opcode.ROR_WORD -> TODO()
|
||||
// Opcode.ROR_MEM_BYTE -> TODO()
|
||||
// Opcode.ROR_MEM_WORD -> TODO()
|
||||
// Opcode.ROR_VAR_BYTE -> TODO()
|
||||
// Opcode.ROR_VAR_WORD -> TODO()
|
||||
// Opcode.ROL2_BYTE -> TODO()
|
||||
// Opcode.ROL2_WORD -> TODO()
|
||||
// Opcode.ROL2_MEM_BYTE -> TODO()
|
||||
// Opcode.ROL2_MEM_WORD -> TODO()
|
||||
// Opcode.ROL2_VAR_BYTE -> TODO()
|
||||
// Opcode.ROL2_VAR_WORD -> TODO()
|
||||
// Opcode.ROR2_BYTE -> TODO()
|
||||
// Opcode.ROR2_WORD -> TODO()
|
||||
// Opcode.ROR2_MEM_BYTE -> 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_WORD -> 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
|
||||
}
|
||||
|
@ -42,11 +42,11 @@ class AssemblyProgram(val name: String) {
|
||||
private fun generateBreakpointList() {
|
||||
// builds list of breakpoints, appends to monitor list file
|
||||
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()) {
|
||||
val match = pattern.matchEntire(line)
|
||||
if(match!=null)
|
||||
breakpoints.add("break \$" + match.groupValues[0]) // todo check
|
||||
breakpoints.add("break \$" + match.groupValues[0]) // todo check this
|
||||
}
|
||||
val num = breakpoints.size
|
||||
breakpoints.add(0, "; vice monitor breakpoint list now follows")
|
||||
|
@ -5,7 +5,6 @@ import prog8.compiler.HeapValues
|
||||
import kotlin.math.log2
|
||||
|
||||
|
||||
|
||||
class BuiltinFunctionParam(val name: String, val possibleDatatypes: Set<DataType>)
|
||||
|
||||
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(
|
||||
// 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),
|
||||
"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),
|
||||
"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),
|
||||
"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) },
|
||||
"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) },
|
||||
@ -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) },
|
||||
"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) },
|
||||
"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),
|
||||
"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} }},
|
||||
@ -65,24 +67,24 @@ val BuiltinFunctions = mapOf(
|
||||
"str2word" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes)), DataType.WORD),
|
||||
"str2uword" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes)), DataType.UWORD),
|
||||
"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_memstr" to FunctionSignature(false, listOf(BuiltinFunctionParam("address", setOf(DataType.UWORD))), 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_str" to FunctionSignature(false, listOf(BuiltinFunctionParam("string", 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_pixel" to FunctionSignature(false, listOf(
|
||||
"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_num" to FunctionSignature(false, listOf(BuiltinFunctionParam("number", NumericDatatypes)), 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_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_pixel" to FunctionSignature(false, listOf(
|
||||
BuiltinFunctionParam("x", IntegerDatatypes),
|
||||
BuiltinFunctionParam("y", IntegerDatatypes),
|
||||
BuiltinFunctionParam("color", IntegerDatatypes)), null),
|
||||
"_vm_gfx_line" to FunctionSignature(false, listOf(
|
||||
"vm_gfx_line" to FunctionSignature(false, listOf(
|
||||
BuiltinFunctionParam("x1", IntegerDatatypes),
|
||||
BuiltinFunctionParam("y1", IntegerDatatypes),
|
||||
BuiltinFunctionParam("x2", IntegerDatatypes),
|
||||
BuiltinFunctionParam("y2", IntegerDatatypes),
|
||||
BuiltinFunctionParam("color", IntegerDatatypes)), null),
|
||||
"_vm_gfx_text" to FunctionSignature(false, listOf(
|
||||
"vm_gfx_text" to FunctionSignature(false, listOf(
|
||||
BuiltinFunctionParam("x", IntegerDatatypes),
|
||||
BuiltinFunctionParam("y", 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
|
||||
}
|
||||
}
|
||||
else -> throw FatalAstException("unknown result type for builtin function $function")
|
||||
else -> return null
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ class Program (val name: String,
|
||||
labels: MutableMap<String, Instruction>)
|
||||
{
|
||||
while(true) {
|
||||
val (lineNr, line) = lines.next()
|
||||
val (_, line) = lines.next()
|
||||
if(line.isEmpty())
|
||||
continue
|
||||
else if(line=="%end_block")
|
||||
@ -73,7 +73,7 @@ class Program (val name: String,
|
||||
val splitpattern = Pattern.compile("\\s+")
|
||||
val heapvalues = mutableListOf<Triple<Int, DataType, String>>()
|
||||
while(true) {
|
||||
val (lineNr, line) = lines.next()
|
||||
val (_, line) = lines.next()
|
||||
if (line == "%end_heap")
|
||||
break
|
||||
val parts = line.split(splitpattern, limit=3)
|
||||
@ -185,7 +185,7 @@ class Program (val name: String,
|
||||
vars: MutableMap<String, Value>): Map<String, Value> {
|
||||
val splitpattern = Pattern.compile("\\s+")
|
||||
while(true) {
|
||||
val (lineNr, line) = lines.next()
|
||||
val (_, line) = lines.next()
|
||||
if(line=="%end_variables")
|
||||
return vars
|
||||
val (name, typeStr, valueStr) = line.split(splitpattern, limit = 3)
|
||||
|
@ -15,16 +15,16 @@ import kotlin.math.*
|
||||
|
||||
|
||||
enum class Syscall(val callNr: Short) {
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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_WRITE_MEMCHR(10), // print a single char from the memory address popped from stack
|
||||
VM_WRITE_MEMSTR(11), // print a 0-terminated petscii string from the memory address popped from stack
|
||||
VM_WRITE_NUM(12), // pop from the evaluation stack and print it as a number
|
||||
VM_WRITE_CHAR(13), // pop from the evaluation stack and print it as a single petscii character
|
||||
VM_WRITE_STR(14), // pop from the evaluation stack and print it as a string
|
||||
VM_INPUT_STR(15), // user input a string onto the stack, with max length (truncated) given by value on stack
|
||||
VM_GFX_PIXEL(16), // plot a pixel at (x,y,color) pushed on stack in that order
|
||||
VM_GFX_CLEARSCR(17), // clear the screen with color pushed on stack
|
||||
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)
|
||||
VM_GFX_LINE(19), // draw line on screen at (x1,y1,x2,y2,color) pushed on stack in that order
|
||||
|
||||
FUNC_SIN(66),
|
||||
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)!
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
@ -1329,21 +1341,21 @@ class StackVm(private var traceOutputFile: String?) {
|
||||
val callId = ins.arg!!.integerValue().toShort()
|
||||
val syscall = Syscall.values().first { it.callNr == callId }
|
||||
when (syscall) {
|
||||
Syscall.WRITE_MEMCHR -> {
|
||||
Syscall.VM_WRITE_MEMCHR -> {
|
||||
val address = evalstack.pop().integerValue()
|
||||
print(Petscii.decodePetscii(listOf(mem.getUByte(address)), true))
|
||||
}
|
||||
Syscall.WRITE_MEMSTR -> {
|
||||
Syscall.VM_WRITE_MEMSTR -> {
|
||||
val address = evalstack.pop().integerValue()
|
||||
print(mem.getString(address))
|
||||
}
|
||||
Syscall.WRITE_NUM -> {
|
||||
Syscall.VM_WRITE_NUM -> {
|
||||
print(evalstack.pop().numericValue())
|
||||
}
|
||||
Syscall.WRITE_CHAR -> {
|
||||
Syscall.VM_WRITE_CHAR -> {
|
||||
print(Petscii.decodePetscii(listOf(evalstack.pop().integerValue().toShort()), true))
|
||||
}
|
||||
Syscall.WRITE_STR -> {
|
||||
Syscall.VM_WRITE_STR -> {
|
||||
val value = evalstack.pop()
|
||||
when(value.type){
|
||||
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())
|
||||
}
|
||||
}
|
||||
Syscall.INPUT_STR -> {
|
||||
Syscall.VM_INPUT_STR -> {
|
||||
val variable = evalstack.pop()
|
||||
val value = heap.get(variable.heapId)
|
||||
val maxlen = value.str!!.length
|
||||
val input = readLine() ?: ""
|
||||
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
|
||||
val color = evalstack.pop()
|
||||
val (y, x) = evalstack.pop2()
|
||||
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
|
||||
val color = evalstack.pop()
|
||||
val (y2, x2) = evalstack.pop2()
|
||||
val (y1, x1) = evalstack.pop2()
|
||||
canvas?.drawLine(x1.integerValue(), y1.integerValue(), x2.integerValue(), y2.integerValue(), color.integerValue())
|
||||
}
|
||||
Syscall.GFX_CLEARSCR -> {
|
||||
Syscall.VM_GFX_CLEARSCR -> {
|
||||
val color = evalstack.pop()
|
||||
canvas?.clearScreen(color.integerValue())
|
||||
}
|
||||
Syscall.GFX_TEXT -> {
|
||||
Syscall.VM_GFX_TEXT -> {
|
||||
val textPtr = evalstack.pop()
|
||||
val color = evalstack.pop()
|
||||
val (cy, cx) = evalstack.pop2()
|
||||
|
Loading…
Reference in New Issue
Block a user