mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
Added constant folding for strings, tweaked some error messages
This commit is contained in:
@@ -59,7 +59,9 @@ void repl() {
|
|||||||
while(node != NULL) {
|
while(node != NULL) {
|
||||||
//pack up and restart
|
//pack up and restart
|
||||||
if (node->type == TOY_AST_NODE_ERROR) {
|
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;
|
error = true;
|
||||||
Toy_freeASTNode(node);
|
Toy_freeASTNode(node);
|
||||||
break;
|
break;
|
||||||
@@ -103,7 +105,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
Toy_freeLiteral(driveLiteral);
|
Toy_freeLiteral(driveLiteral);
|
||||||
Toy_freeLiteral(pathLiteral);
|
Toy_freeLiteral(pathLiteral);
|
||||||
|
|
||||||
//Toy_commandLine specific actions
|
//command line specific actions
|
||||||
if (Toy_commandLine.error) {
|
if (Toy_commandLine.error) {
|
||||||
Toy_usageCommandLine(argc, argv);
|
Toy_usageCommandLine(argc, argv);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -121,7 +123,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
|
|
||||||
//version
|
//version
|
||||||
if (Toy_commandLine.verbose) {
|
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
|
//run source file
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef TOY_EXPORT
|
#ifndef TOY_EXPORT
|
||||||
//for processing the Toy_commandLine line arguments
|
//for processing the command line arguments
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool error;
|
bool error;
|
||||||
bool help;
|
bool help;
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ static Toy_Opcode Toy_writeCompilerWithJumps(Toy_Compiler* compiler, Toy_ASTNode
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TOY_AST_NODE_UNARY: {
|
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);
|
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
|
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
|
//all infixes come here
|
||||||
case TOY_AST_NODE_BINARY: {
|
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);
|
Toy_Opcode override = Toy_writeCompilerWithJumps(compiler, node->binary.left, breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode);
|
||||||
|
|
||||||
//special case for when indexing and assigning
|
//special case for when indexing and assigning
|
||||||
|
|||||||
@@ -397,7 +397,7 @@ static bool execArithmetic(Toy_Interpreter* interpreter, Toy_Opcode opcode) {
|
|||||||
//check for overflow
|
//check for overflow
|
||||||
int totalLength = TOY_AS_STRING(lhs)->length + TOY_AS_STRING(rhs)->length;
|
int totalLength = TOY_AS_STRING(lhs)->length + TOY_AS_STRING(rhs)->length;
|
||||||
if (totalLength > TOY_MAX_STRING_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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,7 +445,7 @@ static bool execArithmetic(Toy_Interpreter* interpreter, Toy_Opcode opcode) {
|
|||||||
case TOY_OP_DIVISION:
|
case TOY_OP_DIVISION:
|
||||||
case TOY_OP_VAR_DIVISION_ASSIGN:
|
case TOY_OP_VAR_DIVISION_ASSIGN:
|
||||||
if (TOY_AS_INTEGER(rhs) == 0) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
Toy_pushLiteralArray(&interpreter->stack, TOY_TO_INTEGER_LITERAL( TOY_AS_INTEGER(lhs) / TOY_AS_INTEGER(rhs) ));
|
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_MODULO:
|
||||||
case TOY_OP_VAR_MODULO_ASSIGN:
|
case TOY_OP_VAR_MODULO_ASSIGN:
|
||||||
if (TOY_AS_INTEGER(rhs) == 0) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
Toy_pushLiteralArray(&interpreter->stack, TOY_TO_INTEGER_LITERAL( TOY_AS_INTEGER(lhs) % TOY_AS_INTEGER(rhs) ));
|
Toy_pushLiteralArray(&interpreter->stack, TOY_TO_INTEGER_LITERAL( TOY_AS_INTEGER(lhs) % TOY_AS_INTEGER(rhs) ));
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
interpreter->errorOutput("[internal] bad opcode argument passed to execArithmetic()");
|
interpreter->errorOutput("[internal] bad opcode argument passed to execArithmetic()\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -492,14 +492,14 @@ static bool execArithmetic(Toy_Interpreter* interpreter, Toy_Opcode opcode) {
|
|||||||
case TOY_OP_DIVISION:
|
case TOY_OP_DIVISION:
|
||||||
case TOY_OP_VAR_DIVISION_ASSIGN:
|
case TOY_OP_VAR_DIVISION_ASSIGN:
|
||||||
if (TOY_AS_FLOAT(rhs) == 0) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
Toy_pushLiteralArray(&interpreter->stack, TOY_TO_FLOAT_LITERAL( TOY_AS_FLOAT(lhs) / TOY_AS_FLOAT(rhs) ));
|
Toy_pushLiteralArray(&interpreter->stack, TOY_TO_FLOAT_LITERAL( TOY_AS_FLOAT(lhs) / TOY_AS_FLOAT(rhs) ));
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
interpreter->errorOutput("[internal] bad opcode argument passed to execArithmetic()");
|
interpreter->errorOutput("[internal] bad opcode argument passed to execArithmetic()\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1558,7 +1558,7 @@ static bool execIndex(Toy_Interpreter* interpreter, bool assignIntermediate) {
|
|||||||
Toy_pushLiteralArray(&arguments, first);
|
Toy_pushLiteralArray(&arguments, first);
|
||||||
Toy_pushLiteralArray(&arguments, second);
|
Toy_pushLiteralArray(&arguments, second);
|
||||||
Toy_pushLiteralArray(&arguments, third);
|
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"
|
Toy_pushLiteralArray(&arguments, TOY_TO_NULL_LITERAL); //it expects an assignment "opcode"
|
||||||
|
|
||||||
//leave the idn and compound on the stack
|
//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, first);
|
||||||
Toy_pushLiteralArray(&arguments, second);
|
Toy_pushLiteralArray(&arguments, second);
|
||||||
Toy_pushLiteralArray(&arguments, third);
|
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"
|
Toy_pushLiteralArray(&arguments, op); //it expects an assignment "opcode"
|
||||||
|
|
||||||
//call the _index function
|
//call the _index function
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ static void consume(Toy_Parser* parser, Toy_TokenType tokenType, const char* msg
|
|||||||
static void synchronize(Toy_Parser* parser) {
|
static void synchronize(Toy_Parser* parser) {
|
||||||
#ifndef TOY_EXPORT
|
#ifndef TOY_EXPORT
|
||||||
if (Toy_commandLine.verbose) {
|
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
|
#endif
|
||||||
|
|
||||||
@@ -982,6 +982,21 @@ static bool calcStaticBinaryArithmetic(Toy_Parser* parser, Toy_ASTNode** nodeHan
|
|||||||
Toy_Literal rhs = (*nodeHandle)->binary.right->atomic.literal;
|
Toy_Literal rhs = (*nodeHandle)->binary.right->atomic.literal;
|
||||||
Toy_Literal result = TOY_TO_NULL_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
|
//type coersion
|
||||||
if (TOY_IS_FLOAT(lhs) && TOY_IS_INTEGER(rhs)) {
|
if (TOY_IS_FLOAT(lhs) && TOY_IS_INTEGER(rhs)) {
|
||||||
rhs = TOY_TO_FLOAT_LITERAL(TOY_AS_INTEGER(rhs));
|
rhs = TOY_TO_FLOAT_LITERAL(TOY_AS_INTEGER(rhs));
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
//test division prevention
|
//test division prevention
|
||||||
{
|
{
|
||||||
var x = 0;
|
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
|
//test ambiguous syntax
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
var ddddd = 4;
|
var ddddd = 4;
|
||||||
var eeeeee = 5;
|
var eeeeee = 5;
|
||||||
|
|
||||||
assert aa ? bbb ? cccc : ddddd : eeeeee, "Ambiguous syntax failed";
|
assert (aa ? bbb ? cccc : ddddd : eeeeee) == 3, "Ambiguous syntax failed";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user