compilation of prefix operators, added NOT opcode

This commit is contained in:
Irmen de Jong 2018-09-25 01:02:01 +02:00
parent 70e5a38aa2
commit d990b05998
5 changed files with 71 additions and 1 deletions

View File

@ -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

View File

@ -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)!!

View File

@ -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))

View File

@ -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(

View File

@ -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))
}
}