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)
return when {
fromDt==null || toDt==null -> null
fromDt== DataType.UBYTE && toDt== DataType.UBYTE -> DataType.UBYTE
fromDt== DataType.UWORD && toDt== DataType.UWORD -> DataType.UWORD
fromDt== DataType.UBYTE && toDt== DataType.UBYTE -> DataType.ARRAY_UB
fromDt== DataType.UWORD && toDt== DataType.UWORD -> DataType.ARRAY_UW
fromDt== DataType.STR && toDt== DataType.STR -> DataType.STR
fromDt== DataType.STR_S && toDt== DataType.STR_S -> DataType.STR_S
fromDt== DataType.WORD || toDt== DataType.WORD -> DataType.WORD
fromDt== DataType.BYTE || toDt== DataType.BYTE -> DataType.BYTE
else -> DataType.UBYTE
fromDt== DataType.WORD || toDt== DataType.WORD -> DataType.ARRAY_W
fromDt== DataType.BYTE || toDt== DataType.BYTE -> DataType.ARRAY_B
else -> DataType.ARRAY_UB
}
}
override fun toString(): String {

View File

@ -120,7 +120,7 @@ internal class AstChecker(private val program: Program,
} else {
if (forLoop.loopRegister != null) {
// 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))
if(forLoop.loopRegister!=Register.A)
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)
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)

View File

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

View File

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