From 18d6e7b7df629e582aaed0c5a2f378d3c14ee831 Mon Sep 17 00:00:00 2001 From: r4 Date: Sun, 26 Dec 2021 12:19:54 +0100 Subject: [PATCH] add 'not equal' operator --- ir.c | 2 ++ ir.h | 1 + lex.c | 18 +++++++++++++----- parse.c | 2 ++ runtime.c | 18 ++++++++++++------ tok.c | 2 ++ tok.h | 1 + vm.c | 1 + 8 files changed, 34 insertions(+), 11 deletions(-) diff --git a/ir.c b/ir.c index be80a42..290a27d 100644 --- a/ir.c +++ b/ir.c @@ -11,6 +11,7 @@ const char *irinstr_str[IRInstrEnumSize] = { [IRMul] = "mul", [IRDiv] = "div", [IREq] = "eq", + [IRNeq] = "neq", [IRLt] = "lt", [IRLe] = "le", [IRNot] = "not", @@ -98,6 +99,7 @@ void print_ir(IRToks *v, const BuiltinFunc *builtin_funcs) { case IRDiv: case IRMul: case IREq: + case IRNeq: case IRLt: case IRLe: case IRAnd: diff --git a/ir.h b/ir.h index a229afd..adb2ab9 100644 --- a/ir.h +++ b/ir.h @@ -19,6 +19,7 @@ enum IRInstr { IRMul, IRDiv, IREq, + IRNeq, IRLt, IRLe, IRNot, diff --git a/lex.c b/lex.c index 3184650..5234ea5 100644 --- a/lex.c +++ b/lex.c @@ -222,18 +222,27 @@ TokList lex(const char *s, Pool *static_vars) { continue; } break; + case '!': + consume(&pos, *(s++)); + if (s[0] == '=') + emit(&toks, &pos, (Tok){ .kind = TokOp, .Op = OpNeq, }); + else { + emit(&toks, &pos, (Tok){ .kind = TokOp, .Op = OpNot, }); + continue; + } + break; case '&': consume(&pos, *(s++)); - if (s[0] == '&') { + if (s[0] == '&') emit(&toks, &pos, (Tok){ .kind = TokOp, .Op = OpAnd }); - } else + else continue; break; case '|': consume(&pos, *(s++)); - if (s[0] == '|') { + if (s[0] == '|') emit(&toks, &pos, (Tok){ .kind = TokOp, .Op = OpOr }); - } else + else continue; break; case '{': @@ -244,7 +253,6 @@ TokList lex(const char *s, Pool *static_vars) { case '+': case '-': case '*': - case '!': emit(&toks, &pos, (Tok){ .kind = TokOp, .Op = s[0], diff --git a/parse.c b/parse.c index 819e815..2ee79a6 100644 --- a/parse.c +++ b/parse.c @@ -54,6 +54,7 @@ static void set_irtok_dest_addr(IRTok *t, size_t addr) { case IRMul: case IRDiv: case IREq: + case IRNeq: case IRLt: case IRLe: case IRAnd: @@ -457,6 +458,7 @@ static ExprRet expr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, case OpMul: instr = IRMul; break; case OpDiv: instr = IRDiv; break; case OpEq: instr = IREq; break; + case OpNeq: instr = IRNeq; break; case OpLt: instr = IRLt; break; case OpLe: instr = IRLe; break; case OpGt: instr = IRLt; swap_operands = true; break; diff --git a/runtime.c b/runtime.c index 6ae7049..ed81af2 100644 --- a/runtime.c +++ b/runtime.c @@ -40,21 +40,24 @@ Value eval_binary(IRInstr instr, const Value *lhs, const Value *rhs) { } } case IREq: + case IRNeq: case IRLt: case IRLe: { bool res; if (lhs->type.kind == TypeInt && rhs->type.kind == TypeInt) { switch (instr) { - case IREq: res = lhs->Int == rhs->Int; break; - case IRLt: res = lhs->Int < rhs->Int; break; - case IRLe: res = lhs->Int <= rhs->Int; break; + case IREq: res = lhs->Int == rhs->Int; break; + case IRNeq: res = lhs->Int != rhs->Int; break; + case IRLt: res = lhs->Int < rhs->Int; break; + case IRLe: res = lhs->Int <= rhs->Int; break; default: ASSERT_UNREACHED(); }; } else if (lhs->type.kind == TypeFloat && rhs->type.kind == TypeFloat) { switch (instr) { - case IREq: res = lhs->Float == rhs->Float; break; - case IRLt: res = lhs->Float < rhs->Float; break; - case IRLe: res = lhs->Float <= rhs->Float; break; + case IREq: res = lhs->Float == rhs->Float; break; + case IRNeq: res = lhs->Float != rhs->Float; break; + case IRLt: res = lhs->Float < rhs->Float; break; + case IRLe: res = lhs->Float <= rhs->Float; break; default: ASSERT_UNREACHED(); }; } else if (lhs->type.kind == TypeArr && lhs->Arr.type.kind == TypeChar && lhs->Arr.is_string && @@ -63,6 +66,9 @@ Value eval_binary(IRInstr instr, const Value *lhs, const Value *rhs) { case IREq: res = lhs->Arr.len == rhs->Arr.len ? strncmp(lhs->Arr.vals, rhs->Arr.vals, lhs->Arr.len) == 0 : false; break; + case IRNeq: + res = lhs->Arr.len == rhs->Arr.len ? strncmp(lhs->Arr.vals, rhs->Arr.vals, lhs->Arr.len) != 0 : true; + break; default: set_err("String operation '%s' not supported", irinstr_str[instr]); break; diff --git a/tok.c b/tok.c index 63215ae..5da8184 100644 --- a/tok.c +++ b/tok.c @@ -92,6 +92,7 @@ int8_t op_prec[OperatorEnumSize] = { [OpAnd] = 0, [OpOr] = 0, [OpEq] = 1, + [OpNeq] = 1, [OpLt] = 1, [OpGt] = 1, [OpLe] = 1, @@ -116,6 +117,7 @@ const char *op_str[OperatorEnumSize] = { [OpNewLn] = "\\n", [OpEOF] = "EOF", [OpEq] = "==", + [OpNeq] = "!=", [OpLt] = "<", [OpGt] = ">", [OpLe] = "<=", diff --git a/tok.h b/tok.h index 32fe39d..f935798 100644 --- a/tok.h +++ b/tok.h @@ -57,6 +57,7 @@ enum Operator { OpNot = '!', OpBeginNonchars = 256, OpEq, + OpNeq, OpLt, OpGt, OpLe, diff --git a/vm.c b/vm.c index 6e7e218..bf323ef 100644 --- a/vm.c +++ b/vm.c @@ -65,6 +65,7 @@ void run(const IRToks *ir, const BuiltinFunc *builtin_funcs) { case IRDiv: case IRMul: case IREq: + case IRNeq: case IRLt: case IRLe: case IRAnd: