mirror of
https://github.com/irmen/prog8.git
synced 2025-02-21 10:29:03 +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 leftDt = left.resultingDatatype(namespace)
|
||||||
val rightDt = right.resultingDatatype(namespace)
|
val rightDt = right.resultingDatatype(namespace)
|
||||||
return when(operator) {
|
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 DataType.FLOAT
|
||||||
"//" -> if(leftDt==null || rightDt==null) null else integerDivisionOpDt(leftDt, rightDt)
|
"//" -> if(leftDt==null || rightDt==null) null else integerDivisionOpDt(leftDt, rightDt)
|
||||||
"&" -> leftDt
|
"&" -> leftDt
|
||||||
|
@ -294,6 +294,10 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram, priva
|
|||||||
is RegisterExpr -> {
|
is RegisterExpr -> {
|
||||||
stackvmProg.instr(Opcode.PUSH_VAR, Value(DataType.STR, null, expr.register.toString()))
|
stackvmProg.instr(Opcode.PUSH_VAR, Value(DataType.STR, null, expr.register.toString()))
|
||||||
}
|
}
|
||||||
|
is PrefixExpression -> {
|
||||||
|
translate(expr.expression)
|
||||||
|
translatePrefixOperator(expr.operator)
|
||||||
|
}
|
||||||
is BinaryExpression -> {
|
is BinaryExpression -> {
|
||||||
translate(expr.left)
|
translate(expr.left)
|
||||||
translate(expr.right)
|
translate(expr.right)
|
||||||
@ -399,6 +403,17 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram, priva
|
|||||||
stackvmProg.instr(opcode)
|
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) {
|
private fun translate(stmt: FunctionCallStatement) {
|
||||||
stackvmProg.line(stmt.position)
|
stackvmProg.line(stmt.position)
|
||||||
val targetStmt = stmt.target.targetStatement(namespace)!!
|
val targetStmt = stmt.target.targetStatement(namespace)!!
|
||||||
|
@ -75,6 +75,7 @@ enum class Opcode {
|
|||||||
AND,
|
AND,
|
||||||
OR,
|
OR,
|
||||||
XOR,
|
XOR,
|
||||||
|
NOT,
|
||||||
|
|
||||||
// increment, decrement
|
// increment, decrement
|
||||||
INC,
|
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 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 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 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 {
|
fun inv(): Value {
|
||||||
return when(type) {
|
return when(type) {
|
||||||
@ -1485,6 +1487,10 @@ class StackVm(val traceOutputFile: String?) {
|
|||||||
val (top, second) = evalstack.pop2()
|
val (top, second) = evalstack.pop2()
|
||||||
evalstack.push(second.xor(top))
|
evalstack.push(second.xor(top))
|
||||||
}
|
}
|
||||||
|
Opcode.NOT -> {
|
||||||
|
val value = evalstack.pop()
|
||||||
|
evalstack.push(value.not())
|
||||||
|
}
|
||||||
Opcode.LESS -> {
|
Opcode.LESS -> {
|
||||||
val (top, second) = evalstack.pop2()
|
val (top, second) = evalstack.pop2()
|
||||||
evalstack.push(Value(DataType.BYTE, if(second < top) 1 else 0))
|
evalstack.push(Value(DataType.BYTE, if(second < top) 1 else 0))
|
||||||
|
@ -522,6 +522,32 @@ class TestStackVmOpcodes {
|
|||||||
testBinaryOperator(values, operator, expected)
|
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
|
@Test
|
||||||
fun testInc() {
|
fun testInc() {
|
||||||
val values = listOf(
|
val values = listOf(
|
||||||
|
@ -197,6 +197,29 @@ class TestStackVmValue {
|
|||||||
assertEquals(DataType.WORD, r.type)
|
assertEquals(DataType.WORD, r.type)
|
||||||
assertEquals(33, r.integerValue())
|
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