added and,or operators

This commit is contained in:
Francesco Cozzuto
2022-03-07 19:50:18 +01:00
parent 3c2c68dfe5
commit de7479c7db
7 changed files with 80 additions and 4 deletions
+2
View File
@@ -55,6 +55,8 @@ static const InstrInfo instr_table[] = {
[OPCODE_GRT] = {"GRT", 0, NULL}, [OPCODE_GRT] = {"GRT", 0, NULL},
[OPCODE_LEQ] = {"LEQ", 0, NULL}, [OPCODE_LEQ] = {"LEQ", 0, NULL},
[OPCODE_GEQ] = {"GEQ", 0, NULL}, [OPCODE_GEQ] = {"GEQ", 0, NULL},
[OPCODE_AND] = {"AND", 0, NULL},
[OPCODE_OR] = {"AND", 0, NULL},
[OPCODE_ASS] = {"ASS", 1, (OperandType[]) {OPTP_STRING}}, [OPCODE_ASS] = {"ASS", 1, (OperandType[]) {OPTP_STRING}},
[OPCODE_POP] = {"POP", 1, (OperandType[]) {OPTP_INT}}, [OPCODE_POP] = {"POP", 1, (OperandType[]) {OPTP_INT}},
+2
View File
@@ -35,6 +35,8 @@ typedef enum {
OPCODE_GRT, OPCODE_GRT,
OPCODE_LEQ, OPCODE_LEQ,
OPCODE_GEQ, OPCODE_GEQ,
OPCODE_AND,
OPCODE_OR,
OPCODE_ASS, OPCODE_ASS,
OPCODE_POP, OPCODE_POP,
OPCODE_CALL, OPCODE_CALL,
+2
View File
@@ -30,6 +30,8 @@ typedef enum {
EXPR_GRT, EXPR_GRT,
EXPR_GEQ, EXPR_GEQ,
EXPR_AND,
EXPR_OR,
EXPR_NOT, EXPR_NOT,
EXPR_ASS, EXPR_ASS,
+4
View File
@@ -40,6 +40,8 @@ static Opcode exprkind_to_opcode(ExprKind kind)
case EXPR_LEQ: return OPCODE_LEQ; case EXPR_LEQ: return OPCODE_LEQ;
case EXPR_GRT: return OPCODE_GRT; case EXPR_GRT: return OPCODE_GRT;
case EXPR_GEQ: return OPCODE_GEQ; case EXPR_GEQ: return OPCODE_GEQ;
case EXPR_AND: return OPCODE_AND;
case EXPR_OR: return OPCODE_OR;
default: default:
UNREACHABLE; UNREACHABLE;
break; break;
@@ -70,6 +72,8 @@ static _Bool emit_instr_for_node(ExeBuilder *exeb, Node *node, Error *error)
case EXPR_LEQ: case EXPR_LEQ:
case EXPR_GRT: case EXPR_GRT:
case EXPR_GEQ: case EXPR_GEQ:
case EXPR_AND:
case EXPR_OR:
{ {
OperExprNode *oper = (OperExprNode*) expr; OperExprNode *oper = (OperExprNode*) expr;
+23 -3
View File
@@ -59,6 +59,8 @@ typedef enum {
TKWIF, TKWIF,
TKWFUN, TKWFUN,
TKWNOT, TKWNOT,
TKWAND,
TKWOR,
TKWELSE, TKWELSE,
TKWNONE, TKWNONE,
TKWTRUE, TKWTRUE,
@@ -197,6 +199,14 @@ static Token *tokenize(Source *src, BPAlloc *alloc, Error *error)
{ {
tok->kind = TKWNOT; tok->kind = TKWNOT;
} }
else if(matchstr(str + tok->offset, tok->length, "and"))
{
tok->kind = TKWAND;
}
else if(matchstr(str + tok->offset, tok->length, "or"))
{
tok->kind = TKWOR;
}
else if(matchstr(str + tok->offset, tok->length, "else")) else if(matchstr(str + tok->offset, tok->length, "else"))
{ {
tok->kind = TKWELSE; tok->kind = TKWELSE;
@@ -1519,6 +1529,8 @@ static inline _Bool isbinop(Token *tok)
tok->kind == TGEQ || tok->kind == TGEQ ||
tok->kind == TEQL || tok->kind == TEQL ||
tok->kind == TNQL || tok->kind == TNQL ||
tok->kind == TKWAND ||
tok->kind == TKWOR ||
tok->kind == '='; tok->kind == '=';
} }
@@ -1538,21 +1550,27 @@ static inline int precedenceof(Token *tok)
case '=': case '=':
return 0; return 0;
case TKWOR:
return 1;
case TKWAND:
return 2;
case '<': case '<':
case '>': case '>':
case TLEQ: case TLEQ:
case TGEQ: case TGEQ:
case TEQL: case TEQL:
case TNQL: case TNQL:
return 1; return 3;
case '+': case '+':
case '-': case '-':
return 2; return 4;
case '*': case '*':
case '/': case '/':
return 3; return 5;
default: default:
return -100000000; return -100000000;
@@ -1610,6 +1628,8 @@ static Node *parse_expression_2(Context *ctx, Node *left_expr, int min_prec)
case TGEQ: temp->base.kind = EXPR_GEQ; break; case TGEQ: temp->base.kind = EXPR_GEQ; break;
case TEQL: temp->base.kind = EXPR_EQL; break; case TEQL: temp->base.kind = EXPR_EQL; break;
case TNQL: temp->base.kind = EXPR_NQL; break; case TNQL: temp->base.kind = EXPR_NQL; break;
case TKWAND: temp->base.kind = EXPR_AND; break;
case TKWOR: temp->base.kind = EXPR_OR; break;
case '=': temp->base.kind = EXPR_ASS; break; case '=': temp->base.kind = EXPR_ASS; break;
default: default:
+38
View File
@@ -679,6 +679,44 @@ static _Bool step(Runtime *runtime, Error *error)
return 1; return 1;
} }
case OPCODE_AND:
case OPCODE_OR:
{
assert(opc == 0);
Object *rop = Stack_Top(runtime->stack, 0);
Object *lop = Stack_Top(runtime->stack, -1);
if(!Runtime_Pop(runtime, error, 2))
return 0;
// We managed to pop rop and lop,
// so we know they're not NULL.
assert(rop != NULL);
assert(lop != NULL);
_Bool raw_rop, raw_lop, raw_res;
raw_lop = Object_ToBool(lop, error);
raw_rop = Object_ToBool(rop, error);
if(error->occurred) return 0;
switch(opcode)
{
case OPCODE_AND: raw_res = raw_lop && raw_rop; break;
case OPCODE_OR: raw_res = raw_lop || raw_rop; break;
default: assert(0); break;
}
Object *res = Object_FromBool(raw_res, runtime->heap, error);
if(res == NULL)
return 0;
if(!Runtime_Push(runtime, error, res))
return 0;
return 1;
}
case OPCODE_ASS: case OPCODE_ASS:
{ {
assert(opc == 1); assert(opc == 1);
+8
View File
@@ -59,6 +59,14 @@
assert(false != true); assert(false != true);
assert(true == not false); assert(true == not false);
assert(false == not true); assert(false == not true);
assert((true and true ) == true);
assert((true and false) == false);
assert((false and true ) == false);
assert((false and false) == false);
assert((true or true ) == true);
assert((true or false) == true);
assert((false or true ) == true);
assert((false or false) == false);
} }
# Test if-else statements. # Test if-else statements.