From 8d278077b1808f3c938dd28efee7c5c636220ebd Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sat, 4 Feb 2023 09:50:29 +0000 Subject: [PATCH] Added constant folding for strings, tweaked some error messages --- repl/repl_main.c | 8 +++++--- source/toy_common.h | 2 +- source/toy_compiler.c | 4 ++-- source/toy_interpreter.c | 16 ++++++++-------- source/toy_parser.c | 17 ++++++++++++++++- test/scripts/ternary-expressions.toy | 4 ++-- 6 files changed, 34 insertions(+), 17 deletions(-) diff --git a/repl/repl_main.c b/repl/repl_main.c index a68415a..482eb21 100644 --- a/repl/repl_main.c +++ b/repl/repl_main.c @@ -59,7 +59,9 @@ void repl() { while(node != NULL) { //pack up and restart if (node->type == TOY_AST_NODE_ERROR) { - printf(TOY_CC_ERROR "error node detected\n" TOY_CC_RESET); + if (Toy_commandLine.verbose) { + printf(TOY_CC_ERROR "Error node detected\n" TOY_CC_RESET); + } error = true; Toy_freeASTNode(node); break; @@ -103,7 +105,7 @@ int main(int argc, const char* argv[]) { Toy_freeLiteral(driveLiteral); Toy_freeLiteral(pathLiteral); - //Toy_commandLine specific actions + //command line specific actions if (Toy_commandLine.error) { Toy_usageCommandLine(argc, argv); return 0; @@ -121,7 +123,7 @@ int main(int argc, const char* argv[]) { //version if (Toy_commandLine.verbose) { - printf(TOY_CC_NOTICE "Toy Programming Language Version %d.%d.%d\n" TOY_CC_RESET, TOY_VERSION_MAJOR, TOY_VERSION_MINOR, TOY_VERSION_PATCH); + printf(TOY_CC_NOTICE "Toy Programming Language Version %d.%d.%d, built '%s'\n" TOY_CC_RESET, TOY_VERSION_MAJOR, TOY_VERSION_MINOR, TOY_VERSION_PATCH, TOY_VERSION_BUILD); } //run source file diff --git a/source/toy_common.h b/source/toy_common.h index 58d2dce..c35c87f 100644 --- a/source/toy_common.h +++ b/source/toy_common.h @@ -22,7 +22,7 @@ #endif #ifndef TOY_EXPORT -//for processing the Toy_commandLine line arguments +//for processing the command line arguments typedef struct { bool error; bool help; diff --git a/source/toy_compiler.c b/source/toy_compiler.c index 848ce4f..93bc1c6 100644 --- a/source/toy_compiler.c +++ b/source/toy_compiler.c @@ -279,7 +279,7 @@ static Toy_Opcode Toy_writeCompilerWithJumps(Toy_Compiler* compiler, Toy_ASTNode break; case TOY_AST_NODE_UNARY: { - //pass to the child node, then embed the unary Toy_commandLine (print, negate, etc.) + //pass to the child node, then embed the unary command (print, negate, etc.) Toy_Opcode override = Toy_writeCompilerWithJumps(compiler, node->unary.child, breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode); if (override != TOY_OP_EOF) {//compensate for indexing & dot notation being screwy @@ -292,7 +292,7 @@ static Toy_Opcode Toy_writeCompilerWithJumps(Toy_Compiler* compiler, Toy_ASTNode //all infixes come here case TOY_AST_NODE_BINARY: { - //pass to the child nodes, then embed the binary Toy_commandLine (math, etc.) + //pass to the child nodes, then embed the binary command (math, etc.) Toy_Opcode override = Toy_writeCompilerWithJumps(compiler, node->binary.left, breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode); //special case for when indexing and assigning diff --git a/source/toy_interpreter.c b/source/toy_interpreter.c index cb74446..b52d564 100644 --- a/source/toy_interpreter.c +++ b/source/toy_interpreter.c @@ -397,7 +397,7 @@ static bool execArithmetic(Toy_Interpreter* interpreter, Toy_Opcode opcode) { //check for overflow int totalLength = TOY_AS_STRING(lhs)->length + TOY_AS_STRING(rhs)->length; if (totalLength > TOY_MAX_STRING_LENGTH) { - interpreter->errorOutput("Can't concatenate these strings (result is too long)\n"); + interpreter->errorOutput("Can't concatenate these strings, result is too long (error found in interpreter)\n"); return false; } @@ -445,7 +445,7 @@ static bool execArithmetic(Toy_Interpreter* interpreter, Toy_Opcode opcode) { case TOY_OP_DIVISION: case TOY_OP_VAR_DIVISION_ASSIGN: if (TOY_AS_INTEGER(rhs) == 0) { - interpreter->errorOutput("Can't divide by zero (error found in interpreter)"); + interpreter->errorOutput("Can't divide by zero (error found in interpreter)\n"); return false; } Toy_pushLiteralArray(&interpreter->stack, TOY_TO_INTEGER_LITERAL( TOY_AS_INTEGER(lhs) / TOY_AS_INTEGER(rhs) )); @@ -454,14 +454,14 @@ static bool execArithmetic(Toy_Interpreter* interpreter, Toy_Opcode opcode) { case TOY_OP_MODULO: case TOY_OP_VAR_MODULO_ASSIGN: if (TOY_AS_INTEGER(rhs) == 0) { - interpreter->errorOutput("Can't modulo by zero (error found in interpreter)"); + interpreter->errorOutput("Can't modulo by zero (error found in interpreter)\n"); return false; } Toy_pushLiteralArray(&interpreter->stack, TOY_TO_INTEGER_LITERAL( TOY_AS_INTEGER(lhs) % TOY_AS_INTEGER(rhs) )); return true; default: - interpreter->errorOutput("[internal] bad opcode argument passed to execArithmetic()"); + interpreter->errorOutput("[internal] bad opcode argument passed to execArithmetic()\n"); return false; } } @@ -492,14 +492,14 @@ static bool execArithmetic(Toy_Interpreter* interpreter, Toy_Opcode opcode) { case TOY_OP_DIVISION: case TOY_OP_VAR_DIVISION_ASSIGN: if (TOY_AS_FLOAT(rhs) == 0) { - interpreter->errorOutput("Can't divide by zero (error found in interpreter)"); + interpreter->errorOutput("Can't divide by zero (error found in interpreter)\n"); return false; } Toy_pushLiteralArray(&interpreter->stack, TOY_TO_FLOAT_LITERAL( TOY_AS_FLOAT(lhs) / TOY_AS_FLOAT(rhs) )); return true; default: - interpreter->errorOutput("[internal] bad opcode argument passed to execArithmetic()"); + interpreter->errorOutput("[internal] bad opcode argument passed to execArithmetic()\n"); return false; } } @@ -1558,7 +1558,7 @@ static bool execIndex(Toy_Interpreter* interpreter, bool assignIntermediate) { Toy_pushLiteralArray(&arguments, first); Toy_pushLiteralArray(&arguments, second); Toy_pushLiteralArray(&arguments, third); - Toy_pushLiteralArray(&arguments, TOY_TO_NULL_LITERAL); //it expects an assignment Toy_commandLine + Toy_pushLiteralArray(&arguments, TOY_TO_NULL_LITERAL); //it expects an assignment command Toy_pushLiteralArray(&arguments, TOY_TO_NULL_LITERAL); //it expects an assignment "opcode" //leave the idn and compound on the stack @@ -1688,7 +1688,7 @@ static bool execIndexAssign(Toy_Interpreter* interpreter) { Toy_pushLiteralArray(&arguments, first); Toy_pushLiteralArray(&arguments, second); Toy_pushLiteralArray(&arguments, third); - Toy_pushLiteralArray(&arguments, assign); //it expects an assignment Toy_commandLine + Toy_pushLiteralArray(&arguments, assign); //it expects an assignment command Toy_pushLiteralArray(&arguments, op); //it expects an assignment "opcode" //call the _index function diff --git a/source/toy_parser.c b/source/toy_parser.c index 8c4e79a..974c9ff 100644 --- a/source/toy_parser.c +++ b/source/toy_parser.c @@ -59,7 +59,7 @@ static void consume(Toy_Parser* parser, Toy_TokenType tokenType, const char* msg static void synchronize(Toy_Parser* parser) { #ifndef TOY_EXPORT if (Toy_commandLine.verbose) { - fprintf(stderr, TOY_CC_ERROR "synchronizing\n" TOY_CC_RESET); + fprintf(stderr, TOY_CC_ERROR "Synchronizing input\n" TOY_CC_RESET); } #endif @@ -982,6 +982,21 @@ static bool calcStaticBinaryArithmetic(Toy_Parser* parser, Toy_ASTNode** nodeHan Toy_Literal rhs = (*nodeHandle)->binary.right->atomic.literal; Toy_Literal result = TOY_TO_NULL_LITERAL; + //special case for string concatenation ONLY + if (TOY_IS_STRING(lhs) && TOY_IS_STRING(rhs)) { + //check for overflow + int totalLength = TOY_AS_STRING(lhs)->length + TOY_AS_STRING(rhs)->length; + if (totalLength > TOY_MAX_STRING_LENGTH) { + error(parser, parser->previous, "Can't concatenate these strings, result is too long (error found in constant folding)\n"); + return false; + } + + //concat the strings + char buffer[TOY_MAX_STRING_LENGTH]; + snprintf(buffer, TOY_MAX_STRING_LENGTH, "%s%s", Toy_toCString(TOY_AS_STRING(lhs)), Toy_toCString(TOY_AS_STRING(rhs))); + result = TOY_TO_STRING_LITERAL(Toy_createRefStringLength(buffer, totalLength)); + } + //type coersion if (TOY_IS_FLOAT(lhs) && TOY_IS_INTEGER(rhs)) { rhs = TOY_TO_FLOAT_LITERAL(TOY_AS_INTEGER(rhs)); diff --git a/test/scripts/ternary-expressions.toy b/test/scripts/ternary-expressions.toy index 1e8d72b..61d0acc 100644 --- a/test/scripts/ternary-expressions.toy +++ b/test/scripts/ternary-expressions.toy @@ -18,7 +18,7 @@ //test division prevention { var x = 0; - assert x ? 0 : 1 / x == 0, "Division by zero prevention failed"; + assert (x ? 0 : 1 / x) == 0, "Division by zero prevention failed"; } //test ambiguous syntax @@ -29,7 +29,7 @@ var ddddd = 4; var eeeeee = 5; - assert aa ? bbb ? cccc : ddddd : eeeeee, "Ambiguous syntax failed"; + assert (aa ? bbb ? cccc : ddddd : eeeeee) == 3, "Ambiguous syntax failed"; }