added and,or operators
This commit is contained in:
@@ -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}},
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
@@ -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:
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user