mirror of
https://github.com/irmen/prog8.git
synced 2024-11-29 17:50:35 +00:00
fixed some problems with builtin functions
This commit is contained in:
parent
c01114db9f
commit
79462b3448
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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++
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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),
|
||||||
|
@ -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){
|
||||||
|
@ -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 =
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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")
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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()
|
||||||
|
Loading…
Reference in New Issue
Block a user