mirror of
https://github.com/irmen/prog8.git
synced 2024-11-26 11:49:22 +00:00
abs() now works on multiple data types including float.
no need to use floats.fabs() anymore
This commit is contained in:
parent
319079de7a
commit
38efe25c68
@ -79,7 +79,10 @@ val BuiltinFunctions: Map<String, FSignature> = mapOf(
|
|||||||
// cmp returns a status in the carry flag, but not a proper return value
|
// cmp returns a status in the carry flag, but not a proper return value
|
||||||
"cmp" to FSignature(false, listOf(FParam("value1", IntegerDatatypesNoBool), FParam("value2", NumericDatatypesNoBool)), null),
|
"cmp" to FSignature(false, listOf(FParam("value1", IntegerDatatypesNoBool), FParam("value2", NumericDatatypesNoBool)), null),
|
||||||
"prog8_lib_stringcompare" to FSignature(true, listOf(FParam("str1", arrayOf(DataType.STR)), FParam("str2", arrayOf(DataType.STR))), DataType.BYTE),
|
"prog8_lib_stringcompare" to FSignature(true, listOf(FParam("str1", arrayOf(DataType.STR)), FParam("str2", arrayOf(DataType.STR))), DataType.BYTE),
|
||||||
"abs" to FSignature(true, listOf(FParam("value", IntegerDatatypesNoBool)), DataType.UWORD),
|
"abs" to FSignature(true, listOf(), null),
|
||||||
|
"abs__byte" to FSignature(true, listOf(FParam("value", arrayOf(DataType.BYTE))), DataType.BYTE),
|
||||||
|
"abs__word" to FSignature(true, listOf(FParam("value", arrayOf(DataType.WORD))), DataType.WORD),
|
||||||
|
"abs__float" to FSignature(true, listOf(FParam("value", arrayOf(DataType.FLOAT))), DataType.FLOAT),
|
||||||
"len" to FSignature(true, listOf(FParam("values", IterableDatatypes)), DataType.UWORD),
|
"len" to FSignature(true, listOf(FParam("values", IterableDatatypes)), DataType.UWORD),
|
||||||
// normal functions follow:
|
// normal functions follow:
|
||||||
"sizeof" to FSignature(true, listOf(FParam("object", DataType.values())), DataType.UBYTE),
|
"sizeof" to FSignature(true, listOf(FParam("object", DataType.values())), DataType.UBYTE),
|
||||||
|
@ -33,7 +33,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
|||||||
"mkword" -> funcMkword(fcall, resultToStack, resultRegister)
|
"mkword" -> funcMkword(fcall, resultToStack, resultRegister)
|
||||||
"min__byte", "min__ubyte", "min__word", "min__uword" -> funcMin(fcall, resultToStack, resultRegister)
|
"min__byte", "min__ubyte", "min__word", "min__uword" -> funcMin(fcall, resultToStack, resultRegister)
|
||||||
"max__byte", "max__ubyte", "max__word", "max__uword" -> funcMax(fcall, resultToStack, resultRegister)
|
"max__byte", "max__ubyte", "max__word", "max__uword" -> funcMax(fcall, resultToStack, resultRegister)
|
||||||
"abs" -> funcAbs(fcall, resultToStack, resultRegister, sscope)
|
"abs__byte", "abs__word", "abs__float" -> funcAbs(fcall, resultToStack, resultRegister, sscope)
|
||||||
"any", "all" -> funcAnyAll(fcall, resultToStack, resultRegister, sscope)
|
"any", "all" -> funcAnyAll(fcall, resultToStack, resultRegister, sscope)
|
||||||
"sgn" -> funcSgn(fcall, resultToStack, resultRegister, sscope)
|
"sgn" -> funcSgn(fcall, resultToStack, resultRegister, sscope)
|
||||||
"sqrt" -> funcSqrt(fcall, resultToStack, resultRegister, sscope)
|
"sqrt" -> funcSqrt(fcall, resultToStack, resultRegister, sscope)
|
||||||
@ -301,6 +301,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun funcSqrt(fcall: PtBuiltinFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?, scope: IPtSubroutine?) {
|
private fun funcSqrt(fcall: PtBuiltinFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?, scope: IPtSubroutine?) {
|
||||||
|
require(fcall.type != DataType.FLOAT)
|
||||||
translateArguments(fcall, scope)
|
translateArguments(fcall, scope)
|
||||||
if(resultToStack)
|
if(resultToStack)
|
||||||
asmgen.out(" jsr prog8_lib.func_sqrt16_stack")
|
asmgen.out(" jsr prog8_lib.func_sqrt16_stack")
|
||||||
@ -679,21 +680,32 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
|||||||
val dt = fcall.args.single().type
|
val dt = fcall.args.single().type
|
||||||
if(resultToStack) {
|
if(resultToStack) {
|
||||||
when (dt) {
|
when (dt) {
|
||||||
DataType.UBYTE -> asmgen.out(" ldy #0")
|
|
||||||
DataType.BYTE -> asmgen.out(" jsr prog8_lib.abs_b_stack")
|
DataType.BYTE -> asmgen.out(" jsr prog8_lib.abs_b_stack")
|
||||||
DataType.UWORD -> {}
|
|
||||||
DataType.WORD -> asmgen.out(" jsr prog8_lib.abs_w_stack")
|
DataType.WORD -> asmgen.out(" jsr prog8_lib.abs_w_stack")
|
||||||
else -> throw AssemblyError("weird type")
|
else -> throw AssemblyError("no support for abs onto stack for this dt")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
when (dt) {
|
when (dt) {
|
||||||
DataType.UBYTE -> asmgen.out(" ldy #0")
|
DataType.BYTE -> {
|
||||||
DataType.BYTE -> asmgen.out(" jsr prog8_lib.abs_b_into_AY")
|
asmgen.out(" jsr prog8_lib.abs_b_into_A")
|
||||||
DataType.UWORD -> {}
|
assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A,false)
|
||||||
DataType.WORD -> asmgen.out(" jsr prog8_lib.abs_w_into_AY")
|
}
|
||||||
|
DataType.WORD -> {
|
||||||
|
asmgen.out(" jsr prog8_lib.abs_w_into_AY")
|
||||||
|
assignAsmGen.assignRegisterpairWord(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, false, fcall.position, scope, asmgen), RegisterOrPair.AY)
|
||||||
|
}
|
||||||
|
DataType.FLOAT -> {
|
||||||
|
asmgen.out(" jsr floats.func_abs_f_into_FAC1")
|
||||||
|
assignAsmGen.assignFAC1float(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.FAC1, true, fcall.position, scope, asmgen))
|
||||||
|
}
|
||||||
|
DataType.UBYTE -> {
|
||||||
|
asmgen.assignRegister(RegisterOrPair.A, AsmAssignTarget.fromRegisters(resultRegister?:RegisterOrPair.A, false, fcall.position, scope, asmgen))
|
||||||
|
}
|
||||||
|
DataType.UWORD -> {
|
||||||
|
asmgen.assignRegister(RegisterOrPair.AY, AsmAssignTarget.fromRegisters(resultRegister?:RegisterOrPair.AY, false, fcall.position, scope, asmgen))
|
||||||
|
}
|
||||||
else -> throw AssemblyError("weird type")
|
else -> throw AssemblyError("weird type")
|
||||||
}
|
}
|
||||||
assignAsmGen.assignRegisterpairWord(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, false, fcall.position, scope, asmgen), RegisterOrPair.AY)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
|||||||
return when(call.name) {
|
return when(call.name) {
|
||||||
"any" -> funcAny(call)
|
"any" -> funcAny(call)
|
||||||
"all" -> funcAll(call)
|
"all" -> funcAll(call)
|
||||||
"abs" -> funcAbs(call)
|
"abs__byte", "abs__word", "abs__float" -> funcAbs(call)
|
||||||
"cmp" -> funcCmp(call)
|
"cmp" -> funcCmp(call)
|
||||||
"sgn" -> funcSgn(call)
|
"sgn" -> funcSgn(call)
|
||||||
"sqrt" -> funcSqrt(call)
|
"sqrt" -> funcSqrt(call)
|
||||||
@ -165,12 +165,6 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
|||||||
val tr = exprGen.translateExpression(call.args[0])
|
val tr = exprGen.translateExpression(call.args[0])
|
||||||
addToResult(result, tr, tr.resultReg, -1)
|
addToResult(result, tr, tr.resultReg, -1)
|
||||||
when (sourceDt) {
|
when (sourceDt) {
|
||||||
DataType.UBYTE -> {
|
|
||||||
result += IRCodeChunk(null, null).also {
|
|
||||||
it += IRInstruction(Opcode.EXT, IRDataType.BYTE, reg1 = tr.resultReg)
|
|
||||||
}
|
|
||||||
return ExpressionCodeResult(result, IRDataType.BYTE, tr.resultReg, -1)
|
|
||||||
}
|
|
||||||
DataType.BYTE -> {
|
DataType.BYTE -> {
|
||||||
val notNegativeLabel = codeGen.createLabelName()
|
val notNegativeLabel = codeGen.createLabelName()
|
||||||
val compareReg = codeGen.registers.nextFree()
|
val compareReg = codeGen.registers.nextFree()
|
||||||
@ -196,7 +190,12 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
|||||||
result += IRCodeChunk(notNegativeLabel, null)
|
result += IRCodeChunk(notNegativeLabel, null)
|
||||||
return ExpressionCodeResult(result, IRDataType.WORD, tr.resultReg, -1)
|
return ExpressionCodeResult(result, IRDataType.WORD, tr.resultReg, -1)
|
||||||
}
|
}
|
||||||
else -> throw AssemblyError("weird type")
|
DataType.FLOAT -> {
|
||||||
|
val resultFpReg = codeGen.registers.nextFreeFloat()
|
||||||
|
addInstr(result, IRInstruction(Opcode.FABS, IRDataType.FLOAT, fpReg1 = resultFpReg, fpReg2 = tr.resultFpReg), null)
|
||||||
|
return ExpressionCodeResult(result, IRDataType.FLOAT, -1, resultFpReg)
|
||||||
|
}
|
||||||
|
else -> throw AssemblyError("weird dt")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,6 +100,27 @@ class VarConstantValueTypeAdjuster(private val program: Program, private val err
|
|||||||
functionCallExpr))
|
functionCallExpr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(func==listOf("abs")) {
|
||||||
|
val t1 = functionCallExpr.args[0].inferType(program)
|
||||||
|
if(t1.isKnown) {
|
||||||
|
val dt = t1.getOrElse { throw InternalCompilerException("invalid dt") }
|
||||||
|
val replaceFunc = when(dt) {
|
||||||
|
DataType.BYTE -> "abs__byte"
|
||||||
|
DataType.WORD -> "abs__word"
|
||||||
|
DataType.FLOAT -> "abs__float"
|
||||||
|
DataType.UBYTE, DataType.UWORD -> {
|
||||||
|
return listOf(IAstModification.ReplaceNode(functionCallExpr, functionCallExpr.args[0], parent))
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
errors.err("expected numeric argument", functionCallExpr.position)
|
||||||
|
return noModifications
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return listOf(IAstModification.SetExpression({functionCallExpr.target = it as IdentifierReference},
|
||||||
|
IdentifierReference(listOf(replaceFunc), functionCallExpr.target.position),
|
||||||
|
functionCallExpr))
|
||||||
|
}
|
||||||
|
}
|
||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,3 +144,11 @@ func_all_f_stack .proc
|
|||||||
jsr a_times_5
|
jsr a_times_5
|
||||||
jmp prog8_lib.func_all_b_stack
|
jmp prog8_lib.func_all_b_stack
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
|
func_abs_f_into_FAC1 .proc
|
||||||
|
stx P8ZP_SCRATCH_REG
|
||||||
|
jsr MOVFM
|
||||||
|
jsr ABS
|
||||||
|
ldx P8ZP_SCRATCH_REG
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
@ -86,16 +86,15 @@ func_all_w_stack .proc
|
|||||||
|
|
||||||
abs_b_stack .proc
|
abs_b_stack .proc
|
||||||
; -- push abs(A) on stack (as unsigned word)
|
; -- push abs(A) on stack (as unsigned word)
|
||||||
jsr abs_b_into_AY
|
jsr abs_b_into_A
|
||||||
sta P8ESTACK_LO,x
|
sta P8ESTACK_LO,x
|
||||||
stz P8ESTACK_HI,x
|
stz P8ESTACK_HI,x
|
||||||
dex
|
dex
|
||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
abs_b_into_AY .proc
|
abs_b_into_A .proc
|
||||||
; -- AY = abs(A) (abs always returns unsigned word)
|
; -- A = abs(A)
|
||||||
ldy #0
|
|
||||||
cmp #0
|
cmp #0
|
||||||
bmi +
|
bmi +
|
||||||
rts
|
rts
|
||||||
|
@ -532,7 +532,7 @@ class TestOptimization: FunSpec({
|
|||||||
uword @shared zz
|
uword @shared zz
|
||||||
zz += 60 ; NOT ok to remove initializer, should evaluate to 60
|
zz += 60 ; NOT ok to remove initializer, should evaluate to 60
|
||||||
ubyte @shared xx
|
ubyte @shared xx
|
||||||
xx = 6+lsb(abs(xx)) ; is not an initializer because it references xx
|
xx = 6+lsb(mkword(xx,22)) ; is not an initializer because it references xx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
@ -27,14 +27,14 @@ class TestTypecasts: FunSpec({
|
|||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
float fl
|
float fl
|
||||||
floats.print_f(abs(fl))
|
floats.print_f(lsb(fl))
|
||||||
}
|
}
|
||||||
}"""
|
}"""
|
||||||
val errors = ErrorReporterForTests()
|
val errors = ErrorReporterForTests()
|
||||||
val result = compileText(C64Target(), false, text, writeAssembly = false, errors=errors)
|
val result = compileText(C64Target(), false, text, writeAssembly = false, errors=errors)
|
||||||
result shouldBe null
|
result shouldBe null
|
||||||
errors.errors.size shouldBe 1
|
errors.errors.size shouldBe 1
|
||||||
errors.errors[0] shouldContain "type mismatch, was: FLOAT expected one of: [UBYTE, BYTE, UWORD, WORD]"
|
errors.errors[0] shouldContain "type mismatch, was: FLOAT expected one of: [UWORD, WORD]"
|
||||||
}
|
}
|
||||||
|
|
||||||
test("not casting bool operands to logical operators") {
|
test("not casting bool operands to logical operators") {
|
||||||
|
@ -50,11 +50,11 @@ sys (part of syslib)
|
|||||||
- 16 = compiled for Commander X16 with 65C02 CPU
|
- 16 = compiled for Commander X16 with 65C02 CPU
|
||||||
- 64 = compiled for Commodore 64 with 6502/6510 CPU
|
- 64 = compiled for Commodore 64 with 6502/6510 CPU
|
||||||
|
|
||||||
``exit(returncode)``
|
``exit (returncode)``
|
||||||
Immediately stops the program and exits it, with the returncode in the A register.
|
Immediately stops the program and exits it, with the returncode in the A register.
|
||||||
Note: custom interrupt handlers remain active unless manually cleared first!
|
Note: custom interrupt handlers remain active unless manually cleared first!
|
||||||
|
|
||||||
``memcopy(from, to, numbytes)``
|
``memcopy (from, to, numbytes)``
|
||||||
Efficiently copy a number of bytes from a memory location to another.
|
Efficiently copy a number of bytes from a memory location to another.
|
||||||
*Warning:* can only copy *non-overlapping* memory areas correctly!
|
*Warning:* can only copy *non-overlapping* memory areas correctly!
|
||||||
Because this function imposes some overhead to handle the parameters,
|
Because this function imposes some overhead to handle the parameters,
|
||||||
@ -62,60 +62,60 @@ sys (part of syslib)
|
|||||||
Compare the generated code to see if it was beneficial or not.
|
Compare the generated code to see if it was beneficial or not.
|
||||||
The most efficient will often be to write a specialized copy routine in assembly yourself!
|
The most efficient will often be to write a specialized copy routine in assembly yourself!
|
||||||
|
|
||||||
``memset(address, numbytes, bytevalue)``
|
``memset (address, numbytes, bytevalue)``
|
||||||
Efficiently set a part of memory to the given (u)byte value.
|
Efficiently set a part of memory to the given (u)byte value.
|
||||||
But the most efficient will always be to write a specialized fill routine in assembly yourself!
|
But the most efficient will always be to write a specialized fill routine in assembly yourself!
|
||||||
Note that for clearing the screen, very fast specialized subroutines are
|
Note that for clearing the screen, very fast specialized subroutines are
|
||||||
available in the ``textio`` and ``graphics`` library modules.
|
available in the ``textio`` and ``graphics`` library modules.
|
||||||
|
|
||||||
``memsetw(address, numwords, wordvalue)``
|
``memsetw (address, numwords, wordvalue)``
|
||||||
Efficiently set a part of memory to the given (u)word value.
|
Efficiently set a part of memory to the given (u)word value.
|
||||||
But the most efficient will always be to write a specialized fill routine in assembly yourself!
|
But the most efficient will always be to write a specialized fill routine in assembly yourself!
|
||||||
|
|
||||||
``read_flags() -> ubyte``
|
``read_flags () -> ubyte``
|
||||||
Returns the current value of the CPU status register.
|
Returns the current value of the CPU status register.
|
||||||
|
|
||||||
``set_carry()``
|
``set_carry ()``
|
||||||
Sets the CPU status register Carry flag.
|
Sets the CPU status register Carry flag.
|
||||||
|
|
||||||
``clear_carry()``
|
``clear_carry ()``
|
||||||
Clears the CPU status register Carry flag.
|
Clears the CPU status register Carry flag.
|
||||||
|
|
||||||
``set_irqd()``
|
``set_irqd ()``
|
||||||
Sets the CPU status register Interrupt Disable flag.
|
Sets the CPU status register Interrupt Disable flag.
|
||||||
|
|
||||||
``clear_irqd()``
|
``clear_irqd ()``
|
||||||
Clears the CPU status register Interrupt Disable flag.
|
Clears the CPU status register Interrupt Disable flag.
|
||||||
|
|
||||||
``progend()``
|
``progend ()``
|
||||||
Returns the last address of the program in memory + 1.
|
Returns the last address of the program in memory + 1.
|
||||||
Can be used to load dynamic data after the program, instead of hardcoding something.
|
Can be used to load dynamic data after the program, instead of hardcoding something.
|
||||||
|
|
||||||
``wait(uword jiffies)``
|
``wait (uword jiffies)``
|
||||||
wait approximately the given number of jiffies (1/60th seconds)
|
wait approximately the given number of jiffies (1/60th seconds)
|
||||||
Note: the regular system irq handler has run for this to work as it depends on the system jiffy clock.
|
Note: the regular system irq handler has run for this to work as it depends on the system jiffy clock.
|
||||||
If this is is not possible (for instance because your program is running its own irq handler logic *and* no longer calls
|
If this is is not possible (for instance because your program is running its own irq handler logic *and* no longer calls
|
||||||
the kernal's handler routine), you'll have to write your own wait routine instead.
|
the kernal's handler routine), you'll have to write your own wait routine instead.
|
||||||
|
|
||||||
``waitvsync()``
|
``waitvsync ()``
|
||||||
busy wait till the next vsync has occurred (approximately), without depending on custom irq handling.
|
busy wait till the next vsync has occurred (approximately), without depending on custom irq handling.
|
||||||
can be used to avoid screen flicker/tearing when updating screen contents.
|
can be used to avoid screen flicker/tearing when updating screen contents.
|
||||||
note: a more accurate way to wait for vsync is to set up a vsync irq handler instead.
|
note: a more accurate way to wait for vsync is to set up a vsync irq handler instead.
|
||||||
note for cx16: the regular system irq handler has to run for this to work (this is not required on C64 and C128)
|
note for cx16: the regular system irq handler has to run for this to work (this is not required on C64 and C128)
|
||||||
|
|
||||||
``waitrastborder()`` (c64/c128 targets only)
|
``waitrastborder ()`` (c64/c128 targets only)
|
||||||
busy wait till the raster position has reached the bottom screen border (approximately)
|
busy wait till the raster position has reached the bottom screen border (approximately)
|
||||||
can be used to avoid screen flicker/tearing when updating screen contents.
|
can be used to avoid screen flicker/tearing when updating screen contents.
|
||||||
note: a more accurate way to do this is by using a raster irq handler instead.
|
note: a more accurate way to do this is by using a raster irq handler instead.
|
||||||
|
|
||||||
``reset_system()``
|
``reset_system ()``
|
||||||
Soft-reset the system back to initial power-on BASIC prompt.
|
Soft-reset the system back to initial power-on BASIC prompt.
|
||||||
(called automatically by Prog8 when the main subroutine returns and the program is not using basicsafe zeropage option)
|
(called automatically by Prog8 when the main subroutine returns and the program is not using basicsafe zeropage option)
|
||||||
|
|
||||||
``poweroff_system()`` (commander x16 only)
|
``poweroff_system ()`` (commander x16 only)
|
||||||
Powers down the computer.
|
Powers down the computer.
|
||||||
|
|
||||||
``set_leds_brightness(ubyte activity, ubyte power)`` (commander x16 only)
|
``set_leds_brightness (ubyte activity, ubyte power)`` (commander x16 only)
|
||||||
Sets the brightness of the activity and power leds on the computer.
|
Sets the brightness of the activity and power leds on the computer.
|
||||||
|
|
||||||
|
|
||||||
@ -157,63 +157,63 @@ string
|
|||||||
------
|
------
|
||||||
Provides string manipulation routines.
|
Provides string manipulation routines.
|
||||||
|
|
||||||
``length(str) -> ubyte length``
|
``length (str) -> ubyte length``
|
||||||
Number of bytes in the string. This value is determined during runtime and counts upto
|
Number of bytes in the string. This value is determined during runtime and counts upto
|
||||||
the first terminating 0 byte in the string, regardless of the size of the string during compilation time.
|
the first terminating 0 byte in the string, regardless of the size of the string during compilation time.
|
||||||
Don't confuse this with ``len`` and ``sizeof``!
|
Don't confuse this with ``len`` and ``sizeof``!
|
||||||
|
|
||||||
``left(source, length, target)``
|
``left (source, length, target)``
|
||||||
Copies the left side of the source string of the given length to target string.
|
Copies the left side of the source string of the given length to target string.
|
||||||
It is assumed the target string buffer is large enough to contain the result.
|
It is assumed the target string buffer is large enough to contain the result.
|
||||||
Also, you have to make sure yourself that length is smaller or equal to the length of the source string.
|
Also, you have to make sure yourself that length is smaller or equal to the length of the source string.
|
||||||
Modifies in-place, doesn't return a value (so can't be used in an expression).
|
Modifies in-place, doesn't return a value (so can't be used in an expression).
|
||||||
|
|
||||||
``right(source, length, target)``
|
``right (source, length, target)``
|
||||||
Copies the right side of the source string of the given length to target string.
|
Copies the right side of the source string of the given length to target string.
|
||||||
It is assumed the target string buffer is large enough to contain the result.
|
It is assumed the target string buffer is large enough to contain the result.
|
||||||
Also, you have to make sure yourself that length is smaller or equal to the length of the source string.
|
Also, you have to make sure yourself that length is smaller or equal to the length of the source string.
|
||||||
Modifies in-place, doesn't return a value (so can't be used in an expression).
|
Modifies in-place, doesn't return a value (so can't be used in an expression).
|
||||||
|
|
||||||
``slice(source, start, length, target)``
|
``slice (source, start, length, target)``
|
||||||
Copies a segment from the source string, starting at the given index,
|
Copies a segment from the source string, starting at the given index,
|
||||||
and of the given length to target string.
|
and of the given length to target string.
|
||||||
It is assumed the target string buffer is large enough to contain the result.
|
It is assumed the target string buffer is large enough to contain the result.
|
||||||
Also, you have to make sure yourself that start and length are within bounds of the strings.
|
Also, you have to make sure yourself that start and length are within bounds of the strings.
|
||||||
Modifies in-place, doesn't return a value (so can't be used in an expression).
|
Modifies in-place, doesn't return a value (so can't be used in an expression).
|
||||||
|
|
||||||
``find(string, char) -> ubyte index + carry bit``
|
``find (string, char) -> ubyte index + carry bit``
|
||||||
Locates the first position of the given character in the string, returns carry bit set if found
|
Locates the first position of the given character in the string, returns carry bit set if found
|
||||||
and the index in the string. Or 0+carry bit clear if the character was not found.
|
and the index in the string. Or 0+carry bit clear if the character was not found.
|
||||||
|
|
||||||
``compare(string1, string2) -> ubyte result``
|
``compare (string1, string2) -> ubyte result``
|
||||||
Returns -1, 0 or 1 depending on whether string1 sorts before, equal or after string2.
|
Returns -1, 0 or 1 depending on whether string1 sorts before, equal or after string2.
|
||||||
Note that you can also directly compare strings and string values with each other
|
Note that you can also directly compare strings and string values with each other
|
||||||
using ``==``, ``<`` etcetera (it will use string.compare for you under water automatically).
|
using ``==``, ``<`` etcetera (it will use string.compare for you under water automatically).
|
||||||
|
|
||||||
``copy(from, to) -> ubyte length``
|
``copy (from, to) -> ubyte length``
|
||||||
Copy a string to another, overwriting that one. Returns the length of the string that was copied.
|
Copy a string to another, overwriting that one. Returns the length of the string that was copied.
|
||||||
Often you don't have to call this explicitly and can just write ``string1 = string2``
|
Often you don't have to call this explicitly and can just write ``string1 = string2``
|
||||||
but this function is useful if you're dealing with addresses for instance.
|
but this function is useful if you're dealing with addresses for instance.
|
||||||
|
|
||||||
``lower(string)``
|
``lower (string)``
|
||||||
Lowercases the PETSCII-string in place.
|
Lowercases the PETSCII-string in place.
|
||||||
|
|
||||||
``upper(string)``
|
``upper (string)``
|
||||||
Uppercases the PETSCII-string in place.
|
Uppercases the PETSCII-string in place.
|
||||||
|
|
||||||
``lowerchar(char)``
|
``lowerchar (char)``
|
||||||
Returns lowercased character.
|
Returns lowercased character.
|
||||||
|
|
||||||
``upperchar(char)``
|
``upperchar (char)``
|
||||||
Returns uppercased character.
|
Returns uppercased character.
|
||||||
|
|
||||||
``startswith(string, prefix) -> bool``
|
``startswith (string, prefix) -> bool``
|
||||||
Returns true if string starts with prefix, otherwise false
|
Returns true if string starts with prefix, otherwise false
|
||||||
|
|
||||||
``endswith(string, suffix) -> bool``
|
``endswith (string, suffix) -> bool``
|
||||||
Returns true if string ends with suffix, otherwise false
|
Returns true if string ends with suffix, otherwise false
|
||||||
|
|
||||||
``pattern_match(string, pattern) -> ubyte`` (not on Virtual target)
|
``pattern_match (string, pattern) -> ubyte`` (not on Virtual target)
|
||||||
Returns 1 (true) if the string matches the pattern, 0 (false) if not.
|
Returns 1 (true) if the string matches the pattern, 0 (false) if not.
|
||||||
'?' in the pattern matches any one character. '*' in the pattern matches any substring.
|
'?' in the pattern matches any one character. '*' in the pattern matches any substring.
|
||||||
|
|
||||||
@ -225,61 +225,65 @@ floats
|
|||||||
Floating point support is only available on c64, cx16 and virtual targets for now.
|
Floating point support is only available on c64, cx16 and virtual targets for now.
|
||||||
|
|
||||||
Provides definitions for the ROM/Kernal subroutines and utility routines dealing with floating
|
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,
|
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 a dozen or so floating point
|
|
||||||
math routines.
|
|
||||||
|
|
||||||
atan(x)
|
``atan (x)``
|
||||||
Arctangent.
|
Arctangent.
|
||||||
|
|
||||||
ceil(x)
|
``ceil (x)``
|
||||||
Rounds the floating point up to an integer towards positive infinity.
|
Rounds the floating point up to an integer towards positive infinity.
|
||||||
|
|
||||||
cos(x)
|
``cos (x)``
|
||||||
Cosine.
|
Cosine.
|
||||||
If you want a fast integer cosine, have a look at examples/cx16/sincos.p8
|
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.
|
that contains various lookup tables generated by the 64tass assembler.
|
||||||
|
|
||||||
deg(x)
|
``deg (x)``
|
||||||
Radians to degrees.
|
Radians to degrees.
|
||||||
|
|
||||||
floor (x)
|
``fabs (x)``
|
||||||
|
Returns the absolute value of x. Deprecated, just use the builtin ``abs(x)`` function instead.
|
||||||
|
|
||||||
|
``floor (x)``
|
||||||
Rounds the floating point down to an integer towards minus infinity.
|
Rounds the floating point down to an integer towards minus infinity.
|
||||||
|
|
||||||
ln(x)
|
``ln (x)``
|
||||||
Natural logarithm (base e).
|
Natural logarithm (base e).
|
||||||
|
|
||||||
log2(x)
|
``log2 (x)``
|
||||||
Base 2 logarithm.
|
Base 2 logarithm.
|
||||||
|
|
||||||
minf(x, y)
|
``minf (x, y)``
|
||||||
returns the smallest of x and y.
|
returns the smallest of x and y.
|
||||||
|
|
||||||
maxf(x, y)
|
``maxf (x, y)``
|
||||||
returns the largest of x and y.
|
returns the largest of x and y.
|
||||||
|
|
||||||
rad(x)
|
``print_f (x)``
|
||||||
|
prints the floating point number x as a string.
|
||||||
|
|
||||||
|
``rad (x)``
|
||||||
Degrees to radians.
|
Degrees to radians.
|
||||||
|
|
||||||
round(x)
|
``round (x)``
|
||||||
Rounds the floating point to the closest integer.
|
Rounds the floating point to the closest integer.
|
||||||
|
|
||||||
sin(x)
|
``sin (x)``
|
||||||
Sine.
|
Sine.
|
||||||
If you want a fast integer sine, have a look at examples/cx16/sincos.p8
|
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.
|
that contains various lookup tables generated by the 64tass assembler.
|
||||||
|
|
||||||
sqrtf(x)
|
``sqrtf (x)``
|
||||||
Floating point Square root.
|
Floating point Square root.
|
||||||
To do the reverse, squaring a floating point number, just write ``x*x``.
|
To do the reverse, squaring a floating point number, just write ``x*x``.
|
||||||
|
|
||||||
tan(x)
|
``tan (x)``
|
||||||
Tangent.
|
Tangent.
|
||||||
|
|
||||||
rndf()
|
``rndf ()``
|
||||||
returns the next random float between 0.0 and 1.0 from the Pseudo RNG sequence.
|
returns the next random float between 0.0 and 1.0 from the Pseudo RNG sequence.
|
||||||
|
|
||||||
rndseedf(seed)
|
``rndseedf (seed)``
|
||||||
Sets a new seed for the float pseudo-RNG sequence. Use a negative non-zero number as seed value.
|
Sets a new seed for the float pseudo-RNG sequence. Use a negative non-zero number as seed value.
|
||||||
|
|
||||||
|
|
||||||
@ -306,41 +310,41 @@ Usually a custom lookup table is the way to go if your application needs these,
|
|||||||
but perhaps the provided ones can be of service too.
|
but perhaps the provided ones can be of service too.
|
||||||
|
|
||||||
|
|
||||||
rnd()
|
``rnd ()``
|
||||||
Returns next random byte 0-255 from the pseudo-RNG sequence.
|
Returns next random byte 0-255 from the pseudo-RNG sequence.
|
||||||
|
|
||||||
rndw()
|
``rndw ()``
|
||||||
Returns next random word 0-65535 from the pseudo-RNG sequence.
|
Returns next random word 0-65535 from the pseudo-RNG sequence.
|
||||||
|
|
||||||
rndseed(uword seed1, uword seed2)
|
``rndseed (uword seed1, uword seed2)``
|
||||||
Sets a new seed for the pseudo-RNG sequence (both rnd and rndw). The seed consists of two words.
|
Sets a new seed for the pseudo-RNG sequence (both rnd and rndw). The seed consists of two words.
|
||||||
Do not use zeros for the seed!
|
Do not use zeros for the seed!
|
||||||
|
|
||||||
sin8u(x)
|
``sin8u (x)``
|
||||||
Fast 8-bit ubyte sine of angle 0..255, result is in range 0..255
|
Fast 8-bit ubyte sine of angle 0..255, result is in range 0..255
|
||||||
|
|
||||||
sin8(x)
|
``sin8 (x)``
|
||||||
Fast 8-bit byte sine of angle 0..255, result is in range -127..127
|
Fast 8-bit byte sine of angle 0..255, result is in range -127..127
|
||||||
|
|
||||||
sinr8u(x)
|
``sinr8u (x)``
|
||||||
Fast 8-bit ubyte sine of angle 0..179 (each is a 2 degree step), result is in range 0..255
|
Fast 8-bit ubyte sine of angle 0..179 (each is a 2 degree step), result is in range 0..255
|
||||||
Angles 180..255 will yield a garbage result!
|
Angles 180..255 will yield a garbage result!
|
||||||
|
|
||||||
sinr8(x)
|
``sinr8 (x)``
|
||||||
Fast 8-bit byte sine of angle 0..179 (each is a 2 degree step), result is in range -127..127
|
Fast 8-bit byte sine of angle 0..179 (each is a 2 degree step), result is in range -127..127
|
||||||
Angles 180..255 will yield a garbage result!
|
Angles 180..255 will yield a garbage result!
|
||||||
|
|
||||||
cos8u(x)
|
``cos8u (x)``
|
||||||
Fast 8-bit ubyte cosine of angle 0..255, result is in range 0..255
|
Fast 8-bit ubyte cosine of angle 0..255, result is in range 0..255
|
||||||
|
|
||||||
cos8(x)
|
``cos8 (x)``
|
||||||
Fast 8-bit byte cosine of angle 0..255, result is in range -127..127
|
Fast 8-bit byte cosine of angle 0..255, result is in range -127..127
|
||||||
|
|
||||||
cosr8u(x)
|
``cosr8u (x)``
|
||||||
Fast 8-bit ubyte cosine of angle 0..179 (each is a 2 degree step), result is in range 0..255
|
Fast 8-bit ubyte cosine of angle 0..179 (each is a 2 degree step), result is in range 0..255
|
||||||
Angles 180..255 will yield a garbage result!
|
Angles 180..255 will yield a garbage result!
|
||||||
|
|
||||||
cosr8(x)
|
``cosr8 (x)``
|
||||||
Fast 8-bit byte cosine of angle 0..179 (each is a 2 degree step), result is in range -127..127
|
Fast 8-bit byte cosine of angle 0..179 (each is a 2 degree step), result is in range -127..127
|
||||||
Angles 180..255 will yield a garbage result!
|
Angles 180..255 will yield a garbage result!
|
||||||
|
|
||||||
|
@ -762,8 +762,7 @@ Math
|
|||||||
^^^^
|
^^^^
|
||||||
|
|
||||||
abs (x)
|
abs (x)
|
||||||
Absolute value of an integer. Value returned is an unsigned word.
|
Returns the absolute value of a number.
|
||||||
For floating point numbers, use ``floats.fabs()`` instead.
|
|
||||||
|
|
||||||
min (x, y)
|
min (x, y)
|
||||||
Returns the smallest of x and y. Supported for integer types only, for floats use ``floats.minf()`` instead.
|
Returns the smallest of x and y. Supported for integer types only, for floats use ``floats.minf()`` instead.
|
||||||
|
@ -6,7 +6,8 @@ For 9.0 major changes
|
|||||||
- DONE: added min() max() builtin functions
|
- DONE: added min() max() builtin functions
|
||||||
- DONE: added 'cbm' block in the syslib module that now contains all CBM compatible kernal routines and variables
|
- DONE: added 'cbm' block in the syslib module that now contains all CBM compatible kernal routines and variables
|
||||||
- DONE: rename sqrt16() to just sqrt(), rename floats.sqrt() to floats.sqrtf()
|
- DONE: rename sqrt16() to just sqrt(), rename floats.sqrt() to floats.sqrtf()
|
||||||
- add "polymorphism" of min() and max() to several other builtin functions as well (abs, divmod, pop, push) Fix docs.
|
- DONE: abs() now supports multiple datatypes including float. No need to use floats.fabs() anymore.
|
||||||
|
- add "polymorphism" of min() and max() to several other builtin functions as well (divmod, pop, push) Fix docs.
|
||||||
- 6502 codegen: see if we can let for loops skip the loop if startvar>endvar, without adding a lot of code size/duplicating the loop condition.
|
- 6502 codegen: see if we can let for loops skip the loop if startvar>endvar, without adding a lot of code size/duplicating the loop condition.
|
||||||
It is documented behavior to now loop 'around' $00 but it's too easy to forget about!
|
It is documented behavior to now loop 'around' $00 but it's too easy to forget about!
|
||||||
Lot of work because of so many special cases in ForLoopsAsmgen.....
|
Lot of work because of so many special cases in ForLoopsAsmgen.....
|
||||||
|
Loading…
Reference in New Issue
Block a user