removed '**' power-operator. Use floats.pow() instead.

This commit is contained in:
Irmen de Jong 2022-03-27 12:12:57 +02:00
parent 12712ef812
commit ed30108961
19 changed files with 82 additions and 265 deletions

View File

@ -70,7 +70,6 @@ class AsmGen(internal val program: Program,
}
internal fun isTargetCpu(cpu: CpuType) = options.compTarget.machine.cpu == cpu
internal fun haveFPWRcall() = options.compTarget.name=="cx16"
private var generatedLabelSequenceNumber: Int = 0

View File

@ -735,7 +735,6 @@ internal class ExpressionsAsmGen(private val program: Program,
private fun translateBinaryOperatorBytes(operator: String, types: DataType) {
when(operator) {
"**" -> throw AssemblyError("** operator requires floats")
"*" -> asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
"/" -> asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
"%" -> {
@ -777,7 +776,6 @@ internal class ExpressionsAsmGen(private val program: Program,
private fun translateBinaryOperatorWords(operator: String, dt: DataType) {
when(operator) {
"**" -> throw AssemblyError("** operator requires floats")
"*" -> asmgen.out(" jsr prog8_lib.mul_word")
"/" -> asmgen.out(if(dt==DataType.UWORD) " jsr prog8_lib.idiv_uw" else " jsr prog8_lib.idiv_w")
"%" -> {
@ -812,7 +810,6 @@ internal class ExpressionsAsmGen(private val program: Program,
private fun translateBinaryOperatorFloats(operator: String) {
when(operator) {
"**" -> asmgen.out(" jsr floats.pow_f")
"*" -> asmgen.out(" jsr floats.mul_f")
"/" -> asmgen.out(" jsr floats.div_f")
"+" -> asmgen.out(" jsr floats.add_f")

View File

@ -1590,14 +1590,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
asmgen.assignExpressionToRegister(value, RegisterOrPair.FAC1)
asmgen.saveRegisterLocal(CpuRegister.X, scope)
when (operator) {
"**" -> {
asmgen.out("""
lda #<$name
ldy #>$name
jsr floats.CONUPK
jsr floats.FPWRT
""")
}
"+" -> {
asmgen.out("""
lda #<$name
@ -1644,28 +1636,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
val otherName = asmgen.asmVariableName(ident)
asmgen.saveRegisterLocal(CpuRegister.X, scope)
when (operator) {
"**" -> {
if(asmgen.haveFPWRcall()) {
asmgen.out("""
lda #<$name
ldy #>$name
jsr floats.CONUPK
lda #<$otherName
ldy #>$otherName
jsr floats.FPWR
""")
} else
// cx16 doesn't have FPWR() only FPWRT()
asmgen.out("""
lda #<$name
ldy #>$name
jsr floats.CONUPK
lda #<$otherName
ldy #>$otherName
jsr floats.MOVFM
jsr floats.FPWRT
""")
}
"+" -> {
asmgen.out("""
lda #<$name
@ -1721,28 +1691,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
val constValueName = allocator.getFloatAsmConst(value)
asmgen.saveRegisterLocal(CpuRegister.X, scope)
when (operator) {
"**" -> {
if(asmgen.haveFPWRcall()) {
asmgen.out("""
lda #<$name
ldy #>$name
jsr floats.CONUPK
lda #<$constValueName
ldy #>$constValueName
jsr floats.FPWR
""")
} else
// cx16 doesn't have FPWR() only FPWRT()
asmgen.out("""
lda #<$name
ldy #>$name
jsr floats.CONUPK
lda #<$constValueName
ldy #>$constValueName
jsr floats.MOVFM
jsr floats.FPWRT
""")
}
"+" -> {
if (value == 0.0)
return

View File

@ -231,7 +231,6 @@ internal class ExpressionGen(val codeGen: CodeGen) {
">>" -> {
code += VmCodeInstruction(Instruction(Opcode.LSR, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
}
"**" -> throw AssemblyError("** operator requires floating point ${binExpr.position}")
// TODO the other operators: "==", "!=", "<", ">", "<=", ">="
else -> TODO("operator ${binExpr.operator}")
}

View File

@ -7,7 +7,6 @@ import prog8.ast.expressions.NumericLiteral
import prog8.code.core.DataType
import prog8.code.core.IntegerDatatypes
import prog8.code.core.Position
import kotlin.math.pow
class ConstExprEvaluator {
@ -20,7 +19,6 @@ class ConstExprEvaluator {
"*" -> multiply(left, right)
"/" -> divide(left, right)
"%" -> remainder(left, right)
"**" -> power(left, right)
"&" -> bitwiseand(left, right)
"|" -> bitwiseor(left, right)
"^" -> bitwisexor(left, right)
@ -150,23 +148,6 @@ class ConstExprEvaluator {
throw ExpressionError("cannot calculate $left & $right", left.position)
}
private fun power(left: NumericLiteral, right: NumericLiteral): NumericLiteral {
val error = "cannot calculate $left ** $right"
return when (left.type) {
in IntegerDatatypes -> when (right.type) {
in IntegerDatatypes -> NumericLiteral.optimalNumeric(left.number.toInt().toDouble().pow(right.number.toInt()), left.position)
DataType.FLOAT -> NumericLiteral(DataType.FLOAT, left.number.toInt().toDouble().pow(right.number), left.position)
else -> throw ExpressionError(error, left.position)
}
DataType.FLOAT -> when (right.type) {
in IntegerDatatypes -> NumericLiteral(DataType.FLOAT, left.number.pow(right.number.toInt()), left.position)
DataType.FLOAT -> NumericLiteral(DataType.FLOAT, left.number.pow(right.number), left.position)
else -> throw ExpressionError(error, left.position)
}
else -> throw ExpressionError(error, left.position)
}
}
private fun plus(left: NumericLiteral, right: NumericLiteral): NumericLiteral {
val error = "cannot add $left and $right"
return when (left.type) {

View File

@ -6,7 +6,6 @@ import prog8.ast.base.ExpressionError
import prog8.ast.base.FatalAstException
import prog8.ast.base.UndefinedSymbolError
import prog8.ast.expressions.*
import prog8.ast.statements.Assignment
import prog8.ast.statements.ForLoop
import prog8.ast.statements.VarDecl
import prog8.ast.statements.VarDeclType
@ -14,7 +13,6 @@ import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification
import prog8.code.core.DataType
import prog8.code.core.IntegerDatatypes
import kotlin.math.pow
class ConstantFoldingOptimizer(private val program: Program) : AstWalker() {
@ -140,42 +138,6 @@ class ConstantFoldingOptimizer(private val program: Program) : AstWalker() {
}
}
if(expr.operator == "**" && leftconst!=null) {
// optimize various simple cases of ** :
// optimize away 1 ** x into just 1 and 0 ** x into just 0
// optimize 2 ** x into (1<<x) if both operands are integer.
val leftDt = leftconst.inferType(program).getOr(DataType.UNDEFINED)
when (leftconst.number) {
0.0 -> {
val value = NumericLiteral(leftDt, 0.0, expr.position)
modifications += IAstModification.ReplaceNode(expr, value, parent)
}
1.0 -> {
val value = NumericLiteral(leftDt, 1.0, expr.position)
modifications += IAstModification.ReplaceNode(expr, value, parent)
}
2.0 -> {
if(rightconst!=null) {
val value = NumericLiteral(leftDt, 2.0.pow(rightconst.number), expr.position)
modifications += IAstModification.ReplaceNode(expr, value, parent)
} else {
val rightDt = expr.right.inferType(program).getOr(DataType.UNDEFINED)
if(leftDt in IntegerDatatypes && rightDt in IntegerDatatypes) {
val targetDt =
when (parent) {
is Assignment -> parent.target.inferType(program).getOr(DataType.UNDEFINED)
is VarDecl -> parent.datatype
else -> leftDt
}
val one = NumericLiteral(targetDt, 1.0, expr.position)
val shift = BinaryExpression(one, "<<", expr.right, expr.position)
modifications += IAstModification.ReplaceNode(expr, shift, parent)
}
}
}
}
}
if(expr.inferType(program) istype DataType.FLOAT) {
val subExpr: BinaryExpression? = when {
leftconst != null -> expr.right as? BinaryExpression

View File

@ -256,7 +256,6 @@ class ExpressionSimplifier(private val program: Program, private val errors: IEr
"/" -> optimizeDivision(expr, leftVal, rightVal)
"+" -> optimizeAdd(expr, leftVal, rightVal)
"-" -> optimizeSub(expr, leftVal, rightVal)
"**" -> optimizePower(expr, leftVal, rightVal)
"%" -> optimizeRemainder(expr, leftVal, rightVal)
">>" -> optimizeShiftRight(expr, rightVal)
"<<" -> optimizeShiftLeft(expr, rightVal)
@ -435,75 +434,6 @@ class ExpressionSimplifier(private val program: Program, private val errors: IEr
return null
}
private fun optimizePower(expr: BinaryExpression, leftVal: NumericLiteral?, rightVal: NumericLiteral?): Expression? {
if (leftVal == null && rightVal == null)
return null
if (rightVal != null) {
// right value is a constant, see if we can optimize
val rightConst: NumericLiteral = rightVal
when (rightConst.number) {
-3.0 -> {
// -1/(left*left*left)
return BinaryExpression(NumericLiteral(DataType.FLOAT, -1.0, expr.position), "/",
BinaryExpression(expr.left, "*", BinaryExpression(expr.left, "*", expr.left, expr.position), expr.position),
expr.position)
}
-2.0 -> {
// -1/(left*left)
return BinaryExpression(NumericLiteral(DataType.FLOAT, -1.0, expr.position), "/",
BinaryExpression(expr.left, "*", expr.left, expr.position),
expr.position)
}
-1.0 -> {
// -1/left
return BinaryExpression(NumericLiteral(DataType.FLOAT, -1.0, expr.position), "/",
expr.left, expr.position)
}
0.0 -> {
// 1
return NumericLiteral(rightConst.type, 1.0, expr.position)
}
0.5 -> {
// sqrt(left)
return FunctionCallExpression(IdentifierReference(listOf("sqrt"), expr.position), mutableListOf(expr.left), expr.position)
}
1.0 -> {
// left
return expr.left
}
2.0 -> {
// left*left
return BinaryExpression(expr.left, "*", expr.left, expr.position)
}
3.0 -> {
// left*left*left
return BinaryExpression(expr.left, "*", BinaryExpression(expr.left, "*", expr.left, expr.position), expr.position)
}
}
}
if (leftVal != null) {
// left value is a constant, see if we can optimize
when (leftVal.number) {
-1.0 -> {
// -1
return NumericLiteral(DataType.FLOAT, -1.0, expr.position)
}
0.0 -> {
// 0
return NumericLiteral(leftVal.type, 0.0, expr.position)
}
1.0 -> {
//1
return NumericLiteral(leftVal.type, 1.0, expr.position)
}
}
}
return null
}
private fun optimizeRemainder(expr: BinaryExpression, leftVal: NumericLiteral?, rightVal: NumericLiteral?): Expression? {
if (leftVal == null && rightVal == null)
return null

View File

@ -425,7 +425,6 @@ class StatementOptimizer(private val program: Program,
}
"*" -> if (rightCv == 1.0) return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
"/" -> if (rightCv == 1.0) return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
"**" -> if (rightCv == 1.0) return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
"|" -> if (rightCv == 0.0) return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
"^" -> if (rightCv == 0.0) return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
"<<" -> {

View File

@ -328,25 +328,6 @@ _internal ldx #<fmath_float1
jmp push_float
.pend
pow_f .proc
; -- push f1 ** f2 on stack
lda #<fmath_float2
ldy #>fmath_float2
jsr pop_float
lda #<fmath_float1
ldy #>fmath_float1
jsr pop_float
stx P8ZP_SCRATCH_REG
lda #<fmath_float1
ldy #>fmath_float1
jsr ROMUPK ; fac2 = float1
lda #<fmath_float2
ldy #>fmath_float2
jsr FPWR
jmp push_fac1._internal
.pend
div_f .proc
; -- push f1/f2 on stack
jsr pop_2_floats_f2_in_fac1

View File

@ -151,6 +151,23 @@ sub print_f (float value) {
}}
}
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
}}
}
%asminclude "library:c128/floats.asm"
%asminclude "library:c64/floats_funcs.asm"

View File

@ -335,25 +335,6 @@ _internal ldx #<fmath_float1
jmp push_float
.pend
pow_f .proc
; -- push f1 ** f2 on stack
lda #<fmath_float2
ldy #>fmath_float2
jsr pop_float
lda #<fmath_float1
ldy #>fmath_float1
jsr pop_float
stx P8ZP_SCRATCH_REG
lda #<fmath_float1
ldy #>fmath_float1
jsr CONUPK ; fac2 = float1
lda #<fmath_float2
ldy #>fmath_float2
jsr FPWR
jmp push_fac1._internal
.pend
div_f .proc
; -- push f1/f2 on stack
jsr pop_2_floats_f2_in_fac1

View File

@ -195,6 +195,22 @@ sub print_f (float value) {
}}
}
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
}}
}
%asminclude "library:c64/floats.asm"
%asminclude "library:c64/floats_funcs.asm"

View File

@ -156,6 +156,23 @@ sub print_f (float value) {
}}
}
sub pow(float value, float power) -> float {
%asm {{
phx
phy
lda #<value
ldy #>value
jsr floats.CONUPK
lda #<power
ldy #>power
jsr floats.MOVFM
jsr floats.FPWRT ; cx16 doesn't have FPWR
ply
plx
rts
}}
}
%asminclude "library:c64/floats.asm"
%asminclude "library:c64/floats_funcs.asm"

View File

@ -83,8 +83,8 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
importedFiles = imported
processAst(program, args.errors, compilationOptions)
if (compilationOptions.optimize) {
// println("*********** AST RIGHT BEFORE OPTIMIZING *************")
// printProgram(program)
println("*********** AST RIGHT BEFORE OPTIMIZING *************")
printProgram(program)
optimizeAst(
program,

View File

@ -853,10 +853,6 @@ internal class AstChecker(private val program: Program,
errors.err("remainder can only be used on unsigned integer operands", expr.right.position)
}
}
"**" -> {
if(leftDt in IntegerDatatypes)
errors.err("power operator requires floating point operands", expr.position)
}
"and", "or", "xor" -> {
// only integer numeric operands accepted, and if literal constants, only boolean values accepted (0 or 1)
if(leftDt !in IntegerDatatypes || rightDt !in IntegerDatatypes)

View File

@ -15,7 +15,7 @@ import kotlin.math.round
val AssociativeOperators = setOf("+", "*", "&", "|", "^", "or", "and", "xor", "==", "!=")
val ComparisonOperators = setOf("==", "!=", "<", ">", "<=", ">=")
val AugmentAssignmentOperators = setOf("+", "-", "/", "*", "**", "&", "|", "^", "<<", ">>", "%", "and", "or", "xor")
val AugmentAssignmentOperators = setOf("+", "-", "/", "*", "&", "|", "^", "<<", ">>", "%", "and", "or", "xor")
val LogicalOperators = setOf("and", "or", "xor", "not")
val BitwiseOperators = setOf("&", "|", "^")
@ -198,7 +198,7 @@ class BinaryExpression(var left: Expression, var operator: String, var right: Ex
val leftDt = left.inferType(program)
val rightDt = right.inferType(program)
return when (operator) {
"+", "-", "*", "**", "%", "/" -> {
"+", "-", "*", "%", "/" -> {
if (!leftDt.isKnown || !rightDt.isKnown)
InferredTypes.unknown()
else {

View File

@ -456,10 +456,9 @@ There are several escape sequences available to put special characters into your
Operators
---------
arithmetic: ``+`` ``-`` ``*`` ``/`` ``**`` ``%``
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. (it only works on floating point variables)
``%`` 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).

View File

@ -1,3 +1,4 @@
%import floats
%import textio
; NOTE: meant to test to virtual machine output target (use -target vitual)
@ -6,39 +7,34 @@ main {
sub start() {
txt.clear_screen()
txt.print("Welcome to a prog8 pixel shader :-)\n")
ubyte bb = 10
uword ww = 123
bb <<= 4
ww <<= 5
txt.print("bb=")
txt.print_ub(bb)
txt.nl()
txt.print("ww=")
txt.print_uw(ww)
float fl = 9.9
fl = floats.pow(fl, 3.0)
txt.print("fl=")
floats.print_f(fl)
txt.nl()
sys.exit(99)
syscall1(8, 0) ; enable lo res creen
ubyte shifter
shifter >>= 1
repeat {
uword xx
uword yy = 0
repeat 240 {
xx = 0
repeat 320 {
syscall3(10, xx, yy, xx*yy + shifter) ; plot pixel
xx++
}
yy++
}
shifter+=4
txt.print_ub(shifter)
txt.nl()
}
; syscall1(8, 0) ; enable lo res creen
; ubyte shifter
;
; shifter >>= 1
;
; repeat {
; uword xx
; uword yy = 0
; repeat 240 {
; xx = 0
; repeat 320 {
; syscall3(10, xx, yy, xx*yy + shifter) ; plot pixel
; xx++
; }
; yy++
; }
; shifter+=4
;
; txt.print_ub(shifter)
; txt.nl()
; }
}
}

View File

@ -147,7 +147,7 @@ arrayindex: '[' expression ']' ;
assignment : assign_target '=' expression ;
augassignment :
assign_target operator=('+=' | '-=' | '/=' | '*=' | '**=' | '&=' | '|=' | '^=' | '%=' | '<<=' | '>>=' ) expression
assign_target operator=('+=' | '-=' | '/=' | '*=' | '&=' | '|=' | '^=' | '%=' | '<<=' | '>>=' ) expression
;
assign_target:
@ -162,7 +162,6 @@ expression :
'(' expression ')'
| functioncall
| <assoc=right> prefix = ('+'|'-'|'~') expression
| left = expression EOL? bop = '**' EOL? right = expression
| left = expression EOL? bop = ('*' | '/' | '%' ) EOL? right = expression
| left = expression EOL? bop = ('+' | '-' ) EOL? right = expression
| left = expression EOL? bop = ('<<' | '>>' ) EOL? right = expression