From 8309535bbe8ee2bb879a6a44b6f60b297047fd08 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sat, 20 Aug 2022 07:20:29 +0100 Subject: [PATCH] Fixed negation issue, moved some scripts to test/ --- scripts/casting.toy | 30 ------------------ scripts/example.toy | 1 - source/interpreter.c | 45 +++++++++++++++++++++------ source/literal.c | 2 +- source/opcodes.h | 1 + source/parser.c | 35 ++++++++++++++------- test/arithmetic.toy | 15 +++++++++ test/casting.toy | 33 ++++++++++++++++++++ {scripts => test}/comparisons.toy | 1 - {scripts => test}/long-array.toy | 0 {scripts => test}/long-dictionary.toy | 0 {scripts => test}/long-literals.toy | 0 12 files changed, 109 insertions(+), 54 deletions(-) delete mode 100644 scripts/casting.toy create mode 100644 test/arithmetic.toy create mode 100644 test/casting.toy rename {scripts => test}/comparisons.toy (99%) rename {scripts => test}/long-array.toy (100%) rename {scripts => test}/long-dictionary.toy (100%) rename {scripts => test}/long-literals.toy (100%) diff --git a/scripts/casting.toy b/scripts/casting.toy deleted file mode 100644 index bc68744..0000000 --- a/scripts/casting.toy +++ /dev/null @@ -1,30 +0,0 @@ -//boolean origin -var b: bool = true; - -print (int)b; -print (float)b; -print (string)b; - - -//integer origin -var i: int = 42; - -print (bool)i; -print (float)i; -print (string)i; - - -//float origin -var f: float = 3.14; - -print (bool)f; -print (int)f; -print (string)f; - - -//string origin -var s: string = "78.9"; - -print (bool)s; -print (int)s; -print (float)s; diff --git a/scripts/example.toy b/scripts/example.toy index 2404148..53af2cb 100644 --- a/scripts/example.toy +++ b/scripts/example.toy @@ -87,4 +87,3 @@ assert false, "This is a failed assert, and will end execution"; print "This will not be printed because of the above assert"; -//TODO: use a proper assert-based version of this file diff --git a/source/interpreter.c b/source/interpreter.c index a6f3553..efe194e 100644 --- a/source/interpreter.c +++ b/source/interpreter.c @@ -8,13 +8,13 @@ #include static void stdoutWrapper(const char* output) { - fprintf(stdout, output); + fprintf(stdout, "%s", output); fprintf(stdout, "\n"); //default new line } static void stderrWrapper(const char* output) { fprintf(stderr, "Assertion failure: "); - fprintf(stderr, output); + fprintf(stderr, "%s", output); fprintf(stderr, "\n"); //default new line } @@ -177,7 +177,32 @@ static bool execPushLiteral(Interpreter* interpreter, bool lng) { } static bool execNegate(Interpreter* interpreter) { - //negate the top literal on the stack + //negate the top literal on the stack (numbers only) + Literal lit = popLiteralArray(&interpreter->stack); + + if (!parseIdentifierToValue(interpreter, &lit)) { + return false; + } + + else if (IS_INTEGER(lit)) { + lit = TO_INTEGER_LITERAL(-AS_INTEGER(lit)); + } + else if (IS_FLOAT(lit)) { + lit = TO_FLOAT_LITERAL(-AS_FLOAT(lit)); + } + else { + printf("[internal] The interpreter can't negate that literal: "); + printLiteral(lit); + printf("\n"); + return false; + } + + pushLiteralArray(&interpreter->stack, lit); + return true; +} + +static bool execInvert(Interpreter* interpreter) { + //negate the top literal on the stack (booleans only) Literal lit = popLiteralArray(&interpreter->stack); if (!parseIdentifierToValue(interpreter, &lit)) { @@ -187,14 +212,8 @@ static bool execNegate(Interpreter* interpreter) { if (IS_BOOLEAN(lit)) { lit = TO_BOOLEAN_LITERAL(!AS_BOOLEAN(lit)); } - else if (IS_INTEGER(lit)) { - lit = TO_INTEGER_LITERAL(-AS_INTEGER(lit)); - } - else if (IS_FLOAT(lit)) { - lit = TO_FLOAT_LITERAL(-AS_FLOAT(lit)); - } else { - printf("[internal] The interpreter can't negate that literal: "); + printf("[internal] The interpreter can't invert that literal: "); printLiteral(lit); printf("\n"); return false; @@ -665,6 +684,12 @@ static void execInterpreter(Interpreter* interpreter) { } break; + case OP_INVERT: + if (!execInvert(interpreter)) { + return; + } + break; + default: printf("Unknown opcode found %d, terminating\n", opcode); printLiteralArray(&interpreter->stack, "\n"); diff --git a/source/literal.c b/source/literal.c index 1472c85..854ba68 100644 --- a/source/literal.c +++ b/source/literal.c @@ -9,7 +9,7 @@ //utils static void stdoutWrapper(const char* output) { - fprintf(stdout, output); + fprintf(stdout, "%s", output); } //buffer the prints diff --git a/source/opcodes.h b/source/opcodes.h index 967ba31..b74f6ea 100644 --- a/source/opcodes.h +++ b/source/opcodes.h @@ -42,6 +42,7 @@ typedef enum Opcode { OP_COMPARE_LESS_EQUAL, OP_COMPARE_GREATER, OP_COMPARE_GREATER_EQUAL, + OP_INVERT, //for booleans //meta OP_SECTION_END, diff --git a/source/parser.c b/source/parser.c index c5fee77..8a2d577 100644 --- a/source/parser.c +++ b/source/parser.c @@ -361,7 +361,7 @@ static Opcode unary(Parser* parser, Node** nodeHandle) { parsePrecedence(parser, &tmpNode, PREC_TERNARY); //can be a literal //check for negative literals (optimisation) - if (tmpNode->type == NODE_LITERAL) { + if (tmpNode->type == NODE_LITERAL && (IS_INTEGER(tmpNode->atomic.literal) || IS_FLOAT(tmpNode->atomic.literal))) { //negate directly, if int or float Literal lit = tmpNode->atomic.literal; @@ -378,26 +378,44 @@ static Opcode unary(Parser* parser, Node** nodeHandle) { return OP_EOF; } + + //check for negated boolean errors + if (tmpNode->type == NODE_LITERAL && IS_BOOLEAN(tmpNode->atomic.literal)) { + error(parser, parser->previous, "Negative booleans are not allowed"); + return OP_EOF; + } + + //actually emit the negation + emitNodeUnary(nodeHandle, OP_NEGATE); + (*nodeHandle)->unary.child = tmpNode; //set negate's child to the literal } else if (parser->previous.type == TOKEN_NOT) { //temp handle to potentially negate values parsePrecedence(parser, &tmpNode, PREC_TERNARY); //can be a literal - //check for negative literals (optimisation) - if (tmpNode->type == NODE_LITERAL && !IS_IDENTIFIER(tmpNode->atomic.literal)) { + //check for inverted booleans + if (tmpNode->type == NODE_LITERAL && IS_BOOLEAN(tmpNode->atomic.literal)) { //negate directly, if int or float Literal lit = tmpNode->atomic.literal; - if (IS_BOOLEAN(lit)) { - lit = TO_BOOLEAN_LITERAL(!AS_BOOLEAN(lit)); - } + lit = TO_BOOLEAN_LITERAL(!AS_BOOLEAN(lit)); tmpNode->atomic.literal = lit; *nodeHandle = tmpNode; return OP_EOF; } + + //check for inverted number errors + if (tmpNode->type == NODE_LITERAL && (IS_INTEGER(tmpNode->atomic.literal) || IS_FLOAT(tmpNode->atomic.literal))) { + error(parser, parser->previous, "Inverted numbers are not allowed"); + return OP_EOF; + } + + //actually emit the negation + emitNodeUnary(nodeHandle, OP_INVERT); + (*nodeHandle)->unary.child = tmpNode; //set negate's child to the literal } else { @@ -405,11 +423,6 @@ static Opcode unary(Parser* parser, Node** nodeHandle) { return OP_EOF; } - - //actually emit the negation - emitNodeUnary(nodeHandle, OP_NEGATE); - (*nodeHandle)->unary.child = tmpNode; //set negate's child to the literal - return OP_EOF; } diff --git a/test/arithmetic.toy b/test/arithmetic.toy new file mode 100644 index 0000000..53f13b8 --- /dev/null +++ b/test/arithmetic.toy @@ -0,0 +1,15 @@ +//test operators (integers) +assert 1 + 1 == 2, "1 + 1 == 2"; +assert 1 - 1 == 0, "1 - 1 == 0"; +assert 2 * 2 == 4, "2 * 2 == 4"; +assert 1 / 2 == 0, "1 / 2 == 0"; //integer division +assert 5 % 2 == 1, "5 % 2 == 1"; + +//test operators (floats) +assert 1.0 + 1.0 == 2.0, "1.0 + 1.0 == 2.0"; +assert 1.0 - 1.0 == 0.0, "1.0 - 1.0 == 0.0"; +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"; + + +print "All good"; \ No newline at end of file diff --git a/test/casting.toy b/test/casting.toy new file mode 100644 index 0000000..fff5e4d --- /dev/null +++ b/test/casting.toy @@ -0,0 +1,33 @@ +//boolean origin +var b: bool = true; + +assert (int)b == 1, "bool -> int"; +assert (float)b == 1, "bool -> float"; +assert (string)b == "true", "bool -> string"; + + +//integer origin +var i: int = 42; + +assert (bool)i == true, "int -> bool"; +assert (float)i == 42, "int -> float"; +assert (string)i == "42", "int -> string"; + + +//float origin +var f: float = 3.14; + +assert (bool)f == true, "float -> bool"; +assert (int)f == 3, "float -> int"; +assert (string)f == "3.14", "float -> string"; + + +//string origin +var s: string = "78.9"; + +assert (bool)s == true, "string -> bool"; +assert (int)s == 78, "string -> int"; +assert (float)s == 78.9, "string -> float"; + + +print "All good"; diff --git a/scripts/comparisons.toy b/test/comparisons.toy similarity index 99% rename from scripts/comparisons.toy rename to test/comparisons.toy index be9f2c7..f46d8cd 100644 --- a/scripts/comparisons.toy +++ b/test/comparisons.toy @@ -1,4 +1,3 @@ - //test numbers assert 1 < 2, "1 < 2"; assert 1 == 1, "1 == 1"; diff --git a/scripts/long-array.toy b/test/long-array.toy similarity index 100% rename from scripts/long-array.toy rename to test/long-array.toy diff --git a/scripts/long-dictionary.toy b/test/long-dictionary.toy similarity index 100% rename from scripts/long-dictionary.toy rename to test/long-dictionary.toy diff --git a/scripts/long-literals.toy b/test/long-literals.toy similarity index 100% rename from scripts/long-literals.toy rename to test/long-literals.toy