added and,or operators
This commit is contained in:
@@ -55,6 +55,8 @@ static const InstrInfo instr_table[] = {
|
||||
[OPCODE_GRT] = {"GRT", 0, NULL},
|
||||
[OPCODE_LEQ] = {"LEQ", 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_POP] = {"POP", 1, (OperandType[]) {OPTP_INT}},
|
||||
|
||||
@@ -35,6 +35,8 @@ typedef enum {
|
||||
OPCODE_GRT,
|
||||
OPCODE_LEQ,
|
||||
OPCODE_GEQ,
|
||||
OPCODE_AND,
|
||||
OPCODE_OR,
|
||||
OPCODE_ASS,
|
||||
OPCODE_POP,
|
||||
OPCODE_CALL,
|
||||
|
||||
@@ -30,6 +30,8 @@ typedef enum {
|
||||
EXPR_GRT,
|
||||
EXPR_GEQ,
|
||||
|
||||
EXPR_AND,
|
||||
EXPR_OR,
|
||||
EXPR_NOT,
|
||||
|
||||
EXPR_ASS,
|
||||
|
||||
@@ -40,6 +40,8 @@ static Opcode exprkind_to_opcode(ExprKind kind)
|
||||
case EXPR_LEQ: return OPCODE_LEQ;
|
||||
case EXPR_GRT: return OPCODE_GRT;
|
||||
case EXPR_GEQ: return OPCODE_GEQ;
|
||||
case EXPR_AND: return OPCODE_AND;
|
||||
case EXPR_OR: return OPCODE_OR;
|
||||
default:
|
||||
UNREACHABLE;
|
||||
break;
|
||||
@@ -70,6 +72,8 @@ static _Bool emit_instr_for_node(ExeBuilder *exeb, Node *node, Error *error)
|
||||
case EXPR_LEQ:
|
||||
case EXPR_GRT:
|
||||
case EXPR_GEQ:
|
||||
case EXPR_AND:
|
||||
case EXPR_OR:
|
||||
{
|
||||
OperExprNode *oper = (OperExprNode*) expr;
|
||||
|
||||
|
||||
+23
-3
@@ -59,6 +59,8 @@ typedef enum {
|
||||
TKWIF,
|
||||
TKWFUN,
|
||||
TKWNOT,
|
||||
TKWAND,
|
||||
TKWOR,
|
||||
TKWELSE,
|
||||
TKWNONE,
|
||||
TKWTRUE,
|
||||
@@ -197,6 +199,14 @@ static Token *tokenize(Source *src, BPAlloc *alloc, Error *error)
|
||||
{
|
||||
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"))
|
||||
{
|
||||
tok->kind = TKWELSE;
|
||||
@@ -1519,6 +1529,8 @@ static inline _Bool isbinop(Token *tok)
|
||||
tok->kind == TGEQ ||
|
||||
tok->kind == TEQL ||
|
||||
tok->kind == TNQL ||
|
||||
tok->kind == TKWAND ||
|
||||
tok->kind == TKWOR ||
|
||||
tok->kind == '=';
|
||||
}
|
||||
|
||||
@@ -1538,21 +1550,27 @@ static inline int precedenceof(Token *tok)
|
||||
case '=':
|
||||
return 0;
|
||||
|
||||
case TKWOR:
|
||||
return 1;
|
||||
|
||||
case TKWAND:
|
||||
return 2;
|
||||
|
||||
case '<':
|
||||
case '>':
|
||||
case TLEQ:
|
||||
case TGEQ:
|
||||
case TEQL:
|
||||
case TNQL:
|
||||
return 1;
|
||||
return 3;
|
||||
|
||||
case '+':
|
||||
case '-':
|
||||
return 2;
|
||||
return 4;
|
||||
|
||||
case '*':
|
||||
case '/':
|
||||
return 3;
|
||||
return 5;
|
||||
|
||||
default:
|
||||
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 TEQL: temp->base.kind = EXPR_EQL; 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;
|
||||
|
||||
default:
|
||||
|
||||
@@ -679,6 +679,44 @@ static _Bool step(Runtime *runtime, Error *error)
|
||||
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:
|
||||
{
|
||||
assert(opc == 1);
|
||||
|
||||
@@ -59,6 +59,14 @@
|
||||
assert(false != true);
|
||||
assert(true == not false);
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user