mirror of
https://github.com/irmen/prog8.git
synced 2024-06-01 06:41:42 +00:00
- floats: remove all floating point builtin functions and move them to the floats module instead
This commit is contained in:
parent
88b55ab93e
commit
7eea97d741
|
@ -84,10 +84,6 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
|
|||
"swap" -> funcSwap(fcall)
|
||||
"any", "all" -> funcAnyAll(fcall, func, resultToStack, resultRegister, sscope)
|
||||
"sgn" -> funcSgn(fcall, func, resultToStack, resultRegister, sscope)
|
||||
"sin", "cos", "tan", "atan",
|
||||
"ln", "log2", "sqrt", "rad",
|
||||
"deg", "round", "floor", "ceil",
|
||||
"rndf" -> funcVariousFloatFuncs(fcall, func, resultToStack, resultRegister, sscope)
|
||||
"rnd", "rndw" -> funcRnd(func, resultToStack, resultRegister, sscope)
|
||||
"sqrt16" -> funcSqrt16(fcall, func, resultToStack, resultRegister, sscope)
|
||||
"rol" -> funcRol(fcall)
|
||||
|
@ -663,16 +659,6 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
|
|||
asmgen.assignExpressionToVariable(indexer.indexExpr, "prog8_lib.${operation}_array_u${dt}._arg_index", DataType.UBYTE, null)
|
||||
}
|
||||
|
||||
private fun funcVariousFloatFuncs(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, resultRegister: RegisterOrPair?, scope: Subroutine?) {
|
||||
translateArguments(fcall.args, func, scope)
|
||||
if(resultToStack)
|
||||
asmgen.out(" jsr floats.func_${func.name}_stack")
|
||||
else {
|
||||
asmgen.out(" jsr floats.func_${func.name}_fac1")
|
||||
assignAsmGen.assignFAC1float(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.FAC1, true, scope, program, asmgen))
|
||||
}
|
||||
}
|
||||
|
||||
private fun funcSgn(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, resultRegister: RegisterOrPair?, scope: Subroutine?) {
|
||||
translateArguments(fcall.args, func, scope)
|
||||
val dt = fcall.args.single().inferType(program)
|
||||
|
|
|
@ -18,19 +18,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||
"abs" -> funcAbs(call, resultRegister)
|
||||
"cmp" -> funcCmp(call)
|
||||
"sgn" -> funcSgn(call, resultRegister)
|
||||
"sin" -> TODO("floats not yet implemented")
|
||||
"cos" -> TODO("floats not yet implemented")
|
||||
"tan" -> TODO("floats not yet implemented")
|
||||
"atan" -> TODO("floats not yet implemented")
|
||||
"ln" -> TODO("floats not yet implemented")
|
||||
"log2" -> TODO("floats not yet implemented")
|
||||
"sqrt16" -> funcSqrt16(call, resultRegister)
|
||||
"sqrt" -> TODO("floats not yet implemented")
|
||||
"rad" -> TODO("floats not yet implemented")
|
||||
"deg" -> TODO("floats not yet implemented")
|
||||
"round" -> TODO("floats not yet implemented")
|
||||
"floor" -> TODO("floats not yet implemented")
|
||||
"ceil" -> TODO("floats not yet implemented")
|
||||
"pop" -> funcPop(call)
|
||||
"popw" -> funcPopw(call)
|
||||
"push" -> funcPush(call)
|
||||
|
@ -41,7 +29,6 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||
"rrestorex" -> VmCodeChunk() // vm doesn't have registers to save/restore
|
||||
"rnd" -> funcRnd(resultRegister)
|
||||
"rndw" -> funcRndw(resultRegister)
|
||||
"rndf" -> TODO("floats not yet implemented")
|
||||
"callfar" -> throw AssemblyError("callfar() is for cx16 target only")
|
||||
"callrom" -> throw AssemblyError("callrom() is for cx16 target only")
|
||||
"syscall" -> funcSyscall(call)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
; Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
||||
|
||||
%option enable_floats
|
||||
%import floats_functions
|
||||
|
||||
floats {
|
||||
; ---- this block contains C-128 compatible floating point related functions ----
|
||||
|
@ -110,7 +111,6 @@ asmsub GIVUAYFAY (uword value @ AY) clobbers(A,X,Y) {
|
|||
}}
|
||||
}
|
||||
|
||||
|
||||
asmsub GIVAYFAY (uword value @ AY) clobbers(A,X,Y) {
|
||||
; ---- signed 16 bit word in A/Y (lo/hi) to float in fac1
|
||||
%asm {{
|
||||
|
@ -151,55 +151,6 @@ asmsub FREADUY (ubyte value @Y) {
|
|||
}}
|
||||
}
|
||||
|
||||
sub print_f (float value) {
|
||||
; ---- prints the floating point value (without a newline).
|
||||
%asm {{
|
||||
stx P8ZP_SCRATCH_REG
|
||||
lda #<value
|
||||
ldy #>value
|
||||
jsr MOVFM ; load float into fac1
|
||||
jsr FOUT ; fac1 to string in A/Y
|
||||
sta P8ZP_SCRATCH_W1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
ldy #0
|
||||
- lda (P8ZP_SCRATCH_W1),y
|
||||
beq +
|
||||
jsr c64.CHROUT
|
||||
iny
|
||||
bne -
|
||||
+ ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
sub pow(float value, float power) -> float {
|
||||
%asm {{
|
||||
phx
|
||||
phy
|
||||
lda #<value
|
||||
ldy #>value
|
||||
jsr floats.CONUPK
|
||||
lda #<power
|
||||
ldy #>power
|
||||
jsr floats.FPWR
|
||||
ply
|
||||
plx
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
sub fabs(float value) -> float {
|
||||
%asm {{
|
||||
phx
|
||||
lda #<value
|
||||
ldy #>value
|
||||
jsr MOVFM
|
||||
jsr ABS
|
||||
plx
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
|
||||
%asminclude "library:c128/floats.asm"
|
||||
%asminclude "library:c64/floats_funcs.asm"
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
; indent format: TABS, size=8
|
||||
|
||||
%option enable_floats
|
||||
%import floats_functions
|
||||
|
||||
floats {
|
||||
; ---- this block contains C-64 floating point related functions ----
|
||||
|
@ -91,7 +92,6 @@ romsub $e2b4 = TAN() clobbers(A,X,Y) ; fac1 = TAN(fac1)
|
|||
romsub $e30e = ATN() clobbers(A,X,Y) ; fac1 = ATN(fac1)
|
||||
|
||||
|
||||
|
||||
asmsub FREADS32() clobbers(A,X,Y) {
|
||||
; ---- fac1 = signed int32 from $62-$65 big endian (MSB FIRST)
|
||||
%asm {{
|
||||
|
@ -174,54 +174,6 @@ asmsub GETADRAY () clobbers(X) -> uword @ AY {
|
|||
}}
|
||||
}
|
||||
|
||||
sub print_f (float value) {
|
||||
; ---- prints the floating point value (without a newline).
|
||||
%asm {{
|
||||
stx floats_store_reg
|
||||
lda #<value
|
||||
ldy #>value
|
||||
jsr MOVFM ; load float into fac1
|
||||
jsr FOUT ; fac1 to string in A/Y
|
||||
sta P8ZP_SCRATCH_W1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
ldy #0
|
||||
- lda (P8ZP_SCRATCH_W1),y
|
||||
beq +
|
||||
jsr c64.CHROUT
|
||||
iny
|
||||
bne -
|
||||
+ ldx floats_store_reg
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
sub pow(float value, float power) -> float {
|
||||
%asm {{
|
||||
phx
|
||||
phy
|
||||
lda #<value
|
||||
ldy #>value
|
||||
jsr floats.CONUPK
|
||||
lda #<power
|
||||
ldy #>power
|
||||
jsr floats.FPWR
|
||||
ply
|
||||
plx
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
sub fabs(float value) -> float {
|
||||
%asm {{
|
||||
phx
|
||||
lda #<value
|
||||
ldy #>value
|
||||
jsr MOVFM
|
||||
jsr ABS
|
||||
plx
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
%asminclude "library:c64/floats.asm"
|
||||
%asminclude "library:c64/floats_funcs.asm"
|
||||
|
|
|
@ -1,175 +1,6 @@
|
|||
; --- floating point builtin functions
|
||||
|
||||
|
||||
func_atan_stack .proc
|
||||
jsr func_atan_fac1
|
||||
jmp push_fac1
|
||||
.pend
|
||||
|
||||
func_atan_fac1 .proc
|
||||
jsr MOVFM
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr ATN
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
.pend
|
||||
|
||||
func_ceil_stack .proc
|
||||
jsr func_ceil_fac1
|
||||
jmp push_fac1
|
||||
.pend
|
||||
|
||||
func_ceil_fac1 .proc
|
||||
; -- ceil: tr = int(f); if tr==f -> return else return tr+1
|
||||
jsr MOVFM
|
||||
stx P8ZP_SCRATCH_REG
|
||||
ldx #<fmath_float1
|
||||
ldy #>fmath_float1
|
||||
jsr MOVMF
|
||||
jsr INT
|
||||
lda #<fmath_float1
|
||||
ldy #>fmath_float1
|
||||
jsr FCOMP
|
||||
cmp #0
|
||||
beq +
|
||||
lda #<FL_ONE_const
|
||||
ldy #>FL_ONE_const
|
||||
jsr FADD
|
||||
+ ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
.pend
|
||||
|
||||
func_floor_stack .proc
|
||||
jsr func_floor_fac1
|
||||
jmp push_fac1
|
||||
.pend
|
||||
|
||||
func_floor_fac1 .proc
|
||||
jsr MOVFM
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr INT
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
.pend
|
||||
|
||||
func_round_stack .proc
|
||||
jsr func_round_fac1
|
||||
jmp push_fac1
|
||||
.pend
|
||||
|
||||
func_round_fac1 .proc
|
||||
jsr MOVFM
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr FADDH
|
||||
jsr INT
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
.pend
|
||||
|
||||
func_sin_stack .proc
|
||||
jsr func_sin_fac1
|
||||
jmp push_fac1
|
||||
.pend
|
||||
|
||||
func_sin_fac1 .proc
|
||||
jsr MOVFM
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr SIN
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
.pend
|
||||
|
||||
func_cos_stack .proc
|
||||
jsr func_cos_fac1
|
||||
jmp push_fac1
|
||||
.pend
|
||||
|
||||
func_cos_fac1 .proc
|
||||
jsr MOVFM
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr COS
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
.pend
|
||||
|
||||
func_tan_stack .proc
|
||||
jsr func_tan_fac1
|
||||
jmp push_fac1
|
||||
.pend
|
||||
|
||||
func_tan_fac1 .proc
|
||||
jsr MOVFM
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr TAN
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
.pend
|
||||
|
||||
func_rad_stack .proc
|
||||
jsr func_rad_fac1
|
||||
jmp push_fac1
|
||||
.pend
|
||||
|
||||
func_rad_fac1 .proc
|
||||
; -- convert degrees to radians (d * pi / 180)
|
||||
jsr MOVFM
|
||||
stx P8ZP_SCRATCH_REG
|
||||
lda #<_pi_div_180
|
||||
ldy #>_pi_div_180
|
||||
jsr FMULT
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
_pi_div_180 .byte 123, 14, 250, 53, 18 ; pi / 180
|
||||
.pend
|
||||
|
||||
func_deg_stack .proc
|
||||
jsr func_deg_fac1
|
||||
jmp push_fac1
|
||||
.pend
|
||||
|
||||
func_deg_fac1 .proc
|
||||
; -- convert radians to degrees (d * (1/ pi * 180))
|
||||
jsr MOVFM
|
||||
stx P8ZP_SCRATCH_REG
|
||||
lda #<_one_over_pi_div_180
|
||||
ldy #>_one_over_pi_div_180
|
||||
jsr FMULT
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
_one_over_pi_div_180 .byte 134, 101, 46, 224, 211 ; 1 / (pi * 180)
|
||||
.pend
|
||||
|
||||
func_ln_stack .proc
|
||||
jsr func_ln_fac1
|
||||
jmp push_fac1
|
||||
.pend
|
||||
|
||||
func_ln_fac1 .proc
|
||||
jsr MOVFM
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr LOG
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
.pend
|
||||
|
||||
func_log2_stack .proc
|
||||
jsr func_log2_fac1
|
||||
jmp push_fac1
|
||||
.pend
|
||||
|
||||
func_log2_fac1 .proc
|
||||
jsr MOVFM
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr LOG
|
||||
jsr MOVEF
|
||||
lda #<FL_LOG2_const
|
||||
ldy #>FL_LOG2_const
|
||||
jsr MOVFM
|
||||
jsr FDIVT
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
.pend
|
||||
|
||||
func_sign_f_stack .proc
|
||||
jsr func_sign_f_into_A
|
||||
sta P8ESTACK_LO,x
|
||||
|
@ -182,33 +13,6 @@ func_sign_f_into_A .proc
|
|||
jmp SIGN
|
||||
.pend
|
||||
|
||||
func_sqrt_stack .proc
|
||||
jsr func_sqrt_fac1
|
||||
jmp push_fac1
|
||||
.pend
|
||||
|
||||
func_sqrt_fac1 .proc
|
||||
jsr MOVFM
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr SQR
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
.pend
|
||||
|
||||
func_rndf_stack .proc
|
||||
jsr func_rndf_fac1
|
||||
jmp push_fac1
|
||||
.pend
|
||||
|
||||
func_rndf_fac1 .proc
|
||||
stx P8ZP_SCRATCH_REG
|
||||
lda #1
|
||||
jsr FREADSA
|
||||
jsr RND ; rng into fac1
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
.pend
|
||||
|
||||
func_swap_f .proc
|
||||
; -- swap floats pointed to by SCRATCH_ZPWORD1, SCRATCH_ZPWORD2
|
||||
ldy #4
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
; indent format: TABS, size=8
|
||||
|
||||
%option enable_floats
|
||||
%import floats_functions
|
||||
|
||||
floats {
|
||||
; ---- this block contains C-64 compatible floating point related functions ----
|
||||
|
@ -110,7 +111,6 @@ asmsub GIVUAYFAY (uword value @ AY) clobbers(A,X,Y) {
|
|||
}}
|
||||
}
|
||||
|
||||
|
||||
asmsub GIVAYFAY (uword value @ AY) clobbers(A,X,Y) {
|
||||
; ---- signed 16 bit word in A/Y (lo/hi) to float in fac1
|
||||
%asm {{
|
||||
|
@ -151,7 +151,6 @@ asmsub FREADUY (ubyte value @Y) {
|
|||
}}
|
||||
}
|
||||
|
||||
|
||||
asmsub RND() clobbers(A,X,Y) {
|
||||
%asm {{
|
||||
lda #0
|
||||
|
@ -163,55 +162,6 @@ asmsub RND() clobbers(A,X,Y) {
|
|||
}
|
||||
|
||||
|
||||
sub print_f (float value) {
|
||||
; ---- prints the floating point value (without a newline).
|
||||
%asm {{
|
||||
phx
|
||||
lda #<value
|
||||
ldy #>value
|
||||
jsr MOVFM ; load float into fac1
|
||||
jsr FOUT ; fac1 to string in A/Y
|
||||
sta P8ZP_SCRATCH_W1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
ldy #0
|
||||
- lda (P8ZP_SCRATCH_W1),y
|
||||
beq +
|
||||
jsr c64.CHROUT
|
||||
iny
|
||||
bne -
|
||||
+ plx
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
sub pow(float value, float power) -> float {
|
||||
%asm {{
|
||||
phx
|
||||
phy
|
||||
lda #<value
|
||||
ldy #>value
|
||||
jsr floats.CONUPK
|
||||
lda #<power
|
||||
ldy #>power
|
||||
jsr floats.FPWR
|
||||
ply
|
||||
plx
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
sub fabs(float value) -> float {
|
||||
%asm {{
|
||||
phx
|
||||
lda #<value
|
||||
ldy #>value
|
||||
jsr MOVFM
|
||||
jsr ABS
|
||||
plx
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
%asminclude "library:c64/floats.asm"
|
||||
%asminclude "library:c64/floats_funcs.asm"
|
||||
|
||||
|
|
235
compiler/res/prog8lib/floats_functions.p8
Normal file
235
compiler/res/prog8lib/floats_functions.p8
Normal file
|
@ -0,0 +1,235 @@
|
|||
floats {
|
||||
; the floating point functions shared across compiler targets
|
||||
%option merge
|
||||
|
||||
sub print_f(float value) {
|
||||
; ---- prints the floating point value (without a newline).
|
||||
%asm {{
|
||||
stx floats_store_reg
|
||||
lda #<value
|
||||
ldy #>value
|
||||
jsr MOVFM ; load float into fac1
|
||||
jsr FOUT ; fac1 to string in A/Y
|
||||
sta P8ZP_SCRATCH_W1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
ldy #0
|
||||
- lda (P8ZP_SCRATCH_W1),y
|
||||
beq +
|
||||
jsr c64.CHROUT
|
||||
iny
|
||||
bne -
|
||||
+ ldx floats_store_reg
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
sub pow(float value, float power) -> float {
|
||||
%asm {{
|
||||
phx
|
||||
phy
|
||||
lda #<value
|
||||
ldy #>value
|
||||
jsr floats.CONUPK
|
||||
lda #<power
|
||||
ldy #>power
|
||||
jsr floats.FPWR
|
||||
ply
|
||||
plx
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
sub fabs(float value) -> float {
|
||||
%asm {{
|
||||
phx
|
||||
lda #<value
|
||||
ldy #>value
|
||||
jsr MOVFM
|
||||
jsr ABS
|
||||
plx
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
sub sin(float angle) -> float {
|
||||
%asm {{
|
||||
lda #<angle
|
||||
ldy #>angle
|
||||
jsr MOVFM
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr SIN
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
sub cos(float angle) -> float {
|
||||
%asm {{
|
||||
lda #<angle
|
||||
ldy #>angle
|
||||
jsr MOVFM
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr COS
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
sub tan(float value) -> float {
|
||||
%asm {{
|
||||
lda #<value
|
||||
ldy #>value
|
||||
jsr MOVFM
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr TAN
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
sub atan(float value) -> float {
|
||||
%asm {{
|
||||
lda #<value
|
||||
ldy #>value
|
||||
jsr MOVFM
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr ATN
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
sub ln(float value) -> float {
|
||||
%asm {{
|
||||
lda #<value
|
||||
ldy #>value
|
||||
jsr MOVFM
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr LOG
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
sub log2(float value) -> float {
|
||||
%asm {{
|
||||
lda #<value
|
||||
ldy #>value
|
||||
jsr MOVFM
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr LOG
|
||||
jsr MOVEF
|
||||
lda #<FL_LOG2_const
|
||||
ldy #>FL_LOG2_const
|
||||
jsr MOVFM
|
||||
jsr FDIVT
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
sub sqrt(float value) -> float {
|
||||
%asm {{
|
||||
lda #<value
|
||||
ldy #>value
|
||||
jsr MOVFM
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr SQR
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
sub rad(float angle) -> float {
|
||||
; -- convert degrees to radians (d * pi / 180)
|
||||
%asm {{
|
||||
lda #<angle
|
||||
ldy #>angle
|
||||
jsr MOVFM
|
||||
stx P8ZP_SCRATCH_REG
|
||||
lda #<_pi_div_180
|
||||
ldy #>_pi_div_180
|
||||
jsr FMULT
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
_pi_div_180 .byte 123, 14, 250, 53, 18 ; pi / 180
|
||||
}}
|
||||
}
|
||||
|
||||
sub deg(float angle) -> float {
|
||||
; -- convert radians to degrees (d * (1/ pi * 180))
|
||||
%asm {{
|
||||
lda #<angle
|
||||
ldy #>angle
|
||||
jsr MOVFM
|
||||
stx P8ZP_SCRATCH_REG
|
||||
lda #<_one_over_pi_div_180
|
||||
ldy #>_one_over_pi_div_180
|
||||
jsr FMULT
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
_one_over_pi_div_180 .byte 134, 101, 46, 224, 211 ; 1 / (pi * 180)
|
||||
}}
|
||||
}
|
||||
|
||||
sub round(float value) -> float {
|
||||
%asm {{
|
||||
lda #<value
|
||||
ldy #>value
|
||||
jsr MOVFM
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr FADDH
|
||||
jsr INT
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
sub floor(float value) -> float {
|
||||
%asm {{
|
||||
lda #<value
|
||||
ldy #>value
|
||||
jsr MOVFM
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr INT
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
sub ceil(float value) -> float {
|
||||
; -- ceil: tr = int(f); if tr==f -> return else return tr+1
|
||||
%asm {{
|
||||
lda #<value
|
||||
ldy #>value
|
||||
jsr MOVFM
|
||||
stx P8ZP_SCRATCH_REG
|
||||
ldx #<fmath_float1
|
||||
ldy #>fmath_float1
|
||||
jsr MOVMF
|
||||
jsr INT
|
||||
lda #<fmath_float1
|
||||
ldy #>fmath_float1
|
||||
jsr FCOMP
|
||||
cmp #0
|
||||
beq +
|
||||
lda #<FL_ONE_const
|
||||
ldy #>FL_ONE_const
|
||||
jsr FADD
|
||||
+ ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
sub rndf() -> float {
|
||||
%asm {{
|
||||
stx P8ZP_SCRATCH_REG
|
||||
lda #1
|
||||
jsr FREADSA
|
||||
jsr RND ; rng into fac1
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
}
|
|
@ -41,6 +41,7 @@ main {
|
|||
"syslib",
|
||||
"conv",
|
||||
"floats",
|
||||
"floats_functions",
|
||||
"math",
|
||||
"prog8_lib"
|
||||
)
|
||||
|
@ -97,7 +98,7 @@ main {
|
|||
listOf(
|
||||
internedStringsModuleName,
|
||||
filenameBase,
|
||||
"textio", "syslib", "conv", "floats", "math", "prog8_lib"
|
||||
"textio", "syslib", "conv", "floats", "floats_functions", "math", "prog8_lib"
|
||||
)
|
||||
}
|
||||
options.floats shouldBe true
|
||||
|
|
|
@ -98,19 +98,7 @@ private val functionSignatures: List<FSignature> = listOf(
|
|||
// normal functions follow:
|
||||
FSignature("sizeof" , true, listOf(FParam("object", DataType.values())), DataType.UBYTE, ::builtinSizeof),
|
||||
FSignature("sgn" , true, listOf(FParam("value", NumericDatatypes)), DataType.BYTE, ::builtinSgn ),
|
||||
FSignature("sin" , true, listOf(FParam("rads", arrayOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::sin) },
|
||||
FSignature("cos" , true, listOf(FParam("rads", arrayOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::cos) },
|
||||
FSignature("tan" , true, listOf(FParam("rads", arrayOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::tan) },
|
||||
FSignature("atan" , true, listOf(FParam("rads", arrayOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::atan) },
|
||||
FSignature("ln" , true, listOf(FParam("value", arrayOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::log) },
|
||||
FSignature("log2" , true, listOf(FParam("value", arrayOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, ::log2) },
|
||||
FSignature("sqrt16" , true, listOf(FParam("value", arrayOf(DataType.UWORD))), DataType.UBYTE) { a, p, prg -> oneIntArgOutputInt(a, p, prg) { sqrt(it.toDouble()) } },
|
||||
FSignature("sqrt" , true, listOf(FParam("value", arrayOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::sqrt) },
|
||||
FSignature("rad" , true, listOf(FParam("value", arrayOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::toRadians) },
|
||||
FSignature("deg" , true, listOf(FParam("value", arrayOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::toDegrees) },
|
||||
FSignature("round" , true, listOf(FParam("value", arrayOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArgOutputWord(a, p, prg, ::round) },
|
||||
FSignature("floor" , true, listOf(FParam("value", arrayOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArgOutputWord(a, p, prg, Math::floor) },
|
||||
FSignature("ceil" , true, listOf(FParam("value", arrayOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArgOutputWord(a, p, prg, Math::ceil) },
|
||||
FSignature("any" , true, listOf(FParam("values", ArrayDatatypes)), DataType.UBYTE) { a, p, prg -> collectionArg(a, p, prg, ::builtinAny) },
|
||||
FSignature("all" , true, listOf(FParam("values", ArrayDatatypes)), DataType.UBYTE) { a, p, prg -> collectionArg(a, p, prg, ::builtinAll) },
|
||||
FSignature("lsb" , true, listOf(FParam("value", arrayOf(DataType.UWORD, DataType.WORD))), DataType.UBYTE) { a, p, prg -> oneIntArgOutputInt(a, p, prg) { x: Int -> (x and 255).toDouble() } },
|
||||
|
@ -131,7 +119,6 @@ private val functionSignatures: List<FSignature> = listOf(
|
|||
FSignature("rrestorex" , false, emptyList(), null),
|
||||
FSignature("rnd" , false, emptyList(), DataType.UBYTE),
|
||||
FSignature("rndw" , false, emptyList(), DataType.UWORD),
|
||||
FSignature("rndf" , false, emptyList(), DataType.FLOAT),
|
||||
FSignature("memory" , true, listOf(FParam("name", arrayOf(DataType.STR)), FParam("size", arrayOf(DataType.UWORD)), FParam("alignment", arrayOf(DataType.UWORD))), DataType.UWORD),
|
||||
FSignature("swap" , false, listOf(FParam("first", NumericDatatypes), FParam("second", NumericDatatypes)), null),
|
||||
FSignature("callfar" , false, listOf(FParam("bank", arrayOf(DataType.UBYTE)), FParam("address", arrayOf(DataType.UWORD)), FParam("arg", arrayOf(DataType.UWORD))), null),
|
||||
|
|
|
@ -193,7 +193,52 @@ floats
|
|||
------
|
||||
Provides definitions for the ROM/kernal subroutines and utility routines dealing with floating
|
||||
point variables. This includes ``print_f``, the routine used to print floating point numbers,
|
||||
``fabs`` to get the absolute value of a floating point number, and some others.
|
||||
``fabs`` to get the absolute value of a floating point number, and a dozen or so floating point
|
||||
math routines.
|
||||
|
||||
atan(x)
|
||||
Arctangent.
|
||||
|
||||
ceil(x)
|
||||
Rounds the floating point up to an integer towards positive infinity.
|
||||
|
||||
cos(x)
|
||||
Cosine.
|
||||
If you want a fast integer cosine, have a look at examples/cx16/sincos.p8
|
||||
that contains various lookup tables generated by the 64tass assembler.
|
||||
|
||||
deg(x)
|
||||
Radians to degrees.
|
||||
|
||||
floor (x)
|
||||
Rounds the floating point down to an integer towards minus infinity.
|
||||
|
||||
ln(x)
|
||||
Natural logarithm (base e).
|
||||
|
||||
log2(x)
|
||||
Base 2 logarithm.
|
||||
|
||||
rad(x)
|
||||
Degrees to radians.
|
||||
|
||||
round(x)
|
||||
Rounds the floating point to the closest integer.
|
||||
|
||||
sin(x)
|
||||
Sine.
|
||||
If you want a fast integer sine, have a look at examples/cx16/sincos.p8
|
||||
that contains various lookup tables generated by the 64tass assembler.
|
||||
|
||||
sqrt(x)
|
||||
Floating point Square root.
|
||||
To do the reverse, squaring a floating point number, just write ``x*x`` or ``x**2``.
|
||||
|
||||
tan(x)
|
||||
Tangent.
|
||||
|
||||
rndf()
|
||||
returns a pseudo-random float between 0.0 and 1.0
|
||||
|
||||
|
||||
graphics
|
||||
|
|
|
@ -738,40 +738,6 @@ Math
|
|||
abs(x)
|
||||
Absolute value of an integer. For floating point numbers, use ``floats.fabs()`` instead.
|
||||
|
||||
atan(x)
|
||||
Arctangent.
|
||||
|
||||
ceil(x)
|
||||
Rounds the floating point up to an integer towards positive infinity.
|
||||
|
||||
cos(x)
|
||||
Cosine. (floating point)
|
||||
If you want a fast integer cosine, have a look at examples/cx16/sincos.p8
|
||||
that contains various lookup tables generated by the 64tass assembler.
|
||||
|
||||
deg(x)
|
||||
Radians to degrees.
|
||||
|
||||
floor (x)
|
||||
Rounds the floating point down to an integer towards minus infinity.
|
||||
|
||||
ln(x)
|
||||
Natural logarithm (base e).
|
||||
|
||||
log2(x)
|
||||
Base 2 logarithm.
|
||||
|
||||
rad(x)
|
||||
Degrees to radians.
|
||||
|
||||
round(x)
|
||||
Rounds the floating point to the closest integer.
|
||||
|
||||
sin(x)
|
||||
Sine. (floating point)
|
||||
If you want a fast integer sine, have a look at examples/cx16/sincos.p8
|
||||
that contains various lookup tables generated by the 64tass assembler.
|
||||
|
||||
sgn(x)
|
||||
Get the sign of the value. Result is -1, 0 or 1 (negative, zero, positive).
|
||||
|
||||
|
@ -779,13 +745,6 @@ sqrt16(w)
|
|||
16 bit unsigned integer Square root. Result is unsigned byte.
|
||||
To do the reverse, squaring an integer, just write ``x*x``.
|
||||
|
||||
sqrt(x)
|
||||
Floating point Square root.
|
||||
To do the reverse, squaring a floating point number, just write ``x*x`` or ``x**2``.
|
||||
|
||||
tan(x)
|
||||
Tangent.
|
||||
|
||||
|
||||
Array operations
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
@ -877,9 +836,6 @@ rnd()
|
|||
rndw()
|
||||
returns a pseudo-random word from 0..65535
|
||||
|
||||
rndf()
|
||||
returns a pseudo-random float between 0.0 and 1.0
|
||||
|
||||
rol(x)
|
||||
Rotate the bits in x (byte or word) one position to the left.
|
||||
This uses the CPU's rotate semantics: bit 0 will be set to the current value of the Carry flag,
|
||||
|
|
|
@ -3,6 +3,7 @@ TODO
|
|||
|
||||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- %import inside a block/subroutine should give compilation error
|
||||
- pipe operator: allow non-unary function calls in the pipe that specify the other argument(s) in the calls.
|
||||
- createAssemblyAndAssemble(): make it possible to actually get rid of the VarDecl nodes by fixing the rest of the code mentioned there.
|
||||
- allow "xxx" * constexpr (where constexpr is not a number literal), now gives expression error not same type
|
||||
|
@ -11,8 +12,6 @@ For next release
|
|||
If we can do that why not perhaps also able to inline multi-line subroutines? Why would it be limited to just 1 line? Maybe to protect against code size bloat.
|
||||
Inlined subroutines cannot contain further nested subroutines!
|
||||
Once this works, look for library subroutines that should be inlined.
|
||||
- floats: remove all floating point builtin functions and move them to the floats module instead,
|
||||
note: first try to move only sin and cos and see if the various examples still work!
|
||||
|
||||
...
|
||||
|
||||
|
|
|
@ -46,12 +46,12 @@ main {
|
|||
; rotate around origin (0,0,0)
|
||||
|
||||
; set up the 3d rotation matrix values
|
||||
float cosa = cos(t)
|
||||
float sina = sin(t)
|
||||
float cosb = cos(t*0.33)
|
||||
float sinb = sin(t*0.33)
|
||||
float cosc = cos(t*0.78)
|
||||
float sinc = sin(t*0.78)
|
||||
float cosa = floats.cos(t)
|
||||
float sina = floats.sin(t)
|
||||
float cosb = floats.cos(t*0.33)
|
||||
float sinb = floats.sin(t*0.33)
|
||||
float cosc = floats.cos(t*0.78)
|
||||
float sinc = floats.sin(t*0.78)
|
||||
|
||||
float cosa_sinb = cosa*sinb
|
||||
float sina_sinb = sina*sinb
|
||||
|
|
|
@ -50,13 +50,13 @@ main {
|
|||
gfx2.monochrome_stipple(false)
|
||||
float y_f
|
||||
for ww in -600 to 600 {
|
||||
y_f = sin(ww as float / 60.0)*150
|
||||
y_f = floats.sin(ww as float / 60.0)*150
|
||||
gfx2.plot(ww/2 + 320 as uword, (y_f + 240) as uword, 1)
|
||||
}
|
||||
gfx2.text(480, 100, 1, sc:"sin(x)")
|
||||
|
||||
for ww in -300 to 300 {
|
||||
y_f = cos(ww as float/30.0)*60 - (ww as float)/1.7
|
||||
y_f = floats.cos(ww as float/30.0)*60 - (ww as float)/1.7
|
||||
gfx2.plot(ww + 320 as uword, (y_f + 240) as uword, 1)
|
||||
}
|
||||
gfx2.text(80, 420, 1, sc:"cos(x)+x")
|
||||
|
|
|
@ -12,8 +12,8 @@ main {
|
|||
ubyte ball_color
|
||||
|
||||
repeat {
|
||||
ubyte xx=(sin(ball_t) * txt.DEFAULT_WIDTH/2.1) + txt.DEFAULT_WIDTH/2.0 as ubyte
|
||||
ubyte yy=(cos(ball_t*1.1356) * txt.DEFAULT_HEIGHT/2.1) + txt.DEFAULT_HEIGHT/2.0 as ubyte
|
||||
ubyte xx=(floats.sin(ball_t) * txt.DEFAULT_WIDTH/2.1) + txt.DEFAULT_WIDTH/2.0 as ubyte
|
||||
ubyte yy=(floats.cos(ball_t*1.1356) * txt.DEFAULT_HEIGHT/2.1) + txt.DEFAULT_HEIGHT/2.0 as ubyte
|
||||
txt.setcc(xx, yy, 81, ball_color)
|
||||
ball_t += 0.08
|
||||
ball_color++
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
%import textio
|
||||
%import floats
|
||||
%zeropage dontuse
|
||||
|
||||
|
||||
|
@ -7,40 +8,36 @@
|
|||
main {
|
||||
sub start() {
|
||||
|
||||
ubyte ub = 234
|
||||
byte v1 = -10
|
||||
byte v2 = 20
|
||||
uword w3
|
||||
|
||||
byte v3 = abs(v1) as byte
|
||||
txt.print_b(v3)
|
||||
txt.spc()
|
||||
v3 = abs(v2) as byte
|
||||
txt.print_b(v3)
|
||||
txt.spc()
|
||||
w3 = abs(v1)
|
||||
txt.print_uw(w3)
|
||||
txt.spc()
|
||||
w3 = abs(v2)
|
||||
txt.print_uw(w3)
|
||||
txt.spc()
|
||||
w3 = abs(ub)
|
||||
txt.print_uw(w3)
|
||||
txt.nl()
|
||||
|
||||
txt.print_uw(abs(v1))
|
||||
txt.spc()
|
||||
txt.print_uw(abs(v2))
|
||||
txt.spc()
|
||||
txt.print_uw(abs(ub))
|
||||
txt.nl()
|
||||
|
||||
word sw1 = -12345
|
||||
w3 = abs(sw1)
|
||||
txt.print_uw(w3)
|
||||
txt.spc()
|
||||
txt.print_uw(abs(sw1))
|
||||
txt.nl()
|
||||
float f1 = 1.555
|
||||
floats.print_f(floats.sin(f1))
|
||||
txt.nl()
|
||||
floats.print_f(floats.cos(f1))
|
||||
txt.nl()
|
||||
floats.print_f(floats.tan(f1))
|
||||
txt.nl()
|
||||
floats.print_f(floats.atan(f1))
|
||||
txt.nl()
|
||||
floats.print_f(floats.ln(f1))
|
||||
txt.nl()
|
||||
floats.print_f(floats.log2(f1))
|
||||
txt.nl()
|
||||
floats.print_f(floats.sqrt(f1))
|
||||
txt.nl()
|
||||
floats.print_f(floats.rad(f1))
|
||||
txt.nl()
|
||||
floats.print_f(floats.deg(f1))
|
||||
txt.nl()
|
||||
floats.print_f(floats.round(f1))
|
||||
txt.nl()
|
||||
floats.print_f(floats.floor(f1))
|
||||
txt.nl()
|
||||
floats.print_f(floats.ceil(f1))
|
||||
txt.nl()
|
||||
floats.print_f(floats.rndf())
|
||||
txt.nl()
|
||||
; "sin", "cos", "tan", "atan",
|
||||
; "ln", "log2", "sqrt", "rad",
|
||||
; "deg", "round", "floor", "ceil", "rndf"
|
||||
|
||||
; ; a "pixelshader":
|
||||
; void syscall1(8, 0) ; enable lo res creen
|
||||
|
|
|
@ -65,8 +65,8 @@ turtle {
|
|||
float flen = length as float
|
||||
float sx = xpos
|
||||
float sy = ypos
|
||||
xpos += flen * sin(angle)
|
||||
ypos -= flen * cos(angle)
|
||||
xpos += flen * floats.sin(angle)
|
||||
ypos -= flen * floats.cos(angle)
|
||||
update_turtle_sprite()
|
||||
if pendown {
|
||||
graphics.line(sx as uword, sy as ubyte, xpos as uword, ypos as ubyte)
|
||||
|
@ -74,11 +74,11 @@ turtle {
|
|||
}
|
||||
|
||||
sub rt(uword degrees) {
|
||||
angle += rad(degrees as float)
|
||||
angle += floats.rad(degrees as float)
|
||||
}
|
||||
|
||||
sub lt(uword degrees) {
|
||||
angle -= rad(degrees as float)
|
||||
angle -= floats.rad(degrees as float)
|
||||
}
|
||||
|
||||
sub pu() {
|
||||
|
|
|
@ -4,4 +4,4 @@ org.gradle.parallel=true
|
|||
org.gradle.daemon=true
|
||||
kotlin.code.style=official
|
||||
javaVersion=11
|
||||
kotlinVersion=1.6.20
|
||||
kotlinVersion=1.6.21
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<filetype binary="false" description="Prog8 source file" name="Prog8">
|
||||
<filetype binary="false" default_extension="p8" description="Prog8 source file" name="Prog8">
|
||||
<highlighting>
|
||||
<options>
|
||||
<option name="LINE_COMMENT" value=";" />
|
||||
|
@ -14,10 +14,10 @@
|
|||
<keywords keywords="&;->;@;\$;and;as;asmsub;break;clobbers;do;downto;else;false;for;goto;if;if_cc;if_cs;if_eq;if_mi;if_ne;if_neg;if_nz;if_pl;if_pos;if_vc;if_vs;if_z;in;inline;not;or;repeat;return;romsub;step;sub;to;true;until;when;while;xor;~" ignore_case="false" />
|
||||
<keywords2 keywords="%address;%asm;%asmbinary;%asminclude;%breakpoint;%import;%launcher;%option;%output;%zeropage;%zpreserved;iso:;petscii:;sc:" />
|
||||
<keywords3 keywords="@requirezp;@shared;@zp;byte;const;float;str;ubyte;uword;void;word" />
|
||||
<keywords4 keywords="abs;acos;all;any;asin;atan;avg;callfar;callrom;ceil;cmp;cos;deg;floor;len;ln;log2;lsb;max;memory;min;mkword;msb;peek;peekw;poke;pokew;pop;popw;push;pushw;rad;reverse;rnd;rndf;rndw;rol;rol2;ror;ror2;round;rrestore;rrestorex;rsave;rsavex;sgn;sin;sizeof;sort;sqrt;sqrt16;sum;swap;tan;|>" />
|
||||
<keywords4 keywords="abs;all;any;avg;callfar;callrom;cmp;len;lsb;max;memory;min;mkword;msb;peek;peekw;poke;pokew;pop;popw;push;pushw;reverse;rnd;rndw;rol;rol2;ror;ror2;rrestore;rrestorex;rsave;rsavex;sgn;sizeof;sort;sqrt16;sum;swap;|>" />
|
||||
</highlighting>
|
||||
<extensionMap>
|
||||
<mapping ext="p8" />
|
||||
<mapping ext="prog8" />
|
||||
</extensionMap>
|
||||
</filetype>
|
||||
</filetype>
|
|
@ -27,7 +27,7 @@
|
|||
<Keywords name="Keywords1">void const
str
byte ubyte
word uword
float
zp shared requirezp</Keywords>
|
||||
<Keywords name="Keywords2">%address
%asm
%asmbinary
%asminclude
%breakpoint
%import
%launcher
%option
%output
%zeropage
%zpreserved</Keywords>
|
||||
<Keywords name="Keywords3">inline sub asmsub romsub
clobbers
asm
if
when else
if_cc if_cs if_eq if_mi if_neg if_nz if_pl if_pos if_vc if_vs if_z
for in step do while repeat
break return goto</Keywords>
|
||||
<Keywords name="Keywords4">abs acos all any asin atan avg callfar callrom ceil cmp cos deg floor len ln log2 lsb lsl lsr max memory min mkword msb peek peekw poke pokew push pushw pop popw rsave rsavex rrestore rrestorex rad reverse rnd rndf rndw rol rol2 ror ror2 round sgn sin sizeof sort sqrt sqrt16 sum swap tan</Keywords>
|
||||
<Keywords name="Keywords4">abs all any avg callfar callrom cmp len lsb lsl lsr max memory min mkword msb peek peekw poke pokew push pushw pop popw rsave rsavex rrestore rrestorex reverse rnd rndw rol rol2 ror ror2 sgn sizeof sort sqrt16 sum swap</Keywords>
|
||||
<Keywords name="Keywords5">true false
not and or xor
as to downto |></Keywords>
|
||||
<Keywords name="Keywords6"></Keywords>
|
||||
<Keywords name="Keywords7"></Keywords>
|
||||
|
|
|
@ -7,9 +7,7 @@
|
|||
" Built-in functions
|
||||
|
||||
" Math functions
|
||||
syn keyword prog8BuiltInFunc abs atan ceil cos deg floor
|
||||
syn keyword prog8BuiltInFunc ln log2 rad round sin sgn
|
||||
syn keyword prog8BuiltInFunc sqrt16 sqrt tan
|
||||
syn keyword prog8BuiltInFunc sgn sqrt16
|
||||
|
||||
" Array functions
|
||||
syn keyword prog8BuiltInFunc any all len max min reverse sum sort
|
||||
|
|
Loading…
Reference in New Issue
Block a user