add logical or and logical and

This commit is contained in:
r4 2021-12-23 21:42:09 +01:00
parent d67008cfbf
commit 6bdc4e3210
8 changed files with 53 additions and 9 deletions

4
ir.c
View File

@ -14,6 +14,8 @@ const char *irinstr_str[IRInstrEnumSize] = {
[IRLt] = "lt", [IRLt] = "lt",
[IRLe] = "le", [IRLe] = "le",
[IRNot] = "not", [IRNot] = "not",
[IRAnd] = "and",
[IROr] = "or",
[IRJmp] = "jmp", [IRJmp] = "jmp",
[IRJnz] = "jnz", [IRJnz] = "jnz",
[IRCallInternal] = "calli", [IRCallInternal] = "calli",
@ -119,6 +121,8 @@ void print_ir(IRToks *v, const BuiltinFunc *builtin_funcs) {
case IREq: case IREq:
case IRLt: case IRLt:
case IRLe: case IRLe:
case IRAnd:
case IROr:
printf(" %%%zx ", v->toks[i].Binary.addr); printf(" %%%zx ", v->toks[i].Binary.addr);
print_irparam(&v->toks[i].Binary.lhs); print_irparam(&v->toks[i].Binary.lhs);
printf(" "); printf(" ");

2
ir.h
View File

@ -22,6 +22,8 @@ enum IRInstr {
IRLt, IRLt,
IRLe, IRLe,
IRNot, IRNot,
IRAnd,
IROr,
IRJmp, IRJmp,
IRJnz, IRJnz,
IRCallInternal, IRCallInternal,

14
lex.c
View File

@ -218,6 +218,20 @@ TokList lex(const char *s) {
continue; continue;
} }
break; 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 '}': case '}':
case '(': case '(':

View File

@ -56,6 +56,8 @@ static void set_irtok_dest_addr(IRTok *t, size_t addr) {
case IREq: case IREq:
case IRLt: case IRLt:
case IRLe: case IRLe:
case IRAnd:
case IROr:
t->Binary.addr = addr; t->Binary.addr = addr;
break; break;
case IRCallInternal: 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 OpLe: instr = IRLe; break;
case OpGt: instr = IRLt; swap_operands = true; break; case OpGt: instr = IRLt; swap_operands = true; break;
case OpGe: instr = IRLe; swap_operands = true; break; case OpGe: instr = IRLe; swap_operands = true; break;
case OpAnd: instr = IRAnd; break;
case OpOr: instr = IROr; break;
default: default:
mark_err(l_op); mark_err(l_op);
set_err("Unknown operation: '%s'", op_str[l_op->Op]); set_err("Unknown operation: '%s'", op_str[l_op->Op]);

View File

@ -65,6 +65,18 @@ Value eval_binary(IRInstr instr, const Value *lhs, const Value *rhs) {
.type.kind = TypeBool, .type.kind = TypeBool,
.Bool = res, .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: default:
ASSERT_UNREACHED(); ASSERT_UNREACHED();
} }

22
tok.c
View File

@ -11,15 +11,17 @@ int8_t op_prec[OperatorEnumSize] = {
[OpLCurl] = PREC_DELIM, [OpLCurl] = PREC_DELIM,
[OpRParen] = PREC_DELIM, [OpRParen] = PREC_DELIM,
[OpComma] = PREC_DELIM, [OpComma] = PREC_DELIM,
[OpEq] = 0, [OpAnd] = 0,
[OpLt] = 0, [OpOr] = 0,
[OpGt] = 0, [OpEq] = 1,
[OpLe] = 0, [OpLt] = 1,
[OpGe] = 0, [OpGt] = 1,
[OpAdd] = 1, [OpLe] = 1,
[OpSub] = 1, [OpGe] = 1,
[OpMul] = 2, [OpAdd] = 2,
[OpDiv] = 2, [OpSub] = 2,
[OpMul] = 3,
[OpDiv] = 3,
}; };
const char *op_str[OperatorEnumSize] = { const char *op_str[OperatorEnumSize] = {
@ -40,6 +42,8 @@ const char *op_str[OperatorEnumSize] = {
[OpGt] = ">", [OpGt] = ">",
[OpLe] = "<=", [OpLe] = "<=",
[OpGe] = ">=", [OpGe] = ">=",
[OpAnd] = "&&",
[OpOr] = "||",
}; };
const char *tok_str[TokKindEnumSize] = { const char *tok_str[TokKindEnumSize] = {

2
tok.h
View File

@ -47,6 +47,8 @@ enum Operator {
OpGt, OpGt,
OpLe, OpLe,
OpGe, OpGe,
OpAnd,
OpOr,
OpNewLn, OpNewLn,
OpEOF, OpEOF,
OperatorEnumSize, OperatorEnumSize,

2
vm.c
View File

@ -67,6 +67,8 @@ void run(const IRToks *ir, const BuiltinFunc *builtin_funcs) {
case IREq: case IREq:
case IRLt: case IRLt:
case IRLe: case IRLe:
case IRAnd:
case IROr:
stack_fit(&s, instr->Binary.addr); stack_fit(&s, instr->Binary.addr);
TRY_ELSE(s.mem[instr->Binary.addr] = eval_binary(instr->instr, TRY_ELSE(s.mem[instr->Binary.addr] = eval_binary(instr->instr,
irparam_to_val(&s, &instr->Binary.lhs), irparam_to_val(&s, &instr->Binary.lhs),