mirror of
https://github.com/irmen/prog8.git
synced 2025-02-16 22:30:46 +00:00
compilation of prefix operators, added NOT opcode
This commit is contained in:
parent
70e5a38aa2
commit
d990b05998
@ -725,7 +725,7 @@ class BinaryExpression(var left: IExpression, val operator: String, var right: I
|
||||
val leftDt = left.resultingDatatype(namespace)
|
||||
val rightDt = right.resultingDatatype(namespace)
|
||||
return when(operator) {
|
||||
"+", "-", "*", "**" -> if(leftDt==null || rightDt==null) null else arithmeticOpDt(leftDt, rightDt)
|
||||
"+", "-", "*", "**", "%" -> if(leftDt==null || rightDt==null) null else arithmeticOpDt(leftDt, rightDt)
|
||||
"/" -> if(leftDt==null || rightDt==null) null else DataType.FLOAT
|
||||
"//" -> if(leftDt==null || rightDt==null) null else integerDivisionOpDt(leftDt, rightDt)
|
||||
"&" -> leftDt
|
||||
|
@ -294,6 +294,10 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram, priva
|
||||
is RegisterExpr -> {
|
||||
stackvmProg.instr(Opcode.PUSH_VAR, Value(DataType.STR, null, expr.register.toString()))
|
||||
}
|
||||
is PrefixExpression -> {
|
||||
translate(expr.expression)
|
||||
translatePrefixOperator(expr.operator)
|
||||
}
|
||||
is BinaryExpression -> {
|
||||
translate(expr.left)
|
||||
translate(expr.right)
|
||||
@ -399,6 +403,17 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram, priva
|
||||
stackvmProg.instr(opcode)
|
||||
}
|
||||
|
||||
private fun translatePrefixOperator(operator: String) {
|
||||
val opcode = when(operator) {
|
||||
"+" -> Opcode.NOP
|
||||
"-" -> Opcode.NEG
|
||||
"~" -> Opcode.INV
|
||||
"not" -> Opcode.NOT
|
||||
else -> throw FatalAstException("const evaluation for invalid prefix operator $operator")
|
||||
}
|
||||
stackvmProg.instr(opcode)
|
||||
}
|
||||
|
||||
private fun translate(stmt: FunctionCallStatement) {
|
||||
stackvmProg.line(stmt.position)
|
||||
val targetStmt = stmt.target.targetStatement(namespace)!!
|
||||
|
@ -75,6 +75,7 @@ enum class Opcode {
|
||||
AND,
|
||||
OR,
|
||||
XOR,
|
||||
NOT,
|
||||
|
||||
// increment, decrement
|
||||
INC,
|
||||
@ -546,6 +547,7 @@ class Value(val type: DataType, numericvalue: Number?, val stringvalue: String?=
|
||||
fun and(other: Value) = Value(DataType.BYTE, if(this.asBooleanValue && other.asBooleanValue) 1 else 0)
|
||||
fun or(other: Value) = Value(DataType.BYTE, if(this.asBooleanValue || other.asBooleanValue) 1 else 0)
|
||||
fun xor(other: Value) = Value(DataType.BYTE, if(this.asBooleanValue xor other.asBooleanValue) 1 else 0)
|
||||
fun not() = Value(DataType.BYTE, if(this.asBooleanValue) 0 else 1)
|
||||
|
||||
fun inv(): Value {
|
||||
return when(type) {
|
||||
@ -1485,6 +1487,10 @@ class StackVm(val traceOutputFile: String?) {
|
||||
val (top, second) = evalstack.pop2()
|
||||
evalstack.push(second.xor(top))
|
||||
}
|
||||
Opcode.NOT -> {
|
||||
val value = evalstack.pop()
|
||||
evalstack.push(value.not())
|
||||
}
|
||||
Opcode.LESS -> {
|
||||
val (top, second) = evalstack.pop2()
|
||||
evalstack.push(Value(DataType.BYTE, if(second < top) 1 else 0))
|
||||
|
@ -522,6 +522,32 @@ class TestStackVmOpcodes {
|
||||
testBinaryOperator(values, operator, expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNot() {
|
||||
val values = listOf(
|
||||
Value(DataType.STR, null, ""),
|
||||
Value(DataType.STR, null, "hello"),
|
||||
Value(DataType.FLOAT, 0.0),
|
||||
Value(DataType.FLOAT, 300.33),
|
||||
Value(DataType.WORD, 0),
|
||||
Value(DataType.WORD, 5000),
|
||||
Value(DataType.BYTE, 0),
|
||||
Value(DataType.BYTE, 20))
|
||||
val expected = listOf(
|
||||
Value(DataType.BYTE, 0),
|
||||
Value(DataType.BYTE, 1),
|
||||
Value(DataType.BYTE, 0),
|
||||
Value(DataType.BYTE, 1),
|
||||
Value(DataType.BYTE, 0),
|
||||
Value(DataType.BYTE, 1),
|
||||
Value(DataType.BYTE, 0),
|
||||
Value(DataType.BYTE, 1)
|
||||
)
|
||||
val operator = Opcode.NOT
|
||||
|
||||
testUnaryOperator(values, operator, expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testInc() {
|
||||
val values = listOf(
|
||||
|
@ -197,6 +197,29 @@ class TestStackVmValue {
|
||||
assertEquals(DataType.WORD, r.type)
|
||||
assertEquals(33, r.integerValue())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNoAutoFloatConversion() {
|
||||
assertFailsWith<VmExecutionException> {
|
||||
Value(DataType.BYTE, 233).add(Value(DataType.FLOAT, 1.234))
|
||||
}
|
||||
assertFailsWith<VmExecutionException> {
|
||||
Value(DataType.WORD, 233).add(Value(DataType.FLOAT, 1.234))
|
||||
}
|
||||
assertFailsWith<VmExecutionException> {
|
||||
Value(DataType.BYTE, 233).mul(Value(DataType.FLOAT, 1.234))
|
||||
}
|
||||
assertFailsWith<VmExecutionException> {
|
||||
Value(DataType.WORD, 233).mul(Value(DataType.FLOAT, 1.234))
|
||||
}
|
||||
assertFailsWith<VmExecutionException> {
|
||||
Value(DataType.BYTE, 233).div(Value(DataType.FLOAT, 1.234))
|
||||
}
|
||||
assertFailsWith<VmExecutionException> {
|
||||
Value(DataType.WORD, 233).div(Value(DataType.FLOAT, 1.234))
|
||||
}
|
||||
val result = Value(DataType.FLOAT, 233.333).add(Value(DataType.FLOAT, 1.234))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user