add 'not equal' operator

This commit is contained in:
r4 2021-12-26 12:19:54 +01:00
parent 1f47b5e16c
commit 18d6e7b7df
8 changed files with 34 additions and 11 deletions

2
ir.c
View File

@ -11,6 +11,7 @@ const char *irinstr_str[IRInstrEnumSize] = {
[IRMul] = "mul", [IRMul] = "mul",
[IRDiv] = "div", [IRDiv] = "div",
[IREq] = "eq", [IREq] = "eq",
[IRNeq] = "neq",
[IRLt] = "lt", [IRLt] = "lt",
[IRLe] = "le", [IRLe] = "le",
[IRNot] = "not", [IRNot] = "not",
@ -98,6 +99,7 @@ void print_ir(IRToks *v, const BuiltinFunc *builtin_funcs) {
case IRDiv: case IRDiv:
case IRMul: case IRMul:
case IREq: case IREq:
case IRNeq:
case IRLt: case IRLt:
case IRLe: case IRLe:
case IRAnd: case IRAnd:

1
ir.h
View File

@ -19,6 +19,7 @@ enum IRInstr {
IRMul, IRMul,
IRDiv, IRDiv,
IREq, IREq,
IRNeq,
IRLt, IRLt,
IRLe, IRLe,
IRNot, IRNot,

18
lex.c
View File

@ -222,18 +222,27 @@ TokList lex(const char *s, Pool *static_vars) {
continue; continue;
} }
break; 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 '&': case '&':
consume(&pos, *(s++)); consume(&pos, *(s++));
if (s[0] == '&') { if (s[0] == '&')
emit(&toks, &pos, (Tok){ .kind = TokOp, .Op = OpAnd }); emit(&toks, &pos, (Tok){ .kind = TokOp, .Op = OpAnd });
} else else
continue; continue;
break; break;
case '|': case '|':
consume(&pos, *(s++)); consume(&pos, *(s++));
if (s[0] == '|') { if (s[0] == '|')
emit(&toks, &pos, (Tok){ .kind = TokOp, .Op = OpOr }); emit(&toks, &pos, (Tok){ .kind = TokOp, .Op = OpOr });
} else else
continue; continue;
break; break;
case '{': case '{':
@ -244,7 +253,6 @@ TokList lex(const char *s, Pool *static_vars) {
case '+': case '+':
case '-': case '-':
case '*': case '*':
case '!':
emit(&toks, &pos, (Tok){ emit(&toks, &pos, (Tok){
.kind = TokOp, .kind = TokOp,
.Op = s[0], .Op = s[0],

View File

@ -54,6 +54,7 @@ static void set_irtok_dest_addr(IRTok *t, size_t addr) {
case IRMul: case IRMul:
case IRDiv: case IRDiv:
case IREq: case IREq:
case IRNeq:
case IRLt: case IRLt:
case IRLe: case IRLe:
case IRAnd: 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 OpMul: instr = IRMul; break;
case OpDiv: instr = IRDiv; break; case OpDiv: instr = IRDiv; break;
case OpEq: instr = IREq; break; case OpEq: instr = IREq; break;
case OpNeq: instr = IRNeq; break;
case OpLt: instr = IRLt; break; case OpLt: instr = IRLt; break;
case OpLe: instr = IRLe; break; case OpLe: instr = IRLe; break;
case OpGt: instr = IRLt; swap_operands = true; break; case OpGt: instr = IRLt; swap_operands = true; break;

View File

@ -40,21 +40,24 @@ Value eval_binary(IRInstr instr, const Value *lhs, const Value *rhs) {
} }
} }
case IREq: case IREq:
case IRNeq:
case IRLt: case IRLt:
case IRLe: { case IRLe: {
bool res; bool res;
if (lhs->type.kind == TypeInt && rhs->type.kind == TypeInt) { if (lhs->type.kind == TypeInt && rhs->type.kind == TypeInt) {
switch (instr) { switch (instr) {
case IREq: res = lhs->Int == rhs->Int; break; case IREq: res = lhs->Int == rhs->Int; break;
case IRLt: res = lhs->Int < rhs->Int; break; case IRNeq: res = lhs->Int != rhs->Int; break;
case IRLe: 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(); default: ASSERT_UNREACHED();
}; };
} else if (lhs->type.kind == TypeFloat && rhs->type.kind == TypeFloat) { } else if (lhs->type.kind == TypeFloat && rhs->type.kind == TypeFloat) {
switch (instr) { switch (instr) {
case IREq: res = lhs->Float == rhs->Float; break; case IREq: res = lhs->Float == rhs->Float; break;
case IRLt: res = lhs->Float < rhs->Float; break; case IRNeq: res = lhs->Float != rhs->Float; break;
case IRLe: 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(); default: ASSERT_UNREACHED();
}; };
} else if (lhs->type.kind == TypeArr && lhs->Arr.type.kind == TypeChar && lhs->Arr.is_string && } 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: case IREq:
res = lhs->Arr.len == rhs->Arr.len ? strncmp(lhs->Arr.vals, rhs->Arr.vals, lhs->Arr.len) == 0 : false; res = lhs->Arr.len == rhs->Arr.len ? strncmp(lhs->Arr.vals, rhs->Arr.vals, lhs->Arr.len) == 0 : false;
break; break;
case IRNeq:
res = lhs->Arr.len == rhs->Arr.len ? strncmp(lhs->Arr.vals, rhs->Arr.vals, lhs->Arr.len) != 0 : true;
break;
default: default:
set_err("String operation '%s' not supported", irinstr_str[instr]); set_err("String operation '%s' not supported", irinstr_str[instr]);
break; break;

2
tok.c
View File

@ -92,6 +92,7 @@ int8_t op_prec[OperatorEnumSize] = {
[OpAnd] = 0, [OpAnd] = 0,
[OpOr] = 0, [OpOr] = 0,
[OpEq] = 1, [OpEq] = 1,
[OpNeq] = 1,
[OpLt] = 1, [OpLt] = 1,
[OpGt] = 1, [OpGt] = 1,
[OpLe] = 1, [OpLe] = 1,
@ -116,6 +117,7 @@ const char *op_str[OperatorEnumSize] = {
[OpNewLn] = "\\n", [OpNewLn] = "\\n",
[OpEOF] = "EOF", [OpEOF] = "EOF",
[OpEq] = "==", [OpEq] = "==",
[OpNeq] = "!=",
[OpLt] = "<", [OpLt] = "<",
[OpGt] = ">", [OpGt] = ">",
[OpLe] = "<=", [OpLe] = "<=",

1
tok.h
View File

@ -57,6 +57,7 @@ enum Operator {
OpNot = '!', OpNot = '!',
OpBeginNonchars = 256, OpBeginNonchars = 256,
OpEq, OpEq,
OpNeq,
OpLt, OpLt,
OpGt, OpGt,
OpLe, OpLe,

1
vm.c
View File

@ -65,6 +65,7 @@ void run(const IRToks *ir, const BuiltinFunc *builtin_funcs) {
case IRDiv: case IRDiv:
case IRMul: case IRMul:
case IREq: case IREq:
case IRNeq:
case IRLt: case IRLt:
case IRLe: case IRLe:
case IRAnd: case IRAnd: