Added arithmetic assign operators

This commit is contained in:
2022-08-23 03:33:28 +01:00
parent ce2073832b
commit 6939b216a9
4 changed files with 88 additions and 6 deletions

View File

@@ -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;

View File

@@ -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

View File

@@ -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,

View File

@@ -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";