Implemented logical && and ||

This commit is contained in:
2022-08-23 05:07:17 +01:00
parent 6939b216a9
commit 4f70bea808
5 changed files with 70 additions and 5 deletions

View File

@@ -13,6 +13,8 @@ DONE: truthiness rethink
DONE: string concat with the + operator
DONE: increment & decrement operators
DONE: store compound types in variables
DONE: += -= *= /= %= operators
DONE: && and || operators
TODO: functions take a number of parameters
@@ -23,8 +25,6 @@ TODO: functions are invoked by calling thier names
TODO: functions are first-class citizens
TODO: functions last argument can be a rest parameter
TODO: && and || operators
TODO: += -= *= /= %= operators
TODO: A way to check the type of a variable (typeOf keyword)
TODO: a = b = c = 1; ?
TODO: are compounds shallow or deep copies?

View File

@@ -624,6 +624,40 @@ static bool execCompareLessEqual(Interpreter* interpreter, bool invert) {
return true;
}
static bool execAnd(Interpreter* interpreter) {
Literal rhs = popLiteralArray(&interpreter->stack);
Literal lhs = popLiteralArray(&interpreter->stack);
parseIdentifierToValue(interpreter, &rhs);
parseIdentifierToValue(interpreter, &lhs);
if (IS_TRUTHY(lhs) && IS_TRUTHY(rhs)) {
pushLiteralArray(&interpreter->stack, TO_BOOLEAN_LITERAL(true));
}
else {
pushLiteralArray(&interpreter->stack, TO_BOOLEAN_LITERAL(false));
}
return true;
}
static bool execOr(Interpreter* interpreter) {
Literal rhs = popLiteralArray(&interpreter->stack);
Literal lhs = popLiteralArray(&interpreter->stack);
parseIdentifierToValue(interpreter, &rhs);
parseIdentifierToValue(interpreter, &lhs);
if (IS_TRUTHY(lhs) || IS_TRUTHY(rhs)) {
pushLiteralArray(&interpreter->stack, TO_BOOLEAN_LITERAL(true));
}
else {
pushLiteralArray(&interpreter->stack, TO_BOOLEAN_LITERAL(false));
}
return true;
}
static bool execJump(Interpreter* interpreter) {
int target = (int)readShort(interpreter->bytecode, &interpreter->count);
@@ -806,6 +840,18 @@ static void execInterpreter(Interpreter* interpreter) {
}
break;
case OP_AND:
if (!execAnd(interpreter)) {
return;
}
break;
case OP_OR:
if (!execOr(interpreter)) {
return;
}
break;
case OP_JUMP:
if (!execJump(interpreter)) {
return;

View File

@@ -50,6 +50,10 @@ typedef enum Opcode {
OP_COMPARE_GREATER_EQUAL,
OP_INVERT, //for booleans
//logical operators
OP_AND,
OP_OR,
//jumps, and conditional jumps (absolute)
OP_JUMP,
OP_IF_FALSE_JUMP,

View File

@@ -96,7 +96,6 @@ typedef enum {
PREC_TERNARY,
PREC_OR,
PREC_AND,
// PREC_EQUALITY,
PREC_COMPARISON,
PREC_TERM,
PREC_FACTOR,
@@ -382,6 +381,16 @@ static Opcode binary(Parser* parser, Node** nodeHandle) {
return OP_COMPARE_GREATER_EQUAL;
}
case TOKEN_AND: {
parsePrecedence(parser, nodeHandle, PREC_COMPARISON);
return OP_AND;
}
case TOKEN_OR: {
parsePrecedence(parser, nodeHandle, PREC_COMPARISON);
return OP_OR;
}
default:
error(parser, parser->previous, "Unexpected token passed to binary precedence rule");
return OP_EOF;
@@ -689,8 +698,8 @@ ParseRule parseRules[] = { //must match the token types
{NULL, binary, PREC_COMPARISON},// TOKEN_GREATER,
{NULL, binary, PREC_COMPARISON},// TOKEN_LESS_EQUAL,
{NULL, binary, PREC_COMPARISON},// TOKEN_GREATER_EQUAL,
{NULL, NULL, PREC_NONE},// TOKEN_AND,
{NULL, NULL, PREC_NONE},// TOKEN_OR,
{NULL, binary, PREC_AND},// TOKEN_AND,
{NULL, binary, PREC_OR},// TOKEN_OR,
//other operators
{NULL, NULL, PREC_NONE},// TOKEN_COLON,

6
test/logicals.toy Normal file
View File

@@ -0,0 +1,6 @@
assert true && true, "boolean and failed";
assert true || true, "boolean or failed";
assert false || true && true, "boolen precedence failed";
print "All good";