From 6bdc4e3210414d061965cb05615f3320b90a9f98 Mon Sep 17 00:00:00 2001 From: r4 Date: Thu, 23 Dec 2021 21:42:09 +0100 Subject: [PATCH] add logical or and logical and --- ir.c | 4 ++++ ir.h | 2 ++ lex.c | 14 ++++++++++++++ parse.c | 4 ++++ runtime.c | 12 ++++++++++++ tok.c | 22 +++++++++++++--------- tok.h | 2 ++ vm.c | 2 ++ 8 files changed, 53 insertions(+), 9 deletions(-) diff --git a/ir.c b/ir.c index 9afbbfc..542bfd9 100644 --- a/ir.c +++ b/ir.c @@ -14,6 +14,8 @@ const char *irinstr_str[IRInstrEnumSize] = { [IRLt] = "lt", [IRLe] = "le", [IRNot] = "not", + [IRAnd] = "and", + [IROr] = "or", [IRJmp] = "jmp", [IRJnz] = "jnz", [IRCallInternal] = "calli", @@ -119,6 +121,8 @@ void print_ir(IRToks *v, const BuiltinFunc *builtin_funcs) { case IREq: case IRLt: case IRLe: + case IRAnd: + case IROr: printf(" %%%zx ", v->toks[i].Binary.addr); print_irparam(&v->toks[i].Binary.lhs); printf(" "); diff --git a/ir.h b/ir.h index 1ab87d2..01f6814 100644 --- a/ir.h +++ b/ir.h @@ -22,6 +22,8 @@ enum IRInstr { IRLt, IRLe, IRNot, + IRAnd, + IROr, IRJmp, IRJnz, IRCallInternal, diff --git a/lex.c b/lex.c index bc42e3c..2e57395 100644 --- a/lex.c +++ b/lex.c @@ -218,6 +218,20 @@ TokList lex(const char *s) { continue; } break; + case '&': + consume(&pos, *(s++)); + if (s[0] == '&') { + emit(&toks, &pos, (Tok){ .kind = TokOp, .Op = OpAnd }); + } else + continue; + break; + case '|': + consume(&pos, *(s++)); + if (s[0] == '|') { + emit(&toks, &pos, (Tok){ .kind = TokOp, .Op = OpOr }); + } else + continue; + break; case '{': case '}': case '(': diff --git a/parse.c b/parse.c index 7f6b31d..cb57f92 100644 --- a/parse.c +++ b/parse.c @@ -56,6 +56,8 @@ static void set_irtok_dest_addr(IRTok *t, size_t addr) { case IREq: case IRLt: case IRLe: + case IRAnd: + case IROr: t->Binary.addr = addr; break; case IRCallInternal: @@ -446,6 +448,8 @@ static ExprRet expr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, case OpLe: instr = IRLe; break; case OpGt: instr = IRLt; swap_operands = true; break; case OpGe: instr = IRLe; swap_operands = true; break; + case OpAnd: instr = IRAnd; break; + case OpOr: instr = IROr; break; default: mark_err(l_op); set_err("Unknown operation: '%s'", op_str[l_op->Op]); diff --git a/runtime.c b/runtime.c index 0c18a45..a94b1f4 100644 --- a/runtime.c +++ b/runtime.c @@ -65,6 +65,18 @@ Value eval_binary(IRInstr instr, const Value *lhs, const Value *rhs) { .type.kind = TypeBool, .Bool = res, }; + case IRAnd: + return (Value){ + .type.kind = TypeBool, + .Bool = is_nonzero(lhs) && is_nonzero(rhs), + }; + break; + case IROr: + return (Value){ + .type.kind = TypeBool, + .Bool = is_nonzero(lhs) || is_nonzero(rhs), + }; + break; default: ASSERT_UNREACHED(); } diff --git a/tok.c b/tok.c index 4f51026..33bee36 100644 --- a/tok.c +++ b/tok.c @@ -11,15 +11,17 @@ int8_t op_prec[OperatorEnumSize] = { [OpLCurl] = PREC_DELIM, [OpRParen] = PREC_DELIM, [OpComma] = PREC_DELIM, - [OpEq] = 0, - [OpLt] = 0, - [OpGt] = 0, - [OpLe] = 0, - [OpGe] = 0, - [OpAdd] = 1, - [OpSub] = 1, - [OpMul] = 2, - [OpDiv] = 2, + [OpAnd] = 0, + [OpOr] = 0, + [OpEq] = 1, + [OpLt] = 1, + [OpGt] = 1, + [OpLe] = 1, + [OpGe] = 1, + [OpAdd] = 2, + [OpSub] = 2, + [OpMul] = 3, + [OpDiv] = 3, }; const char *op_str[OperatorEnumSize] = { @@ -40,6 +42,8 @@ const char *op_str[OperatorEnumSize] = { [OpGt] = ">", [OpLe] = "<=", [OpGe] = ">=", + [OpAnd] = "&&", + [OpOr] = "||", }; const char *tok_str[TokKindEnumSize] = { diff --git a/tok.h b/tok.h index 34fd371..5790756 100644 --- a/tok.h +++ b/tok.h @@ -47,6 +47,8 @@ enum Operator { OpGt, OpLe, OpGe, + OpAnd, + OpOr, OpNewLn, OpEOF, OperatorEnumSize, diff --git a/vm.c b/vm.c index d998585..6e7e218 100644 --- a/vm.c +++ b/vm.c @@ -67,6 +67,8 @@ void run(const IRToks *ir, const BuiltinFunc *builtin_funcs) { case IREq: case IRLt: case IRLe: + case IRAnd: + case IROr: stack_fit(&s, instr->Binary.addr); TRY_ELSE(s.mem[instr->Binary.addr] = eval_binary(instr->instr, irparam_to_val(&s, &instr->Binary.lhs),