fix range typing issues and function call param cleanup bug for asmsub

This commit is contained in:
Irmen de Jong 2019-08-02 01:26:28 +02:00
parent fb00ff74d1
commit e9c357a885
4 changed files with 89 additions and 45 deletions

View File

@ -637,13 +637,13 @@ class RangeExpr(var from: Expression,
val toDt=to.inferType(program) val toDt=to.inferType(program)
return when { return when {
fromDt==null || toDt==null -> null fromDt==null || toDt==null -> null
fromDt== DataType.UBYTE && toDt== DataType.UBYTE -> DataType.UBYTE fromDt== DataType.UBYTE && toDt== DataType.UBYTE -> DataType.ARRAY_UB
fromDt== DataType.UWORD && toDt== DataType.UWORD -> DataType.UWORD fromDt== DataType.UWORD && toDt== DataType.UWORD -> DataType.ARRAY_UW
fromDt== DataType.STR && toDt== DataType.STR -> DataType.STR fromDt== DataType.STR && toDt== DataType.STR -> DataType.STR
fromDt== DataType.STR_S && toDt== DataType.STR_S -> DataType.STR_S fromDt== DataType.STR_S && toDt== DataType.STR_S -> DataType.STR_S
fromDt== DataType.WORD || toDt== DataType.WORD -> DataType.WORD fromDt== DataType.WORD || toDt== DataType.WORD -> DataType.ARRAY_W
fromDt== DataType.BYTE || toDt== DataType.BYTE -> DataType.BYTE fromDt== DataType.BYTE || toDt== DataType.BYTE -> DataType.ARRAY_B
else -> DataType.UBYTE else -> DataType.ARRAY_UB
} }
} }
override fun toString(): String { override fun toString(): String {

View File

@ -120,7 +120,7 @@ internal class AstChecker(private val program: Program,
} else { } else {
if (forLoop.loopRegister != null) { if (forLoop.loopRegister != null) {
// loop register // loop register
if (iterableDt != DataType.UBYTE && iterableDt!= DataType.ARRAY_UB && iterableDt !in StringDatatypes) if (iterableDt != DataType.ARRAY_UB && iterableDt != DataType.ARRAY_B && iterableDt !in StringDatatypes)
checkResult.add(ExpressionError("register can only loop over bytes", forLoop.position)) checkResult.add(ExpressionError("register can only loop over bytes", forLoop.position))
if(forLoop.loopRegister!=Register.A) if(forLoop.loopRegister!=Register.A)
checkResult.add(ExpressionError("it's only possible to use A as a loop register", forLoop.position)) checkResult.add(ExpressionError("it's only possible to use A as a loop register", forLoop.position))
@ -750,6 +750,12 @@ internal class AstChecker(private val program: Program,
if(leftDt !in IntegerDatatypes || rightDt !in IntegerDatatypes) if(leftDt !in IntegerDatatypes || rightDt !in IntegerDatatypes)
checkResult.add(ExpressionError("bitwise operator can only be used on integer operands", expr.right.position)) checkResult.add(ExpressionError("bitwise operator can only be used on integer operands", expr.right.position))
} }
"<<", ">>" -> {
// for now, bit-shifts can only shift by a constant number
val constRight = expr.right.constValue(program)
if(constRight==null)
checkResult.add(ExpressionError("bit-shift can only be done by a constant number (for now)", expr.right.position))
}
} }
if(leftDt !in NumericDatatypes) if(leftDt !in NumericDatatypes)

View File

@ -599,10 +599,13 @@ internal class AsmGen2(val program: Program,
} else { } else {
translateSubroutineCall(stmt) translateSubroutineCall(stmt)
// discard any results from the stack: // discard any results from the stack:
val returns = stmt.target.targetSubroutine(program.namespace)!!.returntypes val sub = stmt.target.targetSubroutine(program.namespace)!!
for(t in returns) { val returns = sub.returntypes.zip(sub.asmReturnvaluesRegisters)
if (t in IntegerDatatypes || t in PassByReferenceDatatypes) out(" inx") for((t, reg) in returns) {
else if (t == DataType.FLOAT) out(" inx | inx | inx") if(reg.stack) {
if (t in IntegerDatatypes || t in PassByReferenceDatatypes) out(" inx")
else if (t == DataType.FLOAT) out(" inx | inx | inx")
}
} }
} }
} }
@ -1032,7 +1035,7 @@ $loopLabel lda ${65535.toHex()} ; modified
$endLabel""") $endLabel""")
} }
DataType.ARRAY_UB, DataType.ARRAY_B -> { DataType.ARRAY_UB, DataType.ARRAY_B -> {
val length = decl.arraysize!!.size() val length = decl.arraysize!!.size()!!
if(stmt.loopRegister!=null && stmt.loopRegister!=Register.A) if(stmt.loopRegister!=null && stmt.loopRegister!=Register.A)
throw AssemblyError("can only use A") throw AssemblyError("can only use A")
val counterLabel = makeLabel("for_counter") val counterLabel = makeLabel("for_counter")
@ -1044,8 +1047,6 @@ $endLabel""")
sty $modifiedLabel+2 sty $modifiedLabel+2
ldy #0 ldy #0
$loopLabel sty $counterLabel $loopLabel sty $counterLabel
cpy #$length
beq $endLabel
$modifiedLabel lda ${65535.toHex()},y ; modified""") $modifiedLabel lda ${65535.toHex()},y ; modified""")
if(stmt.loopVar!=null) if(stmt.loopVar!=null)
out(" sta ${asmIdentifierName(stmt.loopVar!!)}") out(" sta ${asmIdentifierName(stmt.loopVar!!)}")
@ -1053,6 +1054,8 @@ $modifiedLabel lda ${65535.toHex()},y ; modified""")
out(""" out("""
ldy $counterLabel ldy $counterLabel
iny iny
cpy #${length and 255}
beq $endLabel
jmp $loopLabel jmp $loopLabel
$counterLabel .byte 0 $counterLabel .byte 0
$endLabel""") $endLabel""")
@ -1076,8 +1079,6 @@ $endLabel""")
sty $modifiedLabel2+2 sty $modifiedLabel2+2
ldy #0 ldy #0
$loopLabel sty $counterLabel $loopLabel sty $counterLabel
cpy #$length
beq $endLabel
$modifiedLabel lda ${65535.toHex()},y ; modified $modifiedLabel lda ${65535.toHex()},y ; modified
sta $loopvarName sta $loopvarName
$modifiedLabel2 lda ${65535.toHex()},y ; modified $modifiedLabel2 lda ${65535.toHex()},y ; modified
@ -1087,6 +1088,8 @@ $modifiedLabel2 lda ${65535.toHex()},y ; modified
ldy $counterLabel ldy $counterLabel
iny iny
iny iny
cpy #${length and 255}
beq $endLabel
jmp $loopLabel jmp $loopLabel
$counterLabel .byte 0 $counterLabel .byte 0
$endLabel""") $endLabel""")
@ -1102,7 +1105,7 @@ $endLabel""")
val loopLabel = makeLabel("for_loop") val loopLabel = makeLabel("for_loop")
val endLabel = makeLabel("for_end") val endLabel = makeLabel("for_end")
when(iterableDt) { when(iterableDt) {
in ByteDatatypes -> { DataType.ARRAY_B, DataType.ARRAY_UB -> {
if(stmt.loopRegister!=null) { if(stmt.loopRegister!=null) {
// loop register over range // loop register over range
@ -1269,7 +1272,7 @@ $endLabel""")
} }
} }
} }
in WordDatatypes -> { DataType.ARRAY_W, DataType.ARRAY_UW -> {
// loop over word range via loopvar // loop over word range via loopvar
val counterLabel = makeLabel("for_counter") val counterLabel = makeLabel("for_counter")
val varname = asmIdentifierName(stmt.loopVar!!) val varname = asmIdentifierName(stmt.loopVar!!)
@ -1745,17 +1748,42 @@ $endLabel""")
} }
private fun translateExpression(expr: BinaryExpression) { private fun translateExpression(expr: BinaryExpression) {
translateExpression(expr.left)
translateExpression(expr.right)
val leftDt = expr.left.inferType(program)!! val leftDt = expr.left.inferType(program)!!
val rightDt = expr.right.inferType(program)!! val rightDt = expr.right.inferType(program)!!
if(leftDt!=rightDt) when(expr.operator) {
throw AssemblyError("binary operator ${expr.operator} left/right dt not identical") // is this strictly required always? ">>" -> {
when (leftDt) { // bit-shifts are always by a constant number (for now)
in ByteDatatypes -> translateBinaryOperatorBytes(expr.operator, leftDt) translateExpression(expr.left)
in WordDatatypes -> translateBinaryOperatorWords(expr.operator, leftDt) val amount = expr.right.constValue(program)!!.number.toInt()
DataType.FLOAT -> translateBinaryOperatorFloats(expr.operator) when(leftDt) {
else -> throw AssemblyError("non-numerical datatype") DataType.UBYTE -> repeat(amount) { out(" lsr $ESTACK_LO_PLUS1_HEX,x") }
DataType.BYTE -> repeat(amount) { out(" lda $ESTACK_LO_PLUS1_HEX,x | asl a | ror $ESTACK_LO_PLUS1_HEX,x") }
DataType.UWORD -> repeat(amount) { out(" lsr $ESTACK_HI_PLUS1_HEX,x | ror $ESTACK_LO_PLUS1_HEX,x") }
DataType.WORD -> repeat(amount) { out( " lda $ESTACK_HI_PLUS1_HEX,x | asl a | ror $ESTACK_HI_PLUS1_HEX,x | ror $ESTACK_LO_PLUS1_HEX,x") }
else -> throw AssemblyError("weird type")
}
}
"<<" -> {
// bit-shifts are always by a constant number (for now)
translateExpression(expr.left)
val amount = expr.right.constValue(program)!!.number.toInt()
if(leftDt in ByteDatatypes)
repeat(amount) { out(" asl $ESTACK_LO_PLUS1_HEX,x") }
else
repeat(amount) { out(" asl $ESTACK_LO_PLUS1_HEX,x | rol $ESTACK_HI_PLUS1_HEX,x") }
}
else -> {
translateExpression(expr.left)
translateExpression(expr.right)
if(leftDt!=rightDt)
throw AssemblyError("binary operator ${expr.operator} left/right dt not identical") // is this strictly required always?
when (leftDt) {
in ByteDatatypes -> translateBinaryOperatorBytes(expr.operator, leftDt)
in WordDatatypes -> translateBinaryOperatorWords(expr.operator, leftDt)
DataType.FLOAT -> translateBinaryOperatorFloats(expr.operator)
else -> throw AssemblyError("non-numerical datatype")
}
}
} }
} }
@ -1819,8 +1847,7 @@ $endLabel""")
inx inx
sta $ESTACK_LO_PLUS1_HEX,x sta $ESTACK_LO_PLUS1_HEX,x
""") """)
"<<" -> throw AssemblyError("<< should not operate via stack") "<<", ">>" -> throw AssemblyError("bit-shifts not via stack")
">>" -> throw AssemblyError(">> should not operate via stack")
"<" -> out(if(types==DataType.UBYTE) " jsr prog8_lib.less_ub" else " jsr prog8_lib.less_b") "<" -> out(if(types==DataType.UBYTE) " jsr prog8_lib.less_ub" else " jsr prog8_lib.less_b")
">" -> out(if(types==DataType.UBYTE) " jsr prog8_lib.greater_ub" else " jsr prog8_lib.greater_b") ">" -> out(if(types==DataType.UBYTE) " jsr prog8_lib.greater_ub" else " jsr prog8_lib.greater_b")
"<=" -> out(if(types==DataType.UBYTE) " jsr prog8_lib.lesseq_ub" else " jsr prog8_lib.lesseq_b") "<=" -> out(if(types==DataType.UBYTE) " jsr prog8_lib.lesseq_ub" else " jsr prog8_lib.lesseq_b")

View File

@ -3,23 +3,34 @@
main { main {
sub start() { sub start() {
c64.CHROUT('\n')
%asm {{
stx $0410
}}
c64.CHRIN()
%asm {{
stx $0411
}}
print_notes(80,35)
%asm {{
stx $0412
}}
return
}
byte bb=10 sub print_notes(ubyte n1, ubyte n2) {
c64scr.print_ub(n1/2)
while bb<15 { c64.CHROUT('\n')
bb++ c64scr.print_ub(n1/3)
c64scr.print_b(bb) c64.CHROUT('\n')
c64.CHROUT('\n') c64scr.print_ub(n1/4)
} c64.CHROUT('\n')
c64.CHROUT('\n')
word ww=5 c64scr.print_ub(n2/2)
c64.CHROUT('\n')
while ww > -5 { c64scr.print_ub(n2/3)
ww-- c64.CHROUT('\n')
c64scr.print_w(ww) c64scr.print_ub(n2/4)
c64.CHROUT('\n') c64.CHROUT('\n')
}
} }
} }