From 6939b216a997575fe362cc9fa8b1fcdb6dbc3738 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Tue, 23 Aug 2022 03:33:28 +0100 Subject: [PATCH] Added arithmetic assign operators --- source/interpreter.c | 38 +++++++++++++++++++++++++++++++++++++- source/opcodes.h | 5 +++++ source/parser.c | 35 ++++++++++++++++++++++++++++++----- test/arithmetic.toy | 16 ++++++++++++++++ 4 files changed, 88 insertions(+), 6 deletions(-) diff --git a/source/interpreter.c b/source/interpreter.c index 4ab577a..d2ebb11 100644 --- a/source/interpreter.c +++ b/source/interpreter.c @@ -269,18 +269,22 @@ static bool execArithmetic(Interpreter* interpreter, Opcode opcode) { if(IS_INTEGER(lhs) && IS_INTEGER(rhs)) { switch(opcode) { case OP_ADDITION: + case OP_VAR_ADDITION_ASSIGN: pushLiteralArray(&interpreter->stack, TO_INTEGER_LITERAL( AS_INTEGER(lhs) + AS_INTEGER(rhs) )); return true; case OP_SUBTRACTION: + case OP_VAR_SUBTRACTION_ASSIGN: pushLiteralArray(&interpreter->stack, TO_INTEGER_LITERAL( AS_INTEGER(lhs) - AS_INTEGER(rhs) )); return true; case OP_MULTIPLICATION: + case OP_VAR_MULTIPLICATION_ASSIGN: pushLiteralArray(&interpreter->stack, TO_INTEGER_LITERAL( AS_INTEGER(lhs) * AS_INTEGER(rhs) )); return true; case OP_DIVISION: + case OP_VAR_DIVISION_ASSIGN: if (AS_INTEGER(rhs) == 0) { printf(ERROR "ERROR: Can't divide by zero (error found in interpreter)" RESET); return false; @@ -289,6 +293,7 @@ static bool execArithmetic(Interpreter* interpreter, Opcode opcode) { return true; case OP_MODULO: + case OP_VAR_MODULO_ASSIGN: if (AS_INTEGER(rhs) == 0) { printf(ERROR "ERROR: Can't modulo by zero (error found in interpreter)" RESET); return false; @@ -303,7 +308,7 @@ static bool execArithmetic(Interpreter* interpreter, Opcode opcode) { } //catch bad modulo - if (opcode == OP_MODULO) { + if (opcode == OP_MODULO || opcode == OP_VAR_MODULO_ASSIGN) { printf(ERROR "ERROR: Bad arithmetic argument (modulo on floats not allowed)\n" RESET); return false; } @@ -311,18 +316,22 @@ static bool execArithmetic(Interpreter* interpreter, Opcode opcode) { if(IS_FLOAT(lhs) && IS_FLOAT(rhs)) { switch(opcode) { case OP_ADDITION: + case OP_VAR_ADDITION_ASSIGN: pushLiteralArray(&interpreter->stack, TO_FLOAT_LITERAL( AS_FLOAT(lhs) + AS_FLOAT(rhs) )); return true; case OP_SUBTRACTION: + case OP_VAR_SUBTRACTION_ASSIGN: pushLiteralArray(&interpreter->stack, TO_FLOAT_LITERAL( AS_FLOAT(lhs) - AS_FLOAT(rhs) )); return true; case OP_MULTIPLICATION: + case OP_VAR_MULTIPLICATION_ASSIGN: pushLiteralArray(&interpreter->stack, TO_FLOAT_LITERAL( AS_FLOAT(lhs) * AS_FLOAT(rhs) )); return true; case OP_DIVISION: + case OP_VAR_DIVISION_ASSIGN: if (AS_FLOAT(rhs) == 0) { printf(ERROR "ERROR: Can't divide by zero (error found in interpreter)" RESET); return false; @@ -414,6 +423,18 @@ static bool execVarAssign(Interpreter* interpreter) { return true; } +static bool execVarArithmeticAssign(Interpreter* interpreter) { + Literal rhs = popLiteralArray(&interpreter->stack); + Literal lhs = popLiteralArray(&interpreter->stack); + + //duplicate the name + pushLiteralArray(&interpreter->stack, lhs); + pushLiteralArray(&interpreter->stack, lhs); + pushLiteralArray(&interpreter->stack, rhs); + + return true; +} + static bool execValCast(Interpreter* interpreter) { Literal value = popLiteralArray(&interpreter->stack); Literal type = popLiteralArray(&interpreter->stack); @@ -691,6 +712,21 @@ static void execInterpreter(Interpreter* interpreter) { } break; + case OP_VAR_ADDITION_ASSIGN: + case OP_VAR_SUBTRACTION_ASSIGN: + case OP_VAR_MULTIPLICATION_ASSIGN: + case OP_VAR_DIVISION_ASSIGN: + case OP_VAR_MODULO_ASSIGN: + execVarArithmeticAssign(interpreter); + if (!execArithmetic(interpreter, opcode)) { + popLiteralArray(&interpreter->stack); + return; + } + if (!execVarAssign(interpreter)) { + return; + } + break; + case OP_GROUPING_BEGIN: execInterpreter(interpreter); break; diff --git a/source/opcodes.h b/source/opcodes.h index 582b201..766d626 100644 --- a/source/opcodes.h +++ b/source/opcodes.h @@ -33,6 +33,11 @@ typedef enum Opcode { OP_VAR_DECL_LONG, //declare a variable to be used (as a long literal) OP_VAR_ASSIGN, //assign to a literal + OP_VAR_ADDITION_ASSIGN, + OP_VAR_SUBTRACTION_ASSIGN, + OP_VAR_MULTIPLICATION_ASSIGN, + OP_VAR_DIVISION_ASSIGN, + OP_VAR_MODULO_ASSIGN, OP_TYPE_CAST, //temporarily change a type of an atomic value diff --git a/source/parser.c b/source/parser.c index 9d51785..56eb986 100644 --- a/source/parser.c +++ b/source/parser.c @@ -326,6 +326,31 @@ static Opcode binary(Parser* parser, Node** nodeHandle) { return OP_VAR_ASSIGN; } + case TOKEN_PLUS_ASSIGN: { + parsePrecedence(parser, nodeHandle, PREC_ASSIGNMENT); + return OP_VAR_ADDITION_ASSIGN; + } + + case TOKEN_MINUS_ASSIGN: { + parsePrecedence(parser, nodeHandle, PREC_ASSIGNMENT); + return OP_VAR_SUBTRACTION_ASSIGN; + } + + case TOKEN_MULTIPLY_ASSIGN: { + parsePrecedence(parser, nodeHandle, PREC_ASSIGNMENT); + return OP_VAR_MULTIPLICATION_ASSIGN; + } + + case TOKEN_DIVIDE_ASSIGN: { + parsePrecedence(parser, nodeHandle, PREC_ASSIGNMENT); + return OP_VAR_DIVISION_ASSIGN; + } + + case TOKEN_MODULO_ASSIGN: { + parsePrecedence(parser, nodeHandle, PREC_ASSIGNMENT); + return OP_VAR_MODULO_ASSIGN; + } + //comparison case TOKEN_EQUAL: { parsePrecedence(parser, nodeHandle, PREC_COMPARISON); @@ -641,11 +666,11 @@ ParseRule parseRules[] = { //must match the token types {NULL, binary, PREC_FACTOR},// TOKEN_MULTIPLY, {NULL, binary, PREC_FACTOR},// TOKEN_DIVIDE, {NULL, binary, PREC_FACTOR},// TOKEN_MODULO, - {NULL, NULL, PREC_NONE},// TOKEN_PLUS_ASSIGN, - {NULL, NULL, PREC_NONE},// TOKEN_MINUS_ASSIGN, - {NULL, NULL, PREC_NONE},// TOKEN_MULTIPLY_ASSIGN, - {NULL, NULL, PREC_NONE},// TOKEN_DIVIDE_ASSIGN, - {NULL, NULL, PREC_NONE},// TOKEN_MODULO_ASSIGN, + {NULL, binary, PREC_ASSIGNMENT},// TOKEN_PLUS_ASSIGN, + {NULL, binary, PREC_ASSIGNMENT},// TOKEN_MINUS_ASSIGN, + {NULL, binary, PREC_ASSIGNMENT},// TOKEN_MULTIPLY_ASSIGN, + {NULL, binary, PREC_ASSIGNMENT},// TOKEN_DIVIDE_ASSIGN, + {NULL, binary, PREC_ASSIGNMENT},// TOKEN_MODULO_ASSIGN, {incrementPrefix, incrementInfix, PREC_CALL},// TOKEN_PLUS_PLUS, {decrementPrefix, decrementInfix, PREC_CALL},// TOKEN_MINUS_MINUS, {NULL, binary, PREC_ASSIGNMENT},// TOKEN_ASSIGN, diff --git a/test/arithmetic.toy b/test/arithmetic.toy index 53f13b8..a2ed656 100644 --- a/test/arithmetic.toy +++ b/test/arithmetic.toy @@ -12,4 +12,20 @@ assert 2.0 * 2.0 == 4.0, "2.0 * 2.0 == 4.0"; assert 1.0 / 2.0 == 0.5, "1.0 / 2.0 == 0.5"; +var a = 10; + +a += 20; +a -= 25; + +assert a == 5, "+= or -= failed"; + +a *= 5; +a /= 2; + +assert a == 12, "*= or /= failed"; + +a %= 8; + +assert a == 4, "%= failed"; + print "All good"; \ No newline at end of file