mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
Fixed jumps in functions issue
This commit is contained in:
@@ -267,7 +267,7 @@ static int writeLiteralToCompiler(Compiler* compiler, Literal literal) {
|
||||
return index;
|
||||
}
|
||||
|
||||
static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAddressesPtr, void* continueAddressesPtr) {
|
||||
static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAddressesPtr, void* continueAddressesPtr, int jumpOffsets) { //NOTE: jumpOfsets are included, because function arg and return indexes are embedded in the code body i.e. need to include thier sizes in the jump
|
||||
//grow if the bytecode space is too small
|
||||
if (compiler->count + 32 > compiler->capacity) {
|
||||
int oldCapacity = compiler->capacity;
|
||||
@@ -291,20 +291,20 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
|
||||
|
||||
case NODE_UNARY:
|
||||
//pass to the child node, then embed the unary command (print, negate, etc.)
|
||||
writeCompilerWithJumps(compiler, node->unary.child, breakAddressesPtr, continueAddressesPtr);
|
||||
writeCompilerWithJumps(compiler, node->unary.child, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)node->unary.opcode; //1 byte
|
||||
break;
|
||||
|
||||
case NODE_BINARY:
|
||||
//pass to the child nodes, then embed the binary command (math, etc.)
|
||||
writeCompilerWithJumps(compiler, node->binary.left, breakAddressesPtr, continueAddressesPtr);
|
||||
writeCompilerWithJumps(compiler, node->binary.right, breakAddressesPtr, continueAddressesPtr);
|
||||
writeCompilerWithJumps(compiler, node->binary.left, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
writeCompilerWithJumps(compiler, node->binary.right, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)node->binary.opcode; //1 byte
|
||||
break;
|
||||
|
||||
case NODE_GROUPING:
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)OP_GROUPING_BEGIN; //1 byte
|
||||
writeCompilerWithJumps(compiler, node->grouping.child, breakAddressesPtr, continueAddressesPtr);
|
||||
writeCompilerWithJumps(compiler, node->grouping.child, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)OP_GROUPING_END; //1 byte
|
||||
break;
|
||||
|
||||
@@ -312,7 +312,7 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)OP_SCOPE_BEGIN; //1 byte
|
||||
|
||||
for (int i = 0; i < node->block.count; i++) {
|
||||
writeCompilerWithJumps(compiler, &(node->block.nodes[i]), breakAddressesPtr, continueAddressesPtr);
|
||||
writeCompilerWithJumps(compiler, &(node->block.nodes[i]), breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
}
|
||||
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)OP_SCOPE_END; //1 byte
|
||||
@@ -343,7 +343,7 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
|
||||
|
||||
case NODE_VAR_DECL: {
|
||||
//first, embed the expression (leaves it on the stack)
|
||||
writeCompilerWithJumps(compiler, node->varDecl.expression, breakAddressesPtr, continueAddressesPtr);
|
||||
writeCompilerWithJumps(compiler, node->varDecl.expression, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
|
||||
//write each piece of the declaration to the bytecode
|
||||
int identifierIndex = findLiteralIndex(&compiler->literalCache, node->varDecl.identifier);
|
||||
@@ -379,7 +379,7 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
|
||||
initCompiler(fnCompiler);
|
||||
writeCompiler(fnCompiler, node->fnDecl.arguments); //can be empty, but not NULL
|
||||
writeCompiler(fnCompiler, node->fnDecl.returns); //can be empty, but not NULL
|
||||
writeCompiler(fnCompiler, node->fnDecl.block); //can be empty, but not NULL
|
||||
writeCompilerWithJumps(fnCompiler, node->fnDecl.block, NULL, NULL, -4); //can be empty, but not NULL
|
||||
|
||||
//create the function in the literal cache (by storing the compiler object)
|
||||
Literal fnLiteral = TO_FUNCTION_LITERAL(fnCompiler, 0);
|
||||
@@ -429,7 +429,7 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
|
||||
for (int i = 0; i < node->fnCall.arguments->fnCollection.count; i++) { //reverse order, to count from the beginning in the interpreter
|
||||
//sub-calls
|
||||
if (node->fnCall.arguments->fnCollection.nodes[i].type != NODE_LITERAL) {
|
||||
writeCompilerWithJumps(compiler, &node->fnCall.arguments->fnCollection.nodes[i], breakAddressesPtr, continueAddressesPtr);
|
||||
writeCompilerWithJumps(compiler, &node->fnCall.arguments->fnCollection.nodes[i], breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -482,7 +482,7 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
|
||||
|
||||
case NODE_PATH_IF: {
|
||||
//process the condition
|
||||
writeCompilerWithJumps(compiler, node->path.condition, breakAddressesPtr, continueAddressesPtr);
|
||||
writeCompilerWithJumps(compiler, node->path.condition, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
|
||||
//cache the point to insert the jump distance at
|
||||
compiler->bytecode[compiler->count++] = OP_IF_FALSE_JUMP; //1 byte
|
||||
@@ -490,7 +490,7 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
|
||||
compiler->count += sizeof(unsigned short); //2 bytes
|
||||
|
||||
//write the then path
|
||||
writeCompilerWithJumps(compiler, node->path.thenPath, breakAddressesPtr, continueAddressesPtr);
|
||||
writeCompilerWithJumps(compiler, node->path.thenPath, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
|
||||
int jumpToEnd = 0;
|
||||
|
||||
@@ -502,14 +502,14 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
|
||||
}
|
||||
|
||||
//update the jumpToElse to point here
|
||||
AS_USHORT(compiler->bytecode[jumpToElse]) = compiler->count; //2 bytes
|
||||
AS_USHORT(compiler->bytecode[jumpToElse]) = compiler->count + jumpOffsets; //2 bytes
|
||||
|
||||
if (node->path.elsePath) {
|
||||
//if there's an else path, write it and
|
||||
writeCompilerWithJumps(compiler, node->path.elsePath, breakAddressesPtr, continueAddressesPtr);
|
||||
writeCompilerWithJumps(compiler, node->path.elsePath, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
|
||||
//update the jumpToEnd to point here
|
||||
AS_USHORT(compiler->bytecode[jumpToEnd]) = compiler->count; //2 bytes
|
||||
AS_USHORT(compiler->bytecode[jumpToEnd]) = compiler->count + jumpOffsets; //2 bytes
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -526,7 +526,7 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
|
||||
unsigned short jumpToStart = compiler->count;
|
||||
|
||||
//process the condition
|
||||
writeCompilerWithJumps(compiler, node->path.condition, &breakAddresses, &continueAddresses);
|
||||
writeCompilerWithJumps(compiler, node->path.condition, &breakAddresses, &continueAddresses, jumpOffsets);
|
||||
|
||||
//if false, jump to end
|
||||
compiler->bytecode[compiler->count++] = OP_IF_FALSE_JUMP; //1 byte
|
||||
@@ -534,27 +534,30 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
|
||||
compiler->count += sizeof(unsigned short); //2 bytes
|
||||
|
||||
//write the body
|
||||
writeCompilerWithJumps(compiler, node->path.thenPath, &breakAddresses, &continueAddresses);
|
||||
writeCompilerWithJumps(compiler, node->path.thenPath, &breakAddresses, &continueAddresses, jumpOffsets);
|
||||
|
||||
//jump to condition
|
||||
compiler->bytecode[compiler->count++] = OP_JUMP; //1 byte
|
||||
AS_USHORT(compiler->bytecode[compiler->count]) = jumpToStart;
|
||||
AS_USHORT(compiler->bytecode[compiler->count]) = jumpToStart + jumpOffsets;
|
||||
compiler->count += sizeof(unsigned short); //2 bytes
|
||||
|
||||
//jump from condition
|
||||
AS_USHORT(compiler->bytecode[jumpToEnd]) = (unsigned short)compiler->count;
|
||||
AS_USHORT(compiler->bytecode[jumpToEnd]) = (unsigned short)compiler->count + jumpOffsets;
|
||||
|
||||
//set the breaks and continues
|
||||
for (int i = 0; i < breakAddresses.count; i++) {
|
||||
int point = AS_INTEGER(breakAddresses.literals[i]);
|
||||
AS_USHORT(compiler->bytecode[point]) = (unsigned short)compiler->count;
|
||||
AS_USHORT(compiler->bytecode[point]) = (unsigned short)compiler->count + jumpOffsets;
|
||||
}
|
||||
|
||||
for (int i = 0; i < continueAddresses.count; i++) {
|
||||
int point = AS_INTEGER(continueAddresses.literals[i]);
|
||||
AS_USHORT(compiler->bytecode[point]) = jumpToStart;
|
||||
AS_USHORT(compiler->bytecode[point]) = jumpToStart + jumpOffsets;
|
||||
}
|
||||
|
||||
//clear the stack after use
|
||||
compiler->bytecode[compiler->count++] = OP_POP_STACK; //1 byte
|
||||
|
||||
//cleanup
|
||||
freeLiteralArray(&breakAddresses);
|
||||
freeLiteralArray(&continueAddresses);
|
||||
@@ -572,11 +575,11 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
|
||||
compiler->bytecode[compiler->count++] = OP_SCOPE_BEGIN; //1 byte
|
||||
|
||||
//initial setup
|
||||
writeCompilerWithJumps(compiler, node->path.preClause, &breakAddresses, &continueAddresses);
|
||||
writeCompilerWithJumps(compiler, node->path.preClause, &breakAddresses, &continueAddresses, jumpOffsets);
|
||||
|
||||
//conditional
|
||||
unsigned short jumpToStart = compiler->count;
|
||||
writeCompilerWithJumps(compiler, node->path.condition, &breakAddresses, &continueAddresses);
|
||||
writeCompilerWithJumps(compiler, node->path.condition, &breakAddresses, &continueAddresses, jumpOffsets);
|
||||
|
||||
//if false jump to end
|
||||
compiler->bytecode[compiler->count++] = OP_IF_FALSE_JUMP; //1 byte
|
||||
@@ -585,34 +588,37 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
|
||||
|
||||
//write the body
|
||||
compiler->bytecode[compiler->count++] = OP_SCOPE_BEGIN; //1 byte
|
||||
writeCompilerWithJumps(compiler, node->path.thenPath, &breakAddresses, &continueAddresses);
|
||||
writeCompilerWithJumps(compiler, node->path.thenPath, &breakAddresses, &continueAddresses, jumpOffsets);
|
||||
compiler->bytecode[compiler->count++] = OP_SCOPE_END; //1 byte
|
||||
|
||||
//for-breaks actually jump to the bottom
|
||||
int jumpToIncrement = compiler->count;
|
||||
|
||||
//evaluate third clause, restart
|
||||
writeCompilerWithJumps(compiler, node->path.postClause, &breakAddresses, &continueAddresses);
|
||||
writeCompilerWithJumps(compiler, node->path.postClause, &breakAddresses, &continueAddresses, jumpOffsets);
|
||||
|
||||
compiler->bytecode[compiler->count++] = OP_JUMP; //1 byte
|
||||
AS_USHORT(compiler->bytecode[compiler->count]) = jumpToStart;
|
||||
AS_USHORT(compiler->bytecode[compiler->count]) = jumpToStart + jumpOffsets;
|
||||
compiler->count += sizeof(unsigned short); //2 bytes
|
||||
|
||||
AS_USHORT(compiler->bytecode[jumpToEnd]) = compiler->count;
|
||||
AS_USHORT(compiler->bytecode[jumpToEnd]) = compiler->count + jumpOffsets;
|
||||
|
||||
compiler->bytecode[compiler->count++] = OP_SCOPE_END; //1 byte
|
||||
|
||||
//set the breaks and continues
|
||||
for (int i = 0; i < breakAddresses.count; i++) {
|
||||
int point = AS_INTEGER(breakAddresses.literals[i]);
|
||||
AS_USHORT(compiler->bytecode[point]) = compiler->count;
|
||||
AS_USHORT(compiler->bytecode[point]) = compiler->count + jumpOffsets;
|
||||
}
|
||||
|
||||
for (int i = 0; i < continueAddresses.count; i++) {
|
||||
int point = AS_INTEGER(continueAddresses.literals[i]);
|
||||
AS_USHORT(compiler->bytecode[point]) = jumpToIncrement;
|
||||
AS_USHORT(compiler->bytecode[point]) = jumpToIncrement + jumpOffsets;
|
||||
}
|
||||
|
||||
//clear the stack after use
|
||||
compiler->bytecode[compiler->count++] = OP_POP_STACK; //1 byte
|
||||
|
||||
//cleanup
|
||||
freeLiteralArray(&breakAddresses);
|
||||
freeLiteralArray(&continueAddresses);
|
||||
@@ -658,7 +664,7 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
|
||||
case NODE_PATH_RETURN: {
|
||||
//read each returned literal onto the stack, and return the number of values to return
|
||||
for (int i = 0; i < node->path.thenPath->fnCollection.count; i++) {
|
||||
writeCompilerWithJumps(compiler, &node->path.thenPath->fnCollection.nodes[i], breakAddressesPtr, continueAddressesPtr);
|
||||
writeCompilerWithJumps(compiler, &node->path.thenPath->fnCollection.nodes[i], breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
}
|
||||
|
||||
//push the return, with the number of literals
|
||||
@@ -714,7 +720,7 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
|
||||
}
|
||||
|
||||
void writeCompiler(Compiler* compiler, Node* node) {
|
||||
writeCompilerWithJumps(compiler, node, NULL, NULL);
|
||||
writeCompilerWithJumps(compiler, node, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
void freeCompiler(Compiler* compiler) {
|
||||
|
||||
@@ -597,8 +597,12 @@ static bool execPushLiteral(Interpreter* interpreter, bool lng) {
|
||||
static bool rawLiteral(Interpreter* interpreter) {
|
||||
Literal lit = popLiteralArray(&interpreter->stack);
|
||||
|
||||
if (!parseIdentifierToValue(interpreter, &lit)) {
|
||||
return false;
|
||||
if (IS_IDENTIFIER(lit)) {
|
||||
Literal idn = lit;
|
||||
if (!parseIdentifierToValue(interpreter, &lit)) {
|
||||
return false;
|
||||
}
|
||||
freeLiteral(idn);
|
||||
}
|
||||
|
||||
pushLiteralArray(&interpreter->stack, lit);
|
||||
@@ -1277,8 +1281,12 @@ static bool execFalseJump(Interpreter* interpreter) {
|
||||
//actually jump
|
||||
Literal lit = popLiteralArray(&interpreter->stack);
|
||||
|
||||
if (!parseIdentifierToValue(interpreter, &lit)) {
|
||||
return false;
|
||||
bool freeLit = false;
|
||||
if (IS_IDENTIFIER(lit)) {
|
||||
Literal idn = lit;
|
||||
parseIdentifierToValue(interpreter, &lit);
|
||||
freeLiteral(idn);
|
||||
freeLit = true;
|
||||
}
|
||||
|
||||
if (IS_NULL(lit)) {
|
||||
@@ -1290,7 +1298,9 @@ static bool execFalseJump(Interpreter* interpreter) {
|
||||
interpreter->count = target + interpreter->codeStart;
|
||||
}
|
||||
|
||||
freeLiteral(lit);
|
||||
if (freeLit) {
|
||||
freeLiteral(lit);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1322,8 +1332,6 @@ static bool execFnCall(Interpreter* interpreter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
freeLiteral(identifier);
|
||||
|
||||
//check for side-loaded native functions
|
||||
if (IS_FUNCTION_NATIVE(func)) {
|
||||
//reverse the order to the correct order
|
||||
@@ -1343,6 +1351,18 @@ static bool execFnCall(Interpreter* interpreter) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!IS_FUNCTION(func)) {
|
||||
printf(ERROR "ERROR: Function not found: ");
|
||||
printLiteral(identifier);
|
||||
printf("\n" RESET);
|
||||
|
||||
freeLiteral(identifier);
|
||||
freeLiteralArray(&arguments);
|
||||
return false;
|
||||
}
|
||||
|
||||
freeLiteral(identifier);
|
||||
|
||||
//set up a new interpreter
|
||||
Interpreter inner;
|
||||
|
||||
@@ -1463,7 +1483,7 @@ static bool execFnCall(Interpreter* interpreter) {
|
||||
initLiteralArray(&returns);
|
||||
|
||||
//unpack the results
|
||||
while (inner.stack.count > 0) {
|
||||
for (int i = 0; i < (returnArray->count || 1); i++) {
|
||||
Literal lit = popLiteralArray(&inner.stack);
|
||||
pushLiteralArray(&returns, lit); //NOTE: also reverses the order
|
||||
freeLiteral(lit);
|
||||
@@ -1473,7 +1493,7 @@ static bool execFnCall(Interpreter* interpreter) {
|
||||
|
||||
//TODO: remove this when multiple assignment is enabled - note the BUGFIX that balances the stack
|
||||
if (returns.count > 1) {
|
||||
printf(ERROR "ERROR: Too many values returned (multiple returns not yet implemented)\n" RESET);
|
||||
printf(ERROR "ERROR: Too many values returned (multiple returns not yet supported)\n" RESET);
|
||||
|
||||
returnValue = false;
|
||||
}
|
||||
@@ -1526,7 +1546,11 @@ static bool execFnReturn(Interpreter* interpreter) {
|
||||
//get the values of everything on the stack
|
||||
while (interpreter->stack.count > 0) {
|
||||
Literal lit = popLiteralArray(&interpreter->stack);
|
||||
parseIdentifierToValue(interpreter, &lit);
|
||||
if (IS_IDENTIFIER(lit)) {
|
||||
Literal idn = lit;
|
||||
parseIdentifierToValue(interpreter, &lit);
|
||||
freeLiteral(idn);
|
||||
}
|
||||
pushLiteralArray(&returns, lit); //reverses the order
|
||||
freeLiteral(lit);
|
||||
}
|
||||
@@ -1731,6 +1755,12 @@ static void execInterpreter(Interpreter* interpreter) {
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_POP_STACK:
|
||||
while (interpreter->stack.count > 0) {
|
||||
freeLiteral(popLiteralArray(&interpreter->stack));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printf(ERROR "Error: Unknown opcode found %d, terminating\n" RESET, opcode);
|
||||
printLiteralArray(&interpreter->stack, "\n");
|
||||
|
||||
@@ -63,6 +63,9 @@ typedef enum Opcode {
|
||||
OP_FN_CALL,
|
||||
OP_FN_RETURN,
|
||||
|
||||
//pop the stack at the end of a complex statement
|
||||
OP_POP_STACK,
|
||||
|
||||
//meta
|
||||
OP_FN_END, //different from SECTION_END
|
||||
OP_SECTION_END = 255,
|
||||
|
||||
Reference in New Issue
Block a user