From 4f70bea8089af5c2167f70f1f6db3107e0572a83 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Tue, 23 Aug 2022 05:07:17 +0100 Subject: [PATCH] Implemented logical && and || --- docs/TODO.txt | 4 ++-- source/interpreter.c | 46 ++++++++++++++++++++++++++++++++++++++++++++ source/opcodes.h | 4 ++++ source/parser.c | 15 ++++++++++++--- test/logicals.toy | 6 ++++++ 5 files changed, 70 insertions(+), 5 deletions(-) create mode 100644 test/logicals.toy diff --git a/docs/TODO.txt b/docs/TODO.txt index 21b7831..1a28086 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -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? diff --git a/source/interpreter.c b/source/interpreter.c index d2ebb11..594a44a 100644 --- a/source/interpreter.c +++ b/source/interpreter.c @@ -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; diff --git a/source/opcodes.h b/source/opcodes.h index 766d626..ee8e71c 100644 --- a/source/opcodes.h +++ b/source/opcodes.h @@ -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, diff --git a/source/parser.c b/source/parser.c index 56eb986..fffde09 100644 --- a/source/parser.c +++ b/source/parser.c @@ -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, diff --git a/test/logicals.toy b/test/logicals.toy new file mode 100644 index 0000000..cd22ac0 --- /dev/null +++ b/test/logicals.toy @@ -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";