mirror of
https://github.com/irmen/prog8.git
synced 2025-01-23 15:30:10 +00:00
got rid of problematic signed POW operator, added compiler checks for this
This commit is contained in:
parent
ec2e7db23e
commit
83ace753b2
@ -1 +1 @@
|
||||
1.5 (beta)
|
||||
1.6 (beta)
|
||||
|
@ -673,6 +673,9 @@ private class AstChecker(private val namespace: INameScope,
|
||||
}
|
||||
|
||||
override fun process(expr: BinaryExpression): IExpression {
|
||||
val leftDt = expr.left.resultingDatatype(namespace, heap)
|
||||
val rightDt = expr.right.resultingDatatype(namespace, heap)
|
||||
|
||||
when(expr.operator){
|
||||
"/", "%" -> {
|
||||
val constvalRight = expr.right.constValue(namespace, heap)
|
||||
@ -680,16 +683,23 @@ private class AstChecker(private val namespace: INameScope,
|
||||
if(divisor==0.0)
|
||||
checkResult.add(ExpressionError("division by zero", expr.right.position))
|
||||
if(expr.operator=="%") {
|
||||
val rightDt = constvalRight?.resultingDatatype(namespace, heap)
|
||||
val leftDt = expr.left.resultingDatatype(namespace, heap)
|
||||
if ((rightDt != DataType.UBYTE && rightDt != DataType.UWORD) || (leftDt!=DataType.UBYTE && leftDt!=DataType.UWORD))
|
||||
checkResult.add(ExpressionError("remainder can only be used on unsigned integer operands", expr.right.position))
|
||||
}
|
||||
}
|
||||
"**" -> {
|
||||
if(leftDt in IntegerDatatypes) {
|
||||
val constvalRight = expr.right.constValue(namespace, heap)?.asNumericValue?.toDouble()
|
||||
if(constvalRight==null) {
|
||||
if(rightDt==DataType.FLOAT || rightDt==DataType.BYTE || rightDt==DataType.WORD)
|
||||
checkResult.add(ExpressionError("raising to a signed value requires floating point", expr.position))
|
||||
} else if(constvalRight<0.0) {
|
||||
checkResult.add(ExpressionError("raising to negative power requires floating point", expr.position))
|
||||
}
|
||||
}
|
||||
}
|
||||
"and", "or", "xor" -> {
|
||||
// only integer numeric operands accepted, and if literal constants, only boolean values accepted (0 or 1)
|
||||
val rightDt = expr.right.resultingDatatype(namespace, heap)
|
||||
val leftDt = expr.left.resultingDatatype(namespace, heap)
|
||||
if(leftDt !in IntegerDatatypes || rightDt !in IntegerDatatypes)
|
||||
checkResult.add(ExpressionError("logical operator can only be used on boolean operands", expr.right.position))
|
||||
val constLeft = expr.left.constValue(namespace, heap)
|
||||
@ -699,15 +709,11 @@ private class AstChecker(private val namespace: INameScope,
|
||||
}
|
||||
"&", "|", "^" -> {
|
||||
// only integer numeric operands accepted
|
||||
val rightDt = expr.right.resultingDatatype(namespace, heap)
|
||||
val leftDt = expr.left.resultingDatatype(namespace, heap)
|
||||
if(leftDt !in IntegerDatatypes || rightDt !in IntegerDatatypes)
|
||||
checkResult.add(ExpressionError("bitwise operator can only be used on integer operands", expr.right.position))
|
||||
}
|
||||
}
|
||||
|
||||
val leftDt = expr.left.resultingDatatype(namespace, heap)
|
||||
val rightDt = expr.right.resultingDatatype(namespace, heap)
|
||||
if(leftDt !in NumericDatatypes)
|
||||
checkResult.add(ExpressionError("left operand is not numeric", expr.left.position))
|
||||
if(rightDt!in NumericDatatypes)
|
||||
|
@ -1239,9 +1239,8 @@ internal class Compiler(private val rootModule: Module,
|
||||
"**" -> {
|
||||
when(dt) {
|
||||
DataType.UBYTE -> Opcode.POW_UB
|
||||
DataType.BYTE -> Opcode.POW_B
|
||||
DataType.BYTE, DataType.WORD -> throw CompilerException("power operator only available for unsigned integer types and floats")
|
||||
DataType.UWORD -> Opcode.POW_UW
|
||||
DataType.WORD -> Opcode.POW_W
|
||||
DataType.FLOAT -> Opcode.POW_F
|
||||
else -> throw CompilerException("only byte/word/float possible")
|
||||
}
|
||||
|
@ -59,9 +59,7 @@ enum class Opcode {
|
||||
REMAINDER_UB, // signed remainder is undefined/unimplemented
|
||||
REMAINDER_UW, // signed remainder is undefined/unimplemented
|
||||
POW_UB,
|
||||
POW_B,
|
||||
POW_UW,
|
||||
POW_W,
|
||||
POW_F,
|
||||
NEG_B,
|
||||
NEG_W,
|
||||
|
@ -729,6 +729,9 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
Opcode.ABS_B -> " jsr prog8_lib.abs_b"
|
||||
Opcode.ABS_W -> " jsr prog8_lib.abs_w"
|
||||
Opcode.ABS_F -> " jsr c64flt.abs_f"
|
||||
Opcode.POW_UB -> " jsr prog8_lib.pow_ub" // @todo implement
|
||||
Opcode.POW_UW -> " jsr prog8_lib.pow_uw" // @todo implement
|
||||
Opcode.POW_F -> " jsr c64flt.pow_f" // @todo implement
|
||||
Opcode.INV_BYTE -> {
|
||||
"""
|
||||
lda ${(ESTACK_LO + 1).toHex()},x
|
||||
|
@ -631,22 +631,6 @@ class StackVm(private var traceOutputFile: String?) {
|
||||
evalstack.push(value)
|
||||
setFlags(value)
|
||||
}
|
||||
Opcode.POW_B -> {
|
||||
val (top, second) = evalstack.pop2()
|
||||
checkDt(top, DataType.BYTE)
|
||||
checkDt(second, DataType.BYTE)
|
||||
val value=second.pow(top)
|
||||
evalstack.push(value)
|
||||
setFlags(value)
|
||||
}
|
||||
Opcode.POW_W -> {
|
||||
val (top, second) = evalstack.pop2()
|
||||
checkDt(top, DataType.WORD)
|
||||
checkDt(second, DataType.WORD)
|
||||
val value=second.pow(top)
|
||||
evalstack.push(value)
|
||||
setFlags(value)
|
||||
}
|
||||
Opcode.POW_F -> {
|
||||
val (top, second) = evalstack.pop2()
|
||||
checkDt(top, DataType.FLOAT)
|
||||
|
@ -372,7 +372,8 @@ Operators
|
||||
arithmetic: ``+`` ``-`` ``*`` ``/`` ``**`` ``%``
|
||||
``+``, ``-``, ``*``, ``/`` are the familiar arithmetic operations.
|
||||
``/`` is division (will result in integer division when using on integer operands, and a floating point division when at least one of the operands is a float)
|
||||
``**`` is the power operator: ``3 ** 5`` is equal to 3*3*3*3*3 and is 243.
|
||||
``**`` is the power operator: ``3 ** 5`` is equal to 3*3*3*3*3 and is 243. (certain restrictions
|
||||
apply when dealing with signed or negative numbers)
|
||||
``%`` is the remainder operator: ``25 % 7`` is 4. Be careful: without a space, %10 will be parsed as the binary number 2
|
||||
Remainder is only supported on integer operands (not floats).
|
||||
|
||||
|
@ -173,7 +173,3 @@ as a subroutine ``irq`` in the module ``irq`` so like this::
|
||||
; ... irq handling here ...
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.. todo::
|
||||
@todo the irq handler should use its own eval-stack to avoid stack interference issues
|
||||
|
@ -17,7 +17,7 @@ Memory Block Operations integrated in language?
|
||||
|
||||
these should call (or emit inline) optimized pieces of assembly code, so they run as fast as possible
|
||||
|
||||
For now, we have the ``memcopy`` and ``memset`` builtin functions.
|
||||
For now, we have the ``memcopy``, ``memset`` and ``strlen`` builtin functions.
|
||||
|
||||
|
||||
|
||||
@ -52,6 +52,7 @@ Allocate a fixed word in ZP that is the TOS so we can operate on TOS directly
|
||||
without having to to index into the stack?
|
||||
|
||||
|
||||
|
||||
More flexible (non-const) arrays?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Currently, array literals can only be constants
|
||||
|
@ -1,15 +1,69 @@
|
||||
%zeropage basicsafe
|
||||
%option enable_floats
|
||||
|
||||
%import c64flt
|
||||
|
||||
~ main {
|
||||
|
||||
ubyte @zp var1
|
||||
|
||||
sub start() {
|
||||
ubyte @zp var1
|
||||
A=20
|
||||
A=var1
|
||||
Y=main.var1
|
||||
ubyte ub=2
|
||||
ubyte ub2=7
|
||||
uword uw=2
|
||||
uword uw2=5
|
||||
float fl=2.3
|
||||
float fl2=20
|
||||
|
||||
ub = ub ** 7
|
||||
c64scr.print_ub(ub)
|
||||
c64.CHROUT('\n')
|
||||
uw = uw ** 5
|
||||
c64scr.print_uw(uw)
|
||||
c64.CHROUT('\n')
|
||||
fl = fl ** 20.0
|
||||
c64flt.print_f(fl)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
ub=3 ; @todo no instruction?
|
||||
ub **=7 ; @todo no instruction?
|
||||
c64scr.print_ub(ub)
|
||||
c64.CHROUT('\n')
|
||||
uw = 9 ; @todo no instruction?
|
||||
uw **=5 ; @todo no instruction?
|
||||
c64scr.print_uw(uw)
|
||||
c64.CHROUT('\n')
|
||||
fl = 2 ; @todo no instruction?
|
||||
fl **=20.0 ; @todo no instruction?
|
||||
c64flt.print_f(fl)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
|
||||
ub=3
|
||||
ub **= 7
|
||||
|
||||
c64scr.print_ub(ub)
|
||||
c64.CHROUT('\n')
|
||||
uw = 9
|
||||
uw **= 5
|
||||
c64scr.print_uw(uw)
|
||||
c64.CHROUT('\n')
|
||||
fl = 2.3
|
||||
fl **= 20.0
|
||||
c64flt.print_f(fl)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
ub=3
|
||||
ub **= ub2
|
||||
c64scr.print_ub(ub)
|
||||
c64.CHROUT('\n')
|
||||
uw = 9
|
||||
uw **= uw2
|
||||
c64scr.print_uw(uw)
|
||||
c64.CHROUT('\n')
|
||||
fl = 2.3
|
||||
fl **= fl2
|
||||
c64flt.print_f(fl)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user