diff --git a/tools/compiler/compiler.c b/tools/compiler/compiler.c index 738763a..a909904 100644 --- a/tools/compiler/compiler.c +++ b/tools/compiler/compiler.c @@ -240,10 +240,7 @@ static void unary() { switch (operatorType) { case TOKEN_MINUS: { - code[cp++] = OP_PUSH_8; - code[cp++] = 0; - code[cp++] = OP_EXCH; - code[cp++] = OP_SUB_INT; // kinda cheating, should work + code[cp++] = OP_NEG; break; } case TOKEN_BANG: { @@ -259,22 +256,85 @@ static void binary() { TokenType operatorType = parser.previous.type; ParseRule *rule = getRule(operatorType); parsePrecedence((Precedence)(rule->precedence + 1)); - switch (operatorType) { case TOKEN_PLUS: { - code[cp++] = OP_ADD_INT; + switch (parser.previous.type) { + case TOKEN_LITERAL_INT: + code[cp++] = OP_ADD_INT; + break; + case TOKEN_LITERAL_NAT: + code[cp++] = OP_ADD_NAT; + break; + case TOKEN_LITERAL_REAL: + code[cp++] = OP_ADD_REAL; + break; + case TOKEN_IDENTIFIER: + printf("FIXME: find the identifier's type for add\n"); + break; + default: + printf("Unknown Add Arg=%d\n", parser.previous.type); + return; // Unreachable. + } break; } case TOKEN_MINUS: { - code[cp++] = OP_SUB_INT; + switch (parser.previous.type) { + case TOKEN_LITERAL_INT: + code[cp++] = OP_SUB_INT; + break; + case TOKEN_LITERAL_NAT: + code[cp++] = OP_SUB_NAT; + break; + case TOKEN_LITERAL_REAL: + code[cp++] = OP_SUB_REAL; + break; + case TOKEN_IDENTIFIER: + printf("FIXME: find the identifier's type for sub\n"); + break; + default: + printf("Unknown Sub Arg=%d\n", parser.previous.type); + return; // Unreachable. + } break; } case TOKEN_STAR: { - code[cp++] = OP_MUL_INT; + switch (parser.previous.type) { + case TOKEN_LITERAL_INT: + code[cp++] = OP_MUL_INT; + break; + case TOKEN_LITERAL_NAT: + code[cp++] = OP_MUL_NAT; + break; + case TOKEN_LITERAL_REAL: + code[cp++] = OP_MUL_REAL; + break; + case TOKEN_IDENTIFIER: + printf("FIXME: find the identifier's type for mul\n"); + break; + default: + printf("Unknown Mul Arg=%d\n", parser.previous.type); + return; // Unreachable. + } break; } case TOKEN_SLASH: { - code[cp++] = OP_DIV_INT; + switch (parser.previous.type) { + case TOKEN_LITERAL_INT: + code[cp++] = OP_DIV_INT; + break; + case TOKEN_LITERAL_NAT: + code[cp++] = OP_DIV_NAT; + break; + case TOKEN_LITERAL_REAL: + code[cp++] = OP_DIV_REAL; + break; + case TOKEN_IDENTIFIER: + printf("FIXME: find the identifier's type for div\n"); + break; + default: + printf("Unknown Div Arg=%d\n", parser.previous.type); + return; // Unreachable. + } break; } case TOKEN_EQ_EQ: { diff --git a/vm/vm.c b/vm/vm.c index cda8997..ea3a8dc 100644 --- a/vm/vm.c +++ b/vm/vm.c @@ -389,6 +389,11 @@ bool step_vm() { stack[sp++] = result; return true; } + case OP_NEG: { + i32 a = (i32)stack[--sp]; + stack[sp++] = -a; + return true; + } case OP_NOT: { u32 a = !stack[--sp]; stack[sp++] = a; diff --git a/vm/vm.h b/vm/vm.h index 7656e88..3017631 100644 --- a/vm/vm.h +++ b/vm/vm.h @@ -60,6 +60,7 @@ typedef enum { OP_BIT_AND, /* obj2 obj1 `bit_and` obj | obj1 & obj2 */ OP_BIT_OR, /* obj2 obj1 `bit_or` obj | obj1 | obj2 */ OP_BIT_XOR, /* obj2 obj1 `bit_xor` obj | obj1 ^ obj2 */ + OP_NEG, /* obj1 `neg` -obj | -obj1 */ OP_NOT, /* obj1 `bit_xor` !obj | not obj1 */ OP_JMP, /* pc `jump` | jump unconditionally */ OP_JMP_FLAG, /* pc `jump_if_flag` | jump to pc if flag > 0 */