mirror of
https://github.com/irmen/prog8.git
synced 2025-02-05 09:33:46 +00:00
typecheck prefix expressions better
This commit is contained in:
parent
cffb582568
commit
14f9382cf9
@ -360,9 +360,15 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
}
|
||||
|
||||
if(assignment.value.inferType(program) != assignment.target.inferType(program, assignment))
|
||||
val targetDt = assignment.target.inferType(program, assignment)
|
||||
if(assignment.value.inferType(program) != targetDt)
|
||||
errors.err("assignment value is of different type as the target", assignment.value.position)
|
||||
|
||||
if(assignment.value is TypecastExpression) {
|
||||
if(assignment.isAugmentable && targetDt.istype(DataType.FLOAT))
|
||||
errors.err("typecasting a float value in-place makes no sense", assignment.value.position)
|
||||
}
|
||||
|
||||
super.visit(assignment)
|
||||
}
|
||||
|
||||
@ -708,12 +714,20 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
|
||||
override fun visit(expr: PrefixExpression) {
|
||||
val dt = expr.inferType(program).typeOrElse(DataType.STRUCT)
|
||||
if(expr.operator=="-") {
|
||||
val dt = expr.inferType(program).typeOrElse(DataType.STRUCT)
|
||||
if (dt != DataType.BYTE && dt != DataType.WORD && dt != DataType.FLOAT) {
|
||||
errors.err("can only take negative of a signed number type", expr.position)
|
||||
}
|
||||
}
|
||||
else if(expr.operator == "not") {
|
||||
if(dt !in IntegerDatatypes)
|
||||
errors.err("can only use boolean not on integer types", expr.position)
|
||||
}
|
||||
else if(expr.operator == "~") {
|
||||
if(dt !in IntegerDatatypes)
|
||||
errors.err("can only use bitwise invert on integer types", expr.position)
|
||||
}
|
||||
super.visit(expr)
|
||||
}
|
||||
|
||||
|
@ -113,10 +113,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
is TypecastExpression -> {
|
||||
val cast = assign.value as TypecastExpression
|
||||
val sourceType = cast.expression.inferType(program)
|
||||
val targetType = assign.target.inferType(program, assign)
|
||||
if (sourceType.isKnown && targetType.isKnown &&
|
||||
(sourceType.typeOrElse(DataType.STRUCT) in ByteDatatypes && targetType.typeOrElse(DataType.STRUCT) in ByteDatatypes) ||
|
||||
(sourceType.typeOrElse(DataType.STRUCT) in WordDatatypes && targetType.typeOrElse(DataType.STRUCT) in WordDatatypes)) {
|
||||
if (sourceType.isKnown &&
|
||||
(sourceType.typeOrElse(DataType.STRUCT) in ByteDatatypes && cast.type in ByteDatatypes) ||
|
||||
(sourceType.typeOrElse(DataType.STRUCT) in WordDatatypes && cast.type in WordDatatypes)) {
|
||||
// no need for a type cast
|
||||
assign.value = cast.expression
|
||||
translate(assign)
|
||||
@ -131,7 +130,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
}
|
||||
is ArrayLiteralValue, is StringLiteralValue -> throw AssemblyError("no asm gen for string/array assignment $assign")
|
||||
is RangeExpr -> throw AssemblyError("range expression should have been changed into array values ${assign.value.position}")
|
||||
else -> throw AssemblyError("assignment value type should have been handled elsewhere")
|
||||
else -> throw AssemblyError("assignment value type ${assign.value} should have been handled elsewhere")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,12 +2,14 @@ package prog8.compiler.target.c64.codegen
|
||||
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.base.DataType
|
||||
import prog8.ast.base.IterableDatatypes
|
||||
import prog8.ast.expressions.BinaryExpression
|
||||
import prog8.ast.expressions.PrefixExpression
|
||||
import prog8.ast.expressions.TypecastExpression
|
||||
import prog8.ast.statements.AssignTarget
|
||||
import prog8.ast.statements.Assignment
|
||||
import prog8.compiler.AssemblyError
|
||||
import prog8.compiler.target.c64.C64MachineDefinition.C64Zeropage
|
||||
|
||||
internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
private val assignmentAsmGen: AssignmentAsmGen,
|
||||
@ -28,17 +30,53 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
else -> throw AssemblyError("invalid prefix operator")
|
||||
}
|
||||
}
|
||||
is TypecastExpression -> {
|
||||
println("TODO optimize typecast assignment ${assign.position}")
|
||||
assignmentAsmGen.translateOtherAssignment(assign) // TODO get rid of this fallback
|
||||
}
|
||||
is BinaryExpression -> {
|
||||
println("TODO optimize binexpr assignment ${assign.position}")
|
||||
assignmentAsmGen.translateOtherAssignment(assign) // TODO get rid of this fallback
|
||||
}
|
||||
else -> {
|
||||
throw AssemblyError("invalid aug assign value type")
|
||||
is TypecastExpression -> inplaceCast(assign.target, assign.value as TypecastExpression, assign)
|
||||
is BinaryExpression -> inplaceBinary(assign.target, assign.value as BinaryExpression, assign)
|
||||
else -> throw AssemblyError("invalid aug assign value type")
|
||||
}
|
||||
}
|
||||
|
||||
private fun inplaceBinary(target: AssignTarget, binaryExpression: BinaryExpression, assign: Assignment) {
|
||||
println("TODO optimize binexpr assignment ${binaryExpression.position}")
|
||||
assignmentAsmGen.translateOtherAssignment(assign) // TODO get rid of this fallback
|
||||
}
|
||||
|
||||
private fun inplaceCast(target: AssignTarget, cast: TypecastExpression, assign: Assignment) {
|
||||
val targetDt = target.inferType(program, assign).typeOrElse(DataType.STRUCT)
|
||||
val outerCastDt = cast.type
|
||||
val innerCastDt = (cast.expression as? TypecastExpression)?.type
|
||||
|
||||
if(innerCastDt==null) {
|
||||
// simple typecast where the value is the target
|
||||
when(targetDt) {
|
||||
DataType.UBYTE, DataType.BYTE -> { /* byte target can't be casted to anything else at all */ }
|
||||
DataType.UWORD, DataType.WORD -> {
|
||||
when(outerCastDt) {
|
||||
DataType.UBYTE, DataType.BYTE -> {
|
||||
if(target.identifier!=null) {
|
||||
val name = asmgen.asmIdentifierName(target.identifier!!)
|
||||
asmgen.out(" lda #0 | sta $name+1")
|
||||
} else
|
||||
throw AssemblyError("weird value")
|
||||
}
|
||||
DataType.UWORD, DataType.WORD, in IterableDatatypes -> {}
|
||||
DataType.FLOAT -> throw AssemblyError("incompatible cast type")
|
||||
else -> throw AssemblyError("weird cast type")
|
||||
}
|
||||
}
|
||||
DataType.FLOAT -> {
|
||||
if(outerCastDt!=DataType.FLOAT)
|
||||
throw AssemblyError("in-place cast of a float makes no sense")
|
||||
}
|
||||
else -> throw AssemblyError("invalid cast target type")
|
||||
}
|
||||
} else {
|
||||
// typecast with nested typecast, that has the target as a value
|
||||
// calculate singular cast that is required
|
||||
val castDt = if(outerCastDt largerThan innerCastDt) innerCastDt else outerCastDt
|
||||
val value = (cast.expression as TypecastExpression).expression
|
||||
val resultingCast = TypecastExpression(value, castDt, false, assign.position)
|
||||
inplaceCast(target, resultingCast, assign)
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,10 +98,10 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
sta $name""")
|
||||
}
|
||||
memory!=null -> {
|
||||
TODO()
|
||||
TODO("in-place not of ubyte memory")
|
||||
}
|
||||
arrayIdx!=null -> {
|
||||
TODO()
|
||||
TODO("in-place not of ubyte array")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -81,12 +119,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
lsr a
|
||||
sta $name+1""")
|
||||
}
|
||||
memory!=null -> {
|
||||
TODO()
|
||||
}
|
||||
arrayIdx!=null -> {
|
||||
TODO()
|
||||
}
|
||||
arrayIdx!=null -> TODO("in-place not of uword array")
|
||||
memory!=null -> throw AssemblyError("no asm gen for uword-memory not")
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("boolean-not of invalid type")
|
||||
@ -109,10 +143,10 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
sta $name""")
|
||||
}
|
||||
memory!=null -> {
|
||||
TODO()
|
||||
TODO("in-place invert ubyte memory")
|
||||
}
|
||||
arrayIdx!=null -> {
|
||||
TODO()
|
||||
TODO("in-place invert ubyte array")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -128,12 +162,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
eor #255
|
||||
sta $name+1""")
|
||||
}
|
||||
memory!=null -> {
|
||||
TODO()
|
||||
}
|
||||
arrayIdx!=null -> {
|
||||
TODO()
|
||||
}
|
||||
arrayIdx!=null -> TODO("in-place invert uword array")
|
||||
memory!=null -> throw AssemblyError("no asm gen for uword-memory invert")
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("invert of invalid type")
|
||||
@ -157,10 +187,10 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
sta $name""")
|
||||
}
|
||||
memory!=null -> {
|
||||
TODO()
|
||||
TODO("in-place negate byte memory")
|
||||
}
|
||||
arrayIdx!=null -> {
|
||||
TODO()
|
||||
TODO("in-place negate byte array")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -177,16 +207,29 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
sbc $name+1
|
||||
sta $name+1""")
|
||||
}
|
||||
memory!=null -> {
|
||||
TODO()
|
||||
}
|
||||
arrayIdx!=null -> {
|
||||
TODO()
|
||||
}
|
||||
arrayIdx!=null -> TODO("in-place negate word array")
|
||||
memory!=null -> throw AssemblyError("no asm gen for word memory negate")
|
||||
}
|
||||
}
|
||||
DataType.FLOAT -> {
|
||||
TODO()
|
||||
when {
|
||||
identifier!=null -> {
|
||||
val name = asmgen.asmIdentifierName(identifier)
|
||||
asmgen.out("""
|
||||
stx ${C64Zeropage.SCRATCH_REG_X}
|
||||
lda #<$name
|
||||
ldy #>$name
|
||||
jsr c64flt.MOVFM
|
||||
jsr c64flt.NEGOP
|
||||
ldx #<$name
|
||||
ldy #>$name
|
||||
jsr c64flt.MOVMF
|
||||
ldx ${C64Zeropage.SCRATCH_REG_X}
|
||||
""")
|
||||
}
|
||||
arrayIdx!=null -> TODO("in-place negate float array")
|
||||
memory!=null -> throw AssemblyError("no asm gen for float memory negate")
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("negate of invalid type")
|
||||
}
|
||||
|
@ -7,55 +7,50 @@ main {
|
||||
|
||||
sub start() {
|
||||
|
||||
byte A = 99
|
||||
ubyte U = $18
|
||||
word B = 9999
|
||||
uword W = $18f0
|
||||
|
||||
c64scr.print_b(A)
|
||||
c64.CHROUT('\n')
|
||||
A = -A
|
||||
c64scr.print_b(A)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
U = ~U
|
||||
c64scr.print_ubhex(U, true)
|
||||
c64.CHROUT('\n')
|
||||
U = not U
|
||||
c64scr.print_ubhex(U, true)
|
||||
c64.CHROUT('\n')
|
||||
U = not U
|
||||
c64scr.print_ubhex(U, true)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
c64scr.print_w(B)
|
||||
c64.CHROUT('\n')
|
||||
B = -B
|
||||
c64scr.print_w(B)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
W = ~W
|
||||
c64scr.print_uwhex(W, true)
|
||||
c64.CHROUT('\n')
|
||||
W = not W
|
||||
c64scr.print_uwhex(W, true)
|
||||
c64.CHROUT('\n')
|
||||
W = not W
|
||||
c64scr.print_uwhex(W, true)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
; byte A = 99
|
||||
; ubyte U = $18
|
||||
; word B = 9999
|
||||
; uword W = $18f0
|
||||
;
|
||||
; byte B = +A
|
||||
; byte C = -A
|
||||
; uword W = 43210
|
||||
; c64scr.print_b(A)
|
||||
; c64.CHROUT('\n')
|
||||
; A = -A
|
||||
;
|
||||
; c64scr.print_uw(W)
|
||||
; c64scr.print_b(A)
|
||||
; c64.CHROUT('\n')
|
||||
;
|
||||
; W = W as ubyte ; TODO cast(W as ubyte) as uword -> W and 255
|
||||
; c64scr.print_uw(W)
|
||||
; U = ~U
|
||||
; c64scr.print_ubhex(U, true)
|
||||
; c64.CHROUT('\n')
|
||||
; U = not U
|
||||
; c64scr.print_ubhex(U, true)
|
||||
; c64.CHROUT('\n')
|
||||
; U = not U
|
||||
; c64scr.print_ubhex(U, true)
|
||||
; c64.CHROUT('\n')
|
||||
;
|
||||
; c64scr.print_w(B)
|
||||
; c64.CHROUT('\n')
|
||||
; B = -B
|
||||
; c64scr.print_w(B)
|
||||
; c64.CHROUT('\n')
|
||||
;
|
||||
; W = ~W
|
||||
; c64scr.print_uwhex(W, true)
|
||||
; c64.CHROUT('\n')
|
||||
; W = not W
|
||||
; c64scr.print_uwhex(W, true)
|
||||
; c64.CHROUT('\n')
|
||||
; W = not W
|
||||
; c64scr.print_uwhex(W, true)
|
||||
; c64.CHROUT('\n')
|
||||
|
||||
uword W = 43210
|
||||
W = W as ubyte
|
||||
c64scr.print_uw(W)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
ubyte[] array = [1,2,3]
|
||||
array[1] = array[1] as ubyte
|
||||
W = array[0]
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user