avoid impossible type casts

This commit is contained in:
Irmen de Jong 2019-01-04 02:30:59 +01:00
parent e033cff09a
commit 526b28caa7
5 changed files with 77 additions and 65 deletions

View File

@ -2,78 +2,68 @@
%option enable_floats %option enable_floats
~ spritedata $0a00 {
; this memory block contains the sprite data
; it must start on an address aligned to 64 bytes.
%option force_output ; make sure the data in this block appears in the resulting program
ubyte[63] balloonsprite = [ %00000000,%01111111,%00000000,
%00000001,%11111111,%11000000,
%00000011,%11111111,%11100000,
%00000011,%11100011,%11100000,
%00000111,%11011100,%11110000,
%00000111,%11011101,%11110000,
%00000111,%11011100,%11110000,
%00000011,%11100011,%11100000,
%00000011,%11111111,%11100000,
%00000011,%11111111,%11100000,
%00000010,%11111111,%10100000,
%00000001,%01111111,%01000000,
%00000001,%00111110,%01000000,
%00000000,%10011100,%10000000,
%00000000,%10011100,%10000000,
%00000000,%01001001,%00000000,
%00000000,%01001001,%00000000,
%00000000,%00111110,%00000000,
%00000000,%00111110,%00000000,
%00000000,%00111110,%00000000,
%00000000,%00011100,%00000000 ]
}
~ main { ~ main {
const uword SP0X = $d000
const uword SP0Y = $d001
sub start() { sub start() {
ubyte i=0
c64.STROUT("balloon sprites!\n")
c64.STROUT("...we are all floating...\n")
const uword sprite_address_ptr = $0a00 // 64 repeat {
c64.SPRPTR0 = sprite_address_ptr c64scr.print_ub(X)
c64.SPRPTR1 = sprite_address_ptr c64.CHROUT('\n')
c64.SPRPTR2 = sprite_address_ptr ubyte ubx = fastsin8(i) as ubyte
c64.SPRPTR3 = sprite_address_ptr c64scr.print_ub(X)
c64.SPRPTR4 = sprite_address_ptr c64.CHROUT('\n')
c64.SPRPTR5 = sprite_address_ptr ;c64scr.print_ub(X)
c64.SPRPTR6 = sprite_address_ptr ;byte y = fastcos8(i)
c64.SPRPTR7 = sprite_address_ptr c64scr.print_ub(ubx)
;c64.CHROUT(',')
for ubyte i in 0 to 7 { ;c64scr.print_b(y)
@(SP0X+i*2) = 50+25*i c64.CHROUT('\n')
@(SP0Y+i*2) = rnd() i++
} } until i==0
c64.SPENA = 255 ; enable all sprites
c64utils.set_rasterirq(51) ; enable animation
} }
}
~ irq { asmsub fastsin8(ubyte angle8 @ Y) -> clobbers() -> (byte @ A) {
sub irq() { %asm {{
c64.EXTCOL-- lda sinecos8hi,y
; float up & wobble horizontally ;sta prog8_lib.ESTACK_LO,x
for ubyte i in 0 to 14 step 2 { ;dex
@(main.SP0Y+i)-- rts
ubyte r = rnd() }}
if r>200
@(main.SP0X+i)++
else if r<40
@(main.SP0X+i)--
}
c64.EXTCOL++
} }
asmsub fastcos8(ubyte angle8 @ Y) -> clobbers() -> (byte @ A) {
%asm {{
lda sinecos8hi+64,y
rts
}}
}
asmsub fastsin16(ubyte angle8 @ Y) -> clobbers() -> (word @ AY) {
%asm {{
lda sinecos8lo,y
pha
lda sinecos8hi,y
tay
pla
rts
}}
}
asmsub fastcos16(ubyte angle8 @ Y) -> clobbers() -> (word @ AY) {
%asm {{
lda sinecos8lo+64,y
pha
lda sinecos8hi+64,y
tay
pla
rts
}}
}
%asm {{
_ := 32767.5 * sin(range(256+64) * rad(360.0/256.0))
sinecos8lo .byte <_
sinecos8hi .byte >_
}}
} }

View File

@ -712,6 +712,14 @@ class AstChecker(private val namespace: INameScope,
return super.process(expr) return super.process(expr)
} }
override fun process(typecast: TypecastExpression): IExpression {
val funcTarget = (typecast.expression as? IFunctionCall)?.target?.targetStatement(namespace)
if(funcTarget is Subroutine && funcTarget.asmReturnvaluesRegisters.isNotEmpty()) {
checkResult.add(ExpressionError("cannot type cast a call to an asmsub that returns value in register - use a variable to store it first", typecast.position))
}
return super.process(typecast)
}
override fun process(range: RangeExpr): IExpression { override fun process(range: RangeExpr): IExpression {
fun err(msg: String) { fun err(msg: String) {
checkResult.add(SyntaxError(msg, range.position)) checkResult.add(SyntaxError(msg, range.position))

View File

@ -2044,6 +2044,11 @@ private class StatementTranslator(private val prog: IntermediateProgram,
} }
private fun translate(expr: TypecastExpression) { private fun translate(expr: TypecastExpression) {
val funcTarget = (expr.expression as? IFunctionCall)?.target?.targetStatement(namespace)
if(funcTarget is Subroutine && funcTarget.asmReturnvaluesRegisters.isNotEmpty()) {
throw CompilerException("cannot type cast a call to an asmsub that returns value in register - use a variable to store it first")
}
translate(expr.expression) translate(expr.expression)
val sourceDt = expr.expression.resultingDatatype(namespace, heap) ?: throw CompilerException("don't know what type to cast") val sourceDt = expr.expression.resultingDatatype(namespace, heap) ?: throw CompilerException("don't know what type to cast")
if(sourceDt==expr.type) if(sourceDt==expr.type)

View File

@ -337,13 +337,20 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
} }
currentBlock.variables[scopedname] = value currentBlock.variables[scopedname] = value
} }
VarDeclType.MEMORY, VarDeclType.CONST -> { VarDeclType.MEMORY -> {
// note that constants are all folded away, but assembly code may still refer to them // note that constants are all folded away, but assembly code may still refer to them
val lv = decl.value as LiteralValue val lv = decl.value as LiteralValue
if(lv.type!=DataType.UWORD && lv.type!=DataType.UBYTE) if(lv.type!=DataType.UWORD && lv.type!=DataType.UBYTE)
throw CompilerException("expected integer memory address $lv") throw CompilerException("expected integer memory address $lv")
currentBlock.memoryPointers[scopedname] = Pair(lv.asIntegerValue!!, decl.datatype) currentBlock.memoryPointers[scopedname] = Pair(lv.asIntegerValue!!, decl.datatype)
} }
VarDeclType.CONST -> {
// note that constants are all folded away, but assembly code may still refer to them (if their integers)
// floating point constants are not generated at all!!
val lv = decl.value as LiteralValue
if(lv.type in IntegerDatatypes)
currentBlock.memoryPointers[scopedname] = Pair(lv.asIntegerValue!!, decl.datatype)
}
} }
} }

View File

@ -529,6 +529,8 @@ _raster_irq_handler
~ c64flt { ~ c64flt {
; ---- this block contains C-64 floating point related functions ---- ; ---- this block contains C-64 floating point related functions ----
; @todo move to c64fp.p8 and enable float-checkin astchecker.process(decl: VarDecl) again ; @todo move to c64fp.p8 and enable float-checkin astchecker.process(decl: VarDecl) again
const float PI = 3.141592653589793
asmsub FREADS32 () -> clobbers(A,X,Y) -> () { asmsub FREADS32 () -> clobbers(A,X,Y) -> () {