mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 23:04:08 +10:00
Fixed jumps in functions issue
This commit is contained in:
@@ -1,8 +1,19 @@
|
|||||||
|
fn capture(count: int) {
|
||||||
|
print count;
|
||||||
|
print capture;
|
||||||
|
|
||||||
|
if (count < 5) {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
print count;
|
||||||
|
print capture;
|
||||||
|
|
||||||
fn foo() {
|
count++;
|
||||||
//
|
count++;
|
||||||
|
|
||||||
|
// return capture(count + 1);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
foo();
|
print capture(52);
|
||||||
|
|||||||
87
scripts/test/jumps-in-functions.toy
Normal file
87
scripts/test/jumps-in-functions.toy
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
fn sanity() {
|
||||||
|
//test true jump
|
||||||
|
if (true) {
|
||||||
|
assert true, "if-then failed (1)";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert false, "if-then failed (2)";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//test false jump
|
||||||
|
if (false) {
|
||||||
|
assert false, "if-then failed (3)";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert true, "if-then failed (4)";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//test while loop
|
||||||
|
var whileCounter = 0;
|
||||||
|
while (whileCounter < 10) {
|
||||||
|
whileCounter = whileCounter + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert whileCounter == 10, "while-loop failed";
|
||||||
|
|
||||||
|
|
||||||
|
//test for loop
|
||||||
|
var forCache = 0;
|
||||||
|
for (var i = 0; i < 20; i++) {
|
||||||
|
forCache = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert forCache == 19, "for-loop failed";
|
||||||
|
|
||||||
|
|
||||||
|
//test break - while
|
||||||
|
var breakWhileCache = 0;
|
||||||
|
while(true) {
|
||||||
|
breakWhileCache = breakWhileCache + 1;
|
||||||
|
|
||||||
|
if (breakWhileCache >= 7) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert breakWhileCache == 7, "break-while failed";
|
||||||
|
|
||||||
|
|
||||||
|
//test continue - while
|
||||||
|
var continueWhileCache = 0;
|
||||||
|
while (continueWhileCache < 10) {
|
||||||
|
continueWhileCache = continueWhileCache + 1;
|
||||||
|
|
||||||
|
if (continueWhileCache >= 7) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert continueWhileCache < 7, "continue-while failed";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//test break - for
|
||||||
|
for (var i = 0; i < 10; i++) {
|
||||||
|
if (i >= 7) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert i < 7, "break-for failed";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//test break - continue
|
||||||
|
for (var i = 0; i < 10; i++) {
|
||||||
|
if (i >= 7) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert i < 7, "continue-for failed";
|
||||||
|
}
|
||||||
|
|
||||||
|
print "All good";
|
||||||
|
}
|
||||||
|
|
||||||
|
//invoke the test
|
||||||
|
sanity();
|
||||||
@@ -267,7 +267,7 @@ static int writeLiteralToCompiler(Compiler* compiler, Literal literal) {
|
|||||||
return index;
|
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
|
//grow if the bytecode space is too small
|
||||||
if (compiler->count + 32 > compiler->capacity) {
|
if (compiler->count + 32 > compiler->capacity) {
|
||||||
int oldCapacity = compiler->capacity;
|
int oldCapacity = compiler->capacity;
|
||||||
@@ -291,20 +291,20 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
|
|||||||
|
|
||||||
case NODE_UNARY:
|
case NODE_UNARY:
|
||||||
//pass to the child node, then embed the unary command (print, negate, etc.)
|
//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
|
compiler->bytecode[compiler->count++] = (unsigned char)node->unary.opcode; //1 byte
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NODE_BINARY:
|
case NODE_BINARY:
|
||||||
//pass to the child nodes, then embed the binary command (math, etc.)
|
//pass to the child nodes, then embed the binary command (math, etc.)
|
||||||
writeCompilerWithJumps(compiler, node->binary.left, breakAddressesPtr, continueAddressesPtr);
|
writeCompilerWithJumps(compiler, node->binary.left, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||||
writeCompilerWithJumps(compiler, node->binary.right, breakAddressesPtr, continueAddressesPtr);
|
writeCompilerWithJumps(compiler, node->binary.right, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)node->binary.opcode; //1 byte
|
compiler->bytecode[compiler->count++] = (unsigned char)node->binary.opcode; //1 byte
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NODE_GROUPING:
|
case NODE_GROUPING:
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)OP_GROUPING_BEGIN; //1 byte
|
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
|
compiler->bytecode[compiler->count++] = (unsigned char)OP_GROUPING_END; //1 byte
|
||||||
break;
|
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
|
compiler->bytecode[compiler->count++] = (unsigned char)OP_SCOPE_BEGIN; //1 byte
|
||||||
|
|
||||||
for (int i = 0; i < node->block.count; i++) {
|
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
|
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: {
|
case NODE_VAR_DECL: {
|
||||||
//first, embed the expression (leaves it on the stack)
|
//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
|
//write each piece of the declaration to the bytecode
|
||||||
int identifierIndex = findLiteralIndex(&compiler->literalCache, node->varDecl.identifier);
|
int identifierIndex = findLiteralIndex(&compiler->literalCache, node->varDecl.identifier);
|
||||||
@@ -379,7 +379,7 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
|
|||||||
initCompiler(fnCompiler);
|
initCompiler(fnCompiler);
|
||||||
writeCompiler(fnCompiler, node->fnDecl.arguments); //can be empty, but not NULL
|
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.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)
|
//create the function in the literal cache (by storing the compiler object)
|
||||||
Literal fnLiteral = TO_FUNCTION_LITERAL(fnCompiler, 0);
|
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
|
for (int i = 0; i < node->fnCall.arguments->fnCollection.count; i++) { //reverse order, to count from the beginning in the interpreter
|
||||||
//sub-calls
|
//sub-calls
|
||||||
if (node->fnCall.arguments->fnCollection.nodes[i].type != NODE_LITERAL) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,7 +482,7 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
|
|||||||
|
|
||||||
case NODE_PATH_IF: {
|
case NODE_PATH_IF: {
|
||||||
//process the condition
|
//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
|
//cache the point to insert the jump distance at
|
||||||
compiler->bytecode[compiler->count++] = OP_IF_FALSE_JUMP; //1 byte
|
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
|
compiler->count += sizeof(unsigned short); //2 bytes
|
||||||
|
|
||||||
//write the then path
|
//write the then path
|
||||||
writeCompilerWithJumps(compiler, node->path.thenPath, breakAddressesPtr, continueAddressesPtr);
|
writeCompilerWithJumps(compiler, node->path.thenPath, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||||
|
|
||||||
int jumpToEnd = 0;
|
int jumpToEnd = 0;
|
||||||
|
|
||||||
@@ -502,14 +502,14 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
|
|||||||
}
|
}
|
||||||
|
|
||||||
//update the jumpToElse to point here
|
//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 (node->path.elsePath) {
|
||||||
//if there's an else path, write it and
|
//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
|
//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;
|
break;
|
||||||
@@ -526,7 +526,7 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
|
|||||||
unsigned short jumpToStart = compiler->count;
|
unsigned short jumpToStart = compiler->count;
|
||||||
|
|
||||||
//process the condition
|
//process the condition
|
||||||
writeCompilerWithJumps(compiler, node->path.condition, &breakAddresses, &continueAddresses);
|
writeCompilerWithJumps(compiler, node->path.condition, &breakAddresses, &continueAddresses, jumpOffsets);
|
||||||
|
|
||||||
//if false, jump to end
|
//if false, jump to end
|
||||||
compiler->bytecode[compiler->count++] = OP_IF_FALSE_JUMP; //1 byte
|
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
|
compiler->count += sizeof(unsigned short); //2 bytes
|
||||||
|
|
||||||
//write the body
|
//write the body
|
||||||
writeCompilerWithJumps(compiler, node->path.thenPath, &breakAddresses, &continueAddresses);
|
writeCompilerWithJumps(compiler, node->path.thenPath, &breakAddresses, &continueAddresses, jumpOffsets);
|
||||||
|
|
||||||
//jump to condition
|
//jump to condition
|
||||||
compiler->bytecode[compiler->count++] = OP_JUMP; //1 byte
|
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
|
compiler->count += sizeof(unsigned short); //2 bytes
|
||||||
|
|
||||||
//jump from condition
|
//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
|
//set the breaks and continues
|
||||||
for (int i = 0; i < breakAddresses.count; i++) {
|
for (int i = 0; i < breakAddresses.count; i++) {
|
||||||
int point = AS_INTEGER(breakAddresses.literals[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++) {
|
for (int i = 0; i < continueAddresses.count; i++) {
|
||||||
int point = AS_INTEGER(continueAddresses.literals[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
|
//cleanup
|
||||||
freeLiteralArray(&breakAddresses);
|
freeLiteralArray(&breakAddresses);
|
||||||
freeLiteralArray(&continueAddresses);
|
freeLiteralArray(&continueAddresses);
|
||||||
@@ -572,11 +575,11 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
|
|||||||
compiler->bytecode[compiler->count++] = OP_SCOPE_BEGIN; //1 byte
|
compiler->bytecode[compiler->count++] = OP_SCOPE_BEGIN; //1 byte
|
||||||
|
|
||||||
//initial setup
|
//initial setup
|
||||||
writeCompilerWithJumps(compiler, node->path.preClause, &breakAddresses, &continueAddresses);
|
writeCompilerWithJumps(compiler, node->path.preClause, &breakAddresses, &continueAddresses, jumpOffsets);
|
||||||
|
|
||||||
//conditional
|
//conditional
|
||||||
unsigned short jumpToStart = compiler->count;
|
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
|
//if false jump to end
|
||||||
compiler->bytecode[compiler->count++] = OP_IF_FALSE_JUMP; //1 byte
|
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
|
//write the body
|
||||||
compiler->bytecode[compiler->count++] = OP_SCOPE_BEGIN; //1 byte
|
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
|
compiler->bytecode[compiler->count++] = OP_SCOPE_END; //1 byte
|
||||||
|
|
||||||
//for-breaks actually jump to the bottom
|
//for-breaks actually jump to the bottom
|
||||||
int jumpToIncrement = compiler->count;
|
int jumpToIncrement = compiler->count;
|
||||||
|
|
||||||
//evaluate third clause, restart
|
//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
|
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
|
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
|
compiler->bytecode[compiler->count++] = OP_SCOPE_END; //1 byte
|
||||||
|
|
||||||
//set the breaks and continues
|
//set the breaks and continues
|
||||||
for (int i = 0; i < breakAddresses.count; i++) {
|
for (int i = 0; i < breakAddresses.count; i++) {
|
||||||
int point = AS_INTEGER(breakAddresses.literals[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++) {
|
for (int i = 0; i < continueAddresses.count; i++) {
|
||||||
int point = AS_INTEGER(continueAddresses.literals[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
|
//cleanup
|
||||||
freeLiteralArray(&breakAddresses);
|
freeLiteralArray(&breakAddresses);
|
||||||
freeLiteralArray(&continueAddresses);
|
freeLiteralArray(&continueAddresses);
|
||||||
@@ -658,7 +664,7 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
|
|||||||
case NODE_PATH_RETURN: {
|
case NODE_PATH_RETURN: {
|
||||||
//read each returned literal onto the stack, and return the number of values to 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++) {
|
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
|
//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) {
|
void writeCompiler(Compiler* compiler, Node* node) {
|
||||||
writeCompilerWithJumps(compiler, node, NULL, NULL);
|
writeCompilerWithJumps(compiler, node, NULL, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeCompiler(Compiler* compiler) {
|
void freeCompiler(Compiler* compiler) {
|
||||||
|
|||||||
@@ -597,9 +597,13 @@ static bool execPushLiteral(Interpreter* interpreter, bool lng) {
|
|||||||
static bool rawLiteral(Interpreter* interpreter) {
|
static bool rawLiteral(Interpreter* interpreter) {
|
||||||
Literal lit = popLiteralArray(&interpreter->stack);
|
Literal lit = popLiteralArray(&interpreter->stack);
|
||||||
|
|
||||||
|
if (IS_IDENTIFIER(lit)) {
|
||||||
|
Literal idn = lit;
|
||||||
if (!parseIdentifierToValue(interpreter, &lit)) {
|
if (!parseIdentifierToValue(interpreter, &lit)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
freeLiteral(idn);
|
||||||
|
}
|
||||||
|
|
||||||
pushLiteralArray(&interpreter->stack, lit);
|
pushLiteralArray(&interpreter->stack, lit);
|
||||||
|
|
||||||
@@ -1277,8 +1281,12 @@ static bool execFalseJump(Interpreter* interpreter) {
|
|||||||
//actually jump
|
//actually jump
|
||||||
Literal lit = popLiteralArray(&interpreter->stack);
|
Literal lit = popLiteralArray(&interpreter->stack);
|
||||||
|
|
||||||
if (!parseIdentifierToValue(interpreter, &lit)) {
|
bool freeLit = false;
|
||||||
return false;
|
if (IS_IDENTIFIER(lit)) {
|
||||||
|
Literal idn = lit;
|
||||||
|
parseIdentifierToValue(interpreter, &lit);
|
||||||
|
freeLiteral(idn);
|
||||||
|
freeLit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_NULL(lit)) {
|
if (IS_NULL(lit)) {
|
||||||
@@ -1290,7 +1298,9 @@ static bool execFalseJump(Interpreter* interpreter) {
|
|||||||
interpreter->count = target + interpreter->codeStart;
|
interpreter->count = target + interpreter->codeStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (freeLit) {
|
||||||
freeLiteral(lit);
|
freeLiteral(lit);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1322,8 +1332,6 @@ static bool execFnCall(Interpreter* interpreter) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
freeLiteral(identifier);
|
|
||||||
|
|
||||||
//check for side-loaded native functions
|
//check for side-loaded native functions
|
||||||
if (IS_FUNCTION_NATIVE(func)) {
|
if (IS_FUNCTION_NATIVE(func)) {
|
||||||
//reverse the order to the correct order
|
//reverse the order to the correct order
|
||||||
@@ -1343,6 +1351,18 @@ static bool execFnCall(Interpreter* interpreter) {
|
|||||||
return true;
|
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
|
//set up a new interpreter
|
||||||
Interpreter inner;
|
Interpreter inner;
|
||||||
|
|
||||||
@@ -1463,7 +1483,7 @@ static bool execFnCall(Interpreter* interpreter) {
|
|||||||
initLiteralArray(&returns);
|
initLiteralArray(&returns);
|
||||||
|
|
||||||
//unpack the results
|
//unpack the results
|
||||||
while (inner.stack.count > 0) {
|
for (int i = 0; i < (returnArray->count || 1); i++) {
|
||||||
Literal lit = popLiteralArray(&inner.stack);
|
Literal lit = popLiteralArray(&inner.stack);
|
||||||
pushLiteralArray(&returns, lit); //NOTE: also reverses the order
|
pushLiteralArray(&returns, lit); //NOTE: also reverses the order
|
||||||
freeLiteral(lit);
|
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
|
//TODO: remove this when multiple assignment is enabled - note the BUGFIX that balances the stack
|
||||||
if (returns.count > 1) {
|
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;
|
returnValue = false;
|
||||||
}
|
}
|
||||||
@@ -1526,7 +1546,11 @@ static bool execFnReturn(Interpreter* interpreter) {
|
|||||||
//get the values of everything on the stack
|
//get the values of everything on the stack
|
||||||
while (interpreter->stack.count > 0) {
|
while (interpreter->stack.count > 0) {
|
||||||
Literal lit = popLiteralArray(&interpreter->stack);
|
Literal lit = popLiteralArray(&interpreter->stack);
|
||||||
|
if (IS_IDENTIFIER(lit)) {
|
||||||
|
Literal idn = lit;
|
||||||
parseIdentifierToValue(interpreter, &lit);
|
parseIdentifierToValue(interpreter, &lit);
|
||||||
|
freeLiteral(idn);
|
||||||
|
}
|
||||||
pushLiteralArray(&returns, lit); //reverses the order
|
pushLiteralArray(&returns, lit); //reverses the order
|
||||||
freeLiteral(lit);
|
freeLiteral(lit);
|
||||||
}
|
}
|
||||||
@@ -1731,6 +1755,12 @@ static void execInterpreter(Interpreter* interpreter) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OP_POP_STACK:
|
||||||
|
while (interpreter->stack.count > 0) {
|
||||||
|
freeLiteral(popLiteralArray(&interpreter->stack));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf(ERROR "Error: Unknown opcode found %d, terminating\n" RESET, opcode);
|
printf(ERROR "Error: Unknown opcode found %d, terminating\n" RESET, opcode);
|
||||||
printLiteralArray(&interpreter->stack, "\n");
|
printLiteralArray(&interpreter->stack, "\n");
|
||||||
|
|||||||
@@ -63,6 +63,9 @@ typedef enum Opcode {
|
|||||||
OP_FN_CALL,
|
OP_FN_CALL,
|
||||||
OP_FN_RETURN,
|
OP_FN_RETURN,
|
||||||
|
|
||||||
|
//pop the stack at the end of a complex statement
|
||||||
|
OP_POP_STACK,
|
||||||
|
|
||||||
//meta
|
//meta
|
||||||
OP_FN_END, //different from SECTION_END
|
OP_FN_END, //different from SECTION_END
|
||||||
OP_SECTION_END = 255,
|
OP_SECTION_END = 255,
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ all: $(OBJ) $(TESTS:%.c=../$(OUTDIR)/%.exe)
|
|||||||
ifeq ($(shell uname),Linux)
|
ifeq ($(shell uname),Linux)
|
||||||
valgrind --leak-check=full --track-origins=yes $@
|
valgrind --leak-check=full --track-origins=yes $@
|
||||||
else
|
else
|
||||||
@echo please run these tests with valgrind on linux
|
$@
|
||||||
endif
|
endif
|
||||||
|
|
||||||
$(OBJ): | $(ODIR)
|
$(OBJ): | $(ODIR)
|
||||||
|
|||||||
@@ -150,13 +150,14 @@ int main() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
//run each file in ../scripts/test/
|
//run each file in ../scripts/test/
|
||||||
int count = 12;
|
int count = 13;
|
||||||
char* filenames[] = {
|
char* filenames[] = {
|
||||||
"arithmetic.toy",
|
"arithmetic.toy",
|
||||||
"casting.toy",
|
"casting.toy",
|
||||||
"comparisons.toy",
|
"comparisons.toy",
|
||||||
"functions.toy",
|
"functions.toy",
|
||||||
"jumps.toy",
|
"jumps.toy",
|
||||||
|
"jumps-in-functions.toy",
|
||||||
"logicals.toy",
|
"logicals.toy",
|
||||||
"long-array.toy",
|
"long-array.toy",
|
||||||
"long-dictionary.toy",
|
"long-dictionary.toy",
|
||||||
|
|||||||
Reference in New Issue
Block a user