diff --git a/codeCore/src/prog8/code/ast/AstExpressions.kt b/codeCore/src/prog8/code/ast/AstExpressions.kt index da4b2f888..76393ded8 100644 --- a/codeCore/src/prog8/code/ast/AstExpressions.kt +++ b/codeCore/src/prog8/code/ast/AstExpressions.kt @@ -318,7 +318,7 @@ class PtPrefix(val operator: String, type: DataType, position: Position): PtExpr get() = children.single() as PtExpression init { - require(operator in setOf("+", "-", "~", "not")) { "invalid prefix operator: $operator" } + require(operator in setOf("+", "-", "~", "^", "<<", "not")) { "invalid prefix operator: $operator" } } } diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index ccf6e3a0e..053871f5f 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -24,7 +24,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, val sscope = fcall.definingISub() when (fcall.name) { - "bankof" -> throw AssemblyError("bankof() should have been replaced by a const value at all times (either the bank number of a long const, or zero for any other smaller value)") + "bankof" -> throw AssemblyError("bankof() should have been replaced by a const value (either the bank number of a long const, or zero for any other smaller value)") "msb" -> funcMsb(fcall, resultRegister) "lsb" -> funcLsb(fcall, resultRegister) "mkword" -> funcMkword(fcall, resultRegister) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index b58c0fd82..d4eaee6eb 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -536,6 +536,10 @@ internal class AssignmentAsmGen( } } is PtPrefix -> { + if(value.operator=="^") + throw AssemblyError("unary ^ should have been replaced by a const value (either the bank number of a long const, or zero for any other smaller value)") + if(value.operator=="<<") + throw AssemblyError("unary << should have been replaced by a const uword") if(assign.target.array==null) { if(assign.source.datatype isAssignableTo assign.target.datatype || (assign.source.datatype==DataType.BOOL && assign.target.datatype in ByteDatatypes)) { if(assign.source.datatype in IntegerDatatypesWithBoolean) { diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt index 8947da8fd..caf93b0e7 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt @@ -19,7 +19,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe "callfar" -> funcCallfar(call) "callfar2" -> funcCallfar2(call) "call" -> funcCall(call) - "bankof" -> throw AssemblyError("bankof() should have been replaced by a const value at all times (either the bank number of a long const, or zero for any other smaller value)") + "bankof" -> throw AssemblyError("bankof() should have been replaced by a const value (either the bank number of a long const, or zero for any other smaller value)") "msb" -> funcMsb(call) "lsb" -> funcLsb(call) "memory" -> funcMemory(call) diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt index 3c8f16cfd..825a18209 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt @@ -373,6 +373,8 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { "not" -> { addInstr(result, IRInstruction(Opcode.XOR, vmDt, reg1 = tr.resultReg, immediate = 1), null) } + "^" -> throw AssemblyError("unary ^ should have been replaced by a const value (either the bank number of a long const, or zero for any other smaller value)") + "<<" -> throw AssemblyError("unary << should have been replaced by a const uword") else -> throw AssemblyError("weird prefix operator") } return ExpressionCodeResult(result, vmDt, tr.resultReg, tr.resultFpReg) diff --git a/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt b/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt index 0b6994086..7940e8d9a 100644 --- a/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt +++ b/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt @@ -148,6 +148,22 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter, return listOf(IAstModification.ReplaceNode(expr, expr.expression, parent)) } + if(expr.operator=="<<") { + // << X --> X (X is word or byte) + val valueDt = expr.expression.inferType(program) + if(valueDt.isBytes || valueDt.isWords) { + return listOf(IAstModification.ReplaceNode(expr, expr.expression, parent)) + } + } + + if(expr.operator=="^") { + // ^ X --> 0 (X is word or byte) + val valueDt = expr.expression.inferType(program) + if(valueDt.isBytes || valueDt.isWords) { + val zero = NumericLiteral(DataType.UBYTE, 0.0, expr.expression.position) + return listOf(IAstModification.ReplaceNode(expr, zero, parent)) + } + } return noModifications } diff --git a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt index 4a44709f2..889683c24 100644 --- a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt +++ b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt @@ -13,6 +13,7 @@ import prog8.code.target.encodings.JapaneseCharacterConverter import java.io.CharConversionException import java.util.Objects import kotlin.math.abs +import kotlin.math.exp import kotlin.math.floor import kotlin.math.truncate @@ -98,6 +99,11 @@ class PrefixExpression(val operator: String, var expression: Expression, overrid override fun copy() = PrefixExpression(operator, expression.copy(), position) override fun constValue(program: Program): NumericLiteral? { + if(operator=="^") { + val valueDt = expression.inferType(program) + if(valueDt.isBytes || valueDt.isWords) + return NumericLiteral(DataType.UBYTE, 0.0, expression.position) + } val constval = expression.constValue(program) ?: return null val converted = when(operator) { "+" -> constval @@ -114,6 +120,8 @@ class PrefixExpression(val operator: String, var expression: Expression, overrid else -> throw ExpressionError("can only take bitwise inversion of int", constval.position) } "not" -> NumericLiteral.fromBoolean(constval.number==0.0, constval.position) + "^" -> NumericLiteral(DataType.UBYTE, (constval.number.toInt() ushr 16 and 255).toDouble(), constval.position) // bank + "<<" -> NumericLiteral(DataType.UWORD, (constval.number.toInt() and 65535).toDouble(), constval.position) // address else -> throw FatalAstException("invalid operator") } converted.linkParents(this.parent) @@ -138,6 +146,8 @@ class PrefixExpression(val operator: String, var expression: Expression, overrid else if(inferred.isWords) InferredTypes.knownFor(DataType.WORD) else inferred } + "^" -> InferredTypes.knownFor(DataType.UBYTE) + "<<" -> InferredTypes.knownFor(DataType.UWORD) else -> throw FatalAstException("weird prefix expression operator") } } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 7215255d6..8f8079e71 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,9 +1,11 @@ TODO ==== -what to do with bnk(): it's an awkward name but bank() is too general a name and will forbid you to use 'bank' as a variable... +what to do with bankof(): keep it? add another syntax like \`value or ^value to get the bank byte? add a function like addr() or lsw() to complement bnk() in getting easy access to the lower 16 bits of a long integer? - +-> added unary ^ operator as alternative to bankof() +-> added unary << operator as alternative to addr() / lsb(x>>16) / lsw() +-> TODO document whatever remains of those! ... diff --git a/examples/test.p8 b/examples/test.p8 index cac9dc740..412805716 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -4,6 +4,20 @@ main { sub start() { const long foo2 = $123456 + cx16.r0 = $ffff + cx16.r1 = $ea31 + txt.print_uwbin(cx16.r1 << 7, true) + txt.nl() + txt.print_uwhex(cx16.r0 ^ cx16.r1, true) + txt.nl() + txt.print_ubhex(^cx16.r0, true) + txt.spc() + txt.print_uwhex(< prefix = ('+'|'-'|'~') expression + | prefix = ('+'|'-'|'~'|'^'|'<<') expression | left = expression EOL? bop = ('*' | '/' | '%' ) EOL? right = expression | left = expression EOL? bop = ('+' | '-' ) EOL? right = expression | left = expression EOL? bop = ('<<' | '>>' ) EOL? right = expression