mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 23:04:08 +10:00
Fixed nested assignment bug
This commit is contained in:
@@ -35,9 +35,9 @@ DONE: A way to check the type of a variable (typeOf keyword)
|
|||||||
DONE: slice and dot notation around the builtin _index and _dot functions
|
DONE: slice and dot notation around the builtin _index and _dot functions
|
||||||
DONE: maximum recursion/function depth
|
DONE: maximum recursion/function depth
|
||||||
DONE: better sugar for _push, _pop, _length
|
DONE: better sugar for _push, _pop, _length
|
||||||
|
DONE: nested compound assignment bug
|
||||||
|
|
||||||
|
|
||||||
TODO: nested compound assignment
|
|
||||||
TODO: ternary operator?
|
TODO: ternary operator?
|
||||||
TODO: Nullish types?
|
TODO: Nullish types?
|
||||||
TODO: hooks on the external libraries, triggered on import
|
TODO: hooks on the external libraries, triggered on import
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
|
|
||||||
|
|
||||||
|
//test nested indexing
|
||||||
|
{
|
||||||
|
var a = [[[0]]];
|
||||||
|
|
||||||
fn loop(count) {
|
a[0][0][0] = 42;
|
||||||
print count++;
|
print a;
|
||||||
|
assert a[0][0] == [42], "nested indexing failed";
|
||||||
loop(count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loop(0);
|
|
||||||
@@ -61,4 +61,15 @@
|
|||||||
assert week[first:second:third] == ["wednesday", "tuesday"], "indexing with variables failed";
|
assert week[first:second:third] == ["wednesday", "tuesday"], "indexing with variables failed";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//test nested indexing
|
||||||
|
{
|
||||||
|
var a = [[[0]]];
|
||||||
|
|
||||||
|
a[0][0][0] = 42;
|
||||||
|
|
||||||
|
assert a[0][0] == [42], "nested indexing failed";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
print "All good";
|
print "All good";
|
||||||
|
|||||||
@@ -27,4 +27,17 @@
|
|||||||
assert d[first] == 2, "indexing with variables failed";
|
assert d[first] == 2, "indexing with variables failed";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//test nested indexing
|
||||||
|
{
|
||||||
|
var d = ["foo": ["bar": 0]];
|
||||||
|
|
||||||
|
d["foo"]["bar"] = 42;
|
||||||
|
|
||||||
|
print d;
|
||||||
|
|
||||||
|
assert d == ["foo": ["bar": 42]], "nested indexing failed";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
print "All good";
|
print "All good";
|
||||||
|
|||||||
@@ -267,7 +267,9 @@ static int writeLiteralToCompiler(Compiler* compiler, Literal literal) {
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Opcode 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
|
//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
|
||||||
|
//NODE: rootNode should NOT include groupings and blocks
|
||||||
|
static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAddressesPtr, void* continueAddressesPtr, int jumpOffsets, Node* rootNode) {
|
||||||
//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,7 +293,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
|||||||
|
|
||||||
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.)
|
||||||
Opcode override = writeCompilerWithJumps(compiler, node->unary.child, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
Opcode override = writeCompilerWithJumps(compiler, node->unary.child, breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode);
|
||||||
|
|
||||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||||
@@ -304,12 +306,12 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
|||||||
//all infixes come here
|
//all infixes come here
|
||||||
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.)
|
||||||
Opcode override = writeCompilerWithJumps(compiler, node->binary.left, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
Opcode override = writeCompilerWithJumps(compiler, node->binary.left, breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode);
|
||||||
|
|
||||||
//special case for when indexing and assigning
|
//special case for when indexing and assigning
|
||||||
if (override != OP_EOF && node->binary.opcode >= OP_VAR_ASSIGN && node->binary.opcode <= OP_VAR_MODULO_ASSIGN) {
|
if (override != OP_EOF && node->binary.opcode >= OP_VAR_ASSIGN && node->binary.opcode <= OP_VAR_MODULO_ASSIGN) {
|
||||||
writeCompilerWithJumps(compiler, node->binary.right, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
writeCompilerWithJumps(compiler, node->binary.right, breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode);
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)override + 1; //1 byte WARNING: enum arithmetic
|
compiler->bytecode[compiler->count++] = (unsigned char)OP_INDEX_ASSIGN; //1 byte WARNING: enum trickery
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)node->binary.opcode; //1 byte
|
compiler->bytecode[compiler->count++] = (unsigned char)node->binary.opcode; //1 byte
|
||||||
return OP_EOF;
|
return OP_EOF;
|
||||||
}
|
}
|
||||||
@@ -320,7 +322,11 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
|||||||
}
|
}
|
||||||
|
|
||||||
//return this if...
|
//return this if...
|
||||||
Opcode ret = writeCompilerWithJumps(compiler, node->binary.right, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
Opcode ret = writeCompilerWithJumps(compiler, node->binary.right, breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode);
|
||||||
|
|
||||||
|
if (node->binary.opcode == OP_INDEX && rootNode->type == NODE_BINARY && rootNode->binary.opcode == OP_VAR_ASSIGN) { //why var assign?
|
||||||
|
return OP_INDEX_ASSIGN_INTERMEDIATE;
|
||||||
|
}
|
||||||
|
|
||||||
//loopy logic - if opcode == index or dot
|
//loopy logic - if opcode == index or dot
|
||||||
if (node->binary.opcode == OP_INDEX || node->binary.opcode == OP_DOT) {
|
if (node->binary.opcode == OP_INDEX || node->binary.opcode == OP_DOT) {
|
||||||
@@ -340,7 +346,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* 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
|
||||||
Opcode override = writeCompilerWithJumps(compiler, node->grouping.child, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
Opcode override = writeCompilerWithJumps(compiler, node->grouping.child, breakAddressesPtr, continueAddressesPtr, jumpOffsets, node->grouping.child);
|
||||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||||
}
|
}
|
||||||
@@ -352,7 +358,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
|||||||
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++) {
|
||||||
Opcode override = writeCompilerWithJumps(compiler, &(node->block.nodes[i]), breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
Opcode override = writeCompilerWithJumps(compiler, &(node->block.nodes[i]), breakAddressesPtr, continueAddressesPtr, jumpOffsets, &(node->block.nodes[i]));
|
||||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||||
}
|
}
|
||||||
@@ -388,7 +394,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
|||||||
|
|
||||||
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)
|
||||||
Opcode override = writeCompilerWithJumps(compiler, node->varDecl.expression, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
Opcode override = writeCompilerWithJumps(compiler, node->varDecl.expression, breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode);
|
||||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||||
}
|
}
|
||||||
@@ -427,7 +433,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
|||||||
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
|
||||||
Opcode override = writeCompilerWithJumps(fnCompiler, node->fnDecl.block, NULL, NULL, -4); //can be empty, but not NULL
|
Opcode override = writeCompilerWithJumps(fnCompiler, node->fnDecl.block, NULL, NULL, -4, rootNode); //can be empty, but not NULL
|
||||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||||
}
|
}
|
||||||
@@ -480,7 +486,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
|||||||
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) {
|
||||||
Opcode override = writeCompilerWithJumps(compiler, &node->fnCall.arguments->fnCollection.nodes[i], breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
Opcode override = writeCompilerWithJumps(compiler, &node->fnCall.arguments->fnCollection.nodes[i], breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode);
|
||||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||||
}
|
}
|
||||||
@@ -536,7 +542,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
|||||||
|
|
||||||
case NODE_PATH_IF: {
|
case NODE_PATH_IF: {
|
||||||
//process the condition
|
//process the condition
|
||||||
Opcode override = writeCompilerWithJumps(compiler, node->path.condition, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
Opcode override = writeCompilerWithJumps(compiler, node->path.condition, breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode);
|
||||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||||
}
|
}
|
||||||
@@ -547,7 +553,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
|||||||
compiler->count += sizeof(unsigned short); //2 bytes
|
compiler->count += sizeof(unsigned short); //2 bytes
|
||||||
|
|
||||||
//write the then path
|
//write the then path
|
||||||
override = writeCompilerWithJumps(compiler, node->path.thenPath, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
override = writeCompilerWithJumps(compiler, node->path.thenPath, breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode);
|
||||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||||
}
|
}
|
||||||
@@ -566,7 +572,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
|||||||
|
|
||||||
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
|
||||||
Opcode override = writeCompilerWithJumps(compiler, node->path.elsePath, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
Opcode override = writeCompilerWithJumps(compiler, node->path.elsePath, breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode);
|
||||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||||
}
|
}
|
||||||
@@ -589,7 +595,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
|||||||
unsigned short jumpToStart = compiler->count;
|
unsigned short jumpToStart = compiler->count;
|
||||||
|
|
||||||
//process the condition
|
//process the condition
|
||||||
Opcode override = writeCompilerWithJumps(compiler, node->path.condition, &breakAddresses, &continueAddresses, jumpOffsets);
|
Opcode override = writeCompilerWithJumps(compiler, node->path.condition, &breakAddresses, &continueAddresses, jumpOffsets, rootNode);
|
||||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||||
}
|
}
|
||||||
@@ -600,7 +606,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
|||||||
compiler->count += sizeof(unsigned short); //2 bytes
|
compiler->count += sizeof(unsigned short); //2 bytes
|
||||||
|
|
||||||
//write the body
|
//write the body
|
||||||
override = writeCompilerWithJumps(compiler, node->path.thenPath, &breakAddresses, &continueAddresses, jumpOffsets);
|
override = writeCompilerWithJumps(compiler, node->path.thenPath, &breakAddresses, &continueAddresses, jumpOffsets, rootNode);
|
||||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||||
}
|
}
|
||||||
@@ -644,14 +650,14 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
|||||||
compiler->bytecode[compiler->count++] = OP_SCOPE_BEGIN; //1 byte
|
compiler->bytecode[compiler->count++] = OP_SCOPE_BEGIN; //1 byte
|
||||||
|
|
||||||
//initial setup
|
//initial setup
|
||||||
Opcode override = writeCompilerWithJumps(compiler, node->path.preClause, &breakAddresses, &continueAddresses, jumpOffsets);
|
Opcode override = writeCompilerWithJumps(compiler, node->path.preClause, &breakAddresses, &continueAddresses, jumpOffsets, rootNode);
|
||||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||||
}
|
}
|
||||||
|
|
||||||
//conditional
|
//conditional
|
||||||
unsigned short jumpToStart = compiler->count;
|
unsigned short jumpToStart = compiler->count;
|
||||||
override = writeCompilerWithJumps(compiler, node->path.condition, &breakAddresses, &continueAddresses, jumpOffsets);
|
override = writeCompilerWithJumps(compiler, node->path.condition, &breakAddresses, &continueAddresses, jumpOffsets, rootNode);
|
||||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||||
}
|
}
|
||||||
@@ -663,7 +669,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
|||||||
|
|
||||||
//write the body
|
//write the body
|
||||||
compiler->bytecode[compiler->count++] = OP_SCOPE_BEGIN; //1 byte
|
compiler->bytecode[compiler->count++] = OP_SCOPE_BEGIN; //1 byte
|
||||||
override = writeCompilerWithJumps(compiler, node->path.thenPath, &breakAddresses, &continueAddresses, jumpOffsets);
|
override = writeCompilerWithJumps(compiler, node->path.thenPath, &breakAddresses, &continueAddresses, jumpOffsets, rootNode);
|
||||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||||
}
|
}
|
||||||
@@ -673,7 +679,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
|||||||
int jumpToIncrement = compiler->count;
|
int jumpToIncrement = compiler->count;
|
||||||
|
|
||||||
//evaluate third clause, restart
|
//evaluate third clause, restart
|
||||||
override = writeCompilerWithJumps(compiler, node->path.postClause, &breakAddresses, &continueAddresses, jumpOffsets);
|
override = writeCompilerWithJumps(compiler, node->path.postClause, &breakAddresses, &continueAddresses, jumpOffsets, rootNode);
|
||||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||||
}
|
}
|
||||||
@@ -745,7 +751,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
|||||||
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++) {
|
||||||
Opcode override = writeCompilerWithJumps(compiler, &node->path.thenPath->fnCollection.nodes[i], breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
Opcode override = writeCompilerWithJumps(compiler, &node->path.thenPath->fnCollection.nodes[i], breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode);
|
||||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||||
}
|
}
|
||||||
@@ -829,7 +835,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
|||||||
writeLiteralToCompiler(compiler, TO_NULL_LITERAL);
|
writeLiteralToCompiler(compiler, TO_NULL_LITERAL);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Opcode override = writeCompilerWithJumps(compiler, node->index.first, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
Opcode override = writeCompilerWithJumps(compiler, node->index.first, breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode);
|
||||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||||
}
|
}
|
||||||
@@ -840,7 +846,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
|||||||
writeLiteralToCompiler(compiler, TO_NULL_LITERAL);
|
writeLiteralToCompiler(compiler, TO_NULL_LITERAL);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Opcode override = writeCompilerWithJumps(compiler, node->index.second, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
Opcode override = writeCompilerWithJumps(compiler, node->index.second, breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode);
|
||||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||||
}
|
}
|
||||||
@@ -851,7 +857,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
|||||||
writeLiteralToCompiler(compiler, TO_NULL_LITERAL);
|
writeLiteralToCompiler(compiler, TO_NULL_LITERAL);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Opcode override = writeCompilerWithJumps(compiler, node->index.third, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
Opcode override = writeCompilerWithJumps(compiler, node->index.third, breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode);
|
||||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||||
}
|
}
|
||||||
@@ -874,7 +880,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
|||||||
}
|
}
|
||||||
|
|
||||||
void writeCompiler(Compiler* compiler, Node* node) {
|
void writeCompiler(Compiler* compiler, Node* node) {
|
||||||
Opcode op = writeCompilerWithJumps(compiler, node, NULL, NULL, 0);
|
Opcode op = writeCompilerWithJumps(compiler, node, NULL, NULL, 0, node); //pass in "node" as the root node
|
||||||
|
|
||||||
if (op != OP_EOF) {//compensate for indexing & dot notation being screwy
|
if (op != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||||
compiler->bytecode[compiler->count++] = (unsigned char)op; //1 byte
|
compiler->bytecode[compiler->count++] = (unsigned char)op; //1 byte
|
||||||
|
|||||||
@@ -1397,7 +1397,7 @@ static bool execExport(Interpreter* interpreter) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool execIndex(Interpreter* interpreter) {
|
static bool execIndex(Interpreter* interpreter, bool assignIntermediate) {
|
||||||
//assume -> compound, first, second, third are all on the stack
|
//assume -> compound, first, second, third are all on the stack
|
||||||
|
|
||||||
Literal third = popLiteralArray(&interpreter->stack);
|
Literal third = popLiteralArray(&interpreter->stack);
|
||||||
@@ -1405,19 +1405,11 @@ static bool execIndex(Interpreter* interpreter) {
|
|||||||
Literal first = popLiteralArray(&interpreter->stack);
|
Literal first = popLiteralArray(&interpreter->stack);
|
||||||
Literal compound = popLiteralArray(&interpreter->stack);
|
Literal compound = popLiteralArray(&interpreter->stack);
|
||||||
|
|
||||||
if (!IS_IDENTIFIER(compound)) {
|
|
||||||
interpreter->errorOutput("Unknown literal found in indexing notation\n");
|
|
||||||
printLiteralCustom(compound, interpreter->errorOutput);
|
|
||||||
interpreter->errorOutput("\n");
|
|
||||||
freeLiteral(third);
|
|
||||||
freeLiteral(second);
|
|
||||||
freeLiteral(first);
|
|
||||||
freeLiteral(compound);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Literal idn = compound;
|
Literal idn = compound;
|
||||||
|
bool freeIdn = false;
|
||||||
|
|
||||||
|
if (IS_IDENTIFIER(compound)) {
|
||||||
|
freeIdn = true;
|
||||||
if (!parseIdentifierToValue(interpreter, &compound)) {
|
if (!parseIdentifierToValue(interpreter, &compound)) {
|
||||||
freeLiteral(third);
|
freeLiteral(third);
|
||||||
freeLiteral(second);
|
freeLiteral(second);
|
||||||
@@ -1426,6 +1418,7 @@ static bool execIndex(Interpreter* interpreter) {
|
|||||||
//freeLiteral(idn); //since compound is freed, idn is still pointing there
|
//freeLiteral(idn); //since compound is freed, idn is still pointing there
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!IS_ARRAY(compound) && !IS_DICTIONARY(compound) && !IS_STRING(compound)) {
|
if (!IS_ARRAY(compound) && !IS_DICTIONARY(compound) && !IS_STRING(compound)) {
|
||||||
interpreter->errorOutput("Unknown compound found in indexing notation\n");
|
interpreter->errorOutput("Unknown compound found in indexing notation\n");
|
||||||
@@ -1433,7 +1426,9 @@ static bool execIndex(Interpreter* interpreter) {
|
|||||||
freeLiteral(second);
|
freeLiteral(second);
|
||||||
freeLiteral(first);
|
freeLiteral(first);
|
||||||
freeLiteral(compound);
|
freeLiteral(compound);
|
||||||
|
if (freeIdn) {
|
||||||
freeLiteral(idn);
|
freeLiteral(idn);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1449,7 +1444,9 @@ static bool execIndex(Interpreter* interpreter) {
|
|||||||
freeLiteral(second);
|
freeLiteral(second);
|
||||||
freeLiteral(first);
|
freeLiteral(first);
|
||||||
freeLiteral(compound);
|
freeLiteral(compound);
|
||||||
|
if (freeIdn) {
|
||||||
freeLiteral(idn);
|
freeLiteral(idn);
|
||||||
|
}
|
||||||
freeLiteral(func);
|
freeLiteral(func);
|
||||||
freeLiteral(key);
|
freeLiteral(key);
|
||||||
return false;
|
return false;
|
||||||
@@ -1466,6 +1463,17 @@ static bool execIndex(Interpreter* interpreter) {
|
|||||||
pushLiteralArray(&arguments, TO_NULL_LITERAL); //it expects an assignment command
|
pushLiteralArray(&arguments, TO_NULL_LITERAL); //it expects an assignment command
|
||||||
pushLiteralArray(&arguments, TO_NULL_LITERAL); //it expects an assignment "opcode"
|
pushLiteralArray(&arguments, TO_NULL_LITERAL); //it expects an assignment "opcode"
|
||||||
|
|
||||||
|
//leave the idn and compound on the stack
|
||||||
|
if (assignIntermediate) {
|
||||||
|
if (IS_IDENTIFIER(idn)) {
|
||||||
|
pushLiteralArray(&interpreter->stack, idn);
|
||||||
|
}
|
||||||
|
pushLiteralArray(&interpreter->stack, compound);
|
||||||
|
pushLiteralArray(&interpreter->stack, first);
|
||||||
|
pushLiteralArray(&interpreter->stack, second);
|
||||||
|
pushLiteralArray(&interpreter->stack, third);
|
||||||
|
}
|
||||||
|
|
||||||
//call the function
|
//call the function
|
||||||
NativeFn fn = (NativeFn)AS_FUNCTION(func).bytecode;
|
NativeFn fn = (NativeFn)AS_FUNCTION(func).bytecode;
|
||||||
fn(interpreter, &arguments);
|
fn(interpreter, &arguments);
|
||||||
@@ -1475,7 +1483,9 @@ static bool execIndex(Interpreter* interpreter) {
|
|||||||
freeLiteral(second);
|
freeLiteral(second);
|
||||||
freeLiteral(first);
|
freeLiteral(first);
|
||||||
freeLiteral(compound);
|
freeLiteral(compound);
|
||||||
|
if (freeIdn) {
|
||||||
freeLiteral(idn);
|
freeLiteral(idn);
|
||||||
|
}
|
||||||
freeLiteral(func);
|
freeLiteral(func);
|
||||||
freeLiteral(key);
|
freeLiteral(key);
|
||||||
freeLiteralArray(&arguments);
|
freeLiteralArray(&arguments);
|
||||||
@@ -1492,20 +1502,11 @@ static bool execIndexAssign(Interpreter* interpreter) {
|
|||||||
Literal first = popLiteralArray(&interpreter->stack);
|
Literal first = popLiteralArray(&interpreter->stack);
|
||||||
Literal compound = popLiteralArray(&interpreter->stack);
|
Literal compound = popLiteralArray(&interpreter->stack);
|
||||||
|
|
||||||
if (!IS_IDENTIFIER(compound)) {
|
|
||||||
interpreter->errorOutput("Unknown literal found in index assigning notation\n");
|
|
||||||
printLiteralCustom(compound, interpreter->errorOutput);
|
|
||||||
interpreter->errorOutput("\n");
|
|
||||||
freeLiteral(assign);
|
|
||||||
freeLiteral(third);
|
|
||||||
freeLiteral(second);
|
|
||||||
freeLiteral(first);
|
|
||||||
freeLiteral(compound);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Literal idn = compound;
|
Literal idn = compound;
|
||||||
|
bool freeIdn = false;
|
||||||
|
|
||||||
|
if (IS_IDENTIFIER(compound)) {
|
||||||
|
freeIdn = true;
|
||||||
if (!parseIdentifierToValue(interpreter, &compound)) {
|
if (!parseIdentifierToValue(interpreter, &compound)) {
|
||||||
freeLiteral(assign);
|
freeLiteral(assign);
|
||||||
freeLiteral(third);
|
freeLiteral(third);
|
||||||
@@ -1515,6 +1516,7 @@ static bool execIndexAssign(Interpreter* interpreter) {
|
|||||||
freeLiteral(idn);
|
freeLiteral(idn);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!IS_ARRAY(compound) && !IS_DICTIONARY(compound) && !IS_STRING(compound)) {
|
if (!IS_ARRAY(compound) && !IS_DICTIONARY(compound) && !IS_STRING(compound)) {
|
||||||
interpreter->errorOutput("Unknown compound found in index assigning notation\n");
|
interpreter->errorOutput("Unknown compound found in index assigning notation\n");
|
||||||
@@ -1523,23 +1525,28 @@ static bool execIndexAssign(Interpreter* interpreter) {
|
|||||||
freeLiteral(second);
|
freeLiteral(second);
|
||||||
freeLiteral(first);
|
freeLiteral(first);
|
||||||
freeLiteral(compound);
|
freeLiteral(compound);
|
||||||
|
if (freeIdn) {
|
||||||
freeLiteral(idn);
|
freeLiteral(idn);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check const-ness of "first" within "compound"
|
//TODO: come back to this
|
||||||
Literal type = getScopeType(interpreter->scope, idn);
|
// //check const-ness of "first" within "compound"
|
||||||
if ((AS_TYPE(type).typeOf == LITERAL_ARRAY && AS_TYPE(((Literal*)(AS_TYPE(type).subtypes))[0]).constant) || (AS_TYPE(type).typeOf == LITERAL_DICTIONARY && AS_TYPE(((Literal*)(AS_TYPE(type).subtypes))[1]).constant)) {
|
// Literal type = getScopeType(interpreter->scope, idn);
|
||||||
interpreter->errorOutput("couldn't assign to constant within compound within index assigning notation\n");
|
// if ((AS_TYPE(type).typeOf == LITERAL_ARRAY && AS_TYPE(((Literal*)(AS_TYPE(type).subtypes))[0]).constant) || (AS_TYPE(type).typeOf == LITERAL_DICTIONARY && AS_TYPE(((Literal*)(AS_TYPE(type).subtypes))[1]).constant)) {
|
||||||
freeLiteral(assign);
|
// interpreter->errorOutput("couldn't assign to constant within compound within index assigning notation\n");
|
||||||
freeLiteral(third);
|
// freeLiteral(assign);
|
||||||
freeLiteral(second);
|
// freeLiteral(third);
|
||||||
freeLiteral(first);
|
// freeLiteral(second);
|
||||||
freeLiteral(compound);
|
// freeLiteral(first);
|
||||||
freeLiteral(idn);
|
// freeLiteral(compound);
|
||||||
freeLiteral(type);
|
// if (freeIdn) {
|
||||||
return false;
|
// freeLiteral(idn);
|
||||||
}
|
// }
|
||||||
|
// freeLiteral(type);
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
//get the index function
|
//get the index function
|
||||||
Literal func = TO_NULL_LITERAL;
|
Literal func = TO_NULL_LITERAL;
|
||||||
@@ -1554,8 +1561,10 @@ static bool execIndexAssign(Interpreter* interpreter) {
|
|||||||
freeLiteral(second);
|
freeLiteral(second);
|
||||||
freeLiteral(first);
|
freeLiteral(first);
|
||||||
freeLiteral(compound);
|
freeLiteral(compound);
|
||||||
|
if (freeIdn) {
|
||||||
freeLiteral(idn);
|
freeLiteral(idn);
|
||||||
freeLiteral(type);
|
}
|
||||||
|
// freeLiteral(type);
|
||||||
freeLiteral(func);
|
freeLiteral(func);
|
||||||
freeLiteral(key);
|
freeLiteral(key);
|
||||||
return false;
|
return false;
|
||||||
@@ -1591,8 +1600,10 @@ static bool execIndexAssign(Interpreter* interpreter) {
|
|||||||
freeLiteral(second);
|
freeLiteral(second);
|
||||||
freeLiteral(first);
|
freeLiteral(first);
|
||||||
freeLiteral(compound);
|
freeLiteral(compound);
|
||||||
|
if (freeIdn) {
|
||||||
freeLiteral(idn);
|
freeLiteral(idn);
|
||||||
freeLiteral(type);
|
}
|
||||||
|
// freeLiteral(type);
|
||||||
freeLiteral(func);
|
freeLiteral(func);
|
||||||
freeLiteral(key);
|
freeLiteral(key);
|
||||||
return false;
|
return false;
|
||||||
@@ -1618,7 +1629,49 @@ static bool execIndexAssign(Interpreter* interpreter) {
|
|||||||
|
|
||||||
//save the result (assume top of the interpreter stack is the new compound value)
|
//save the result (assume top of the interpreter stack is the new compound value)
|
||||||
Literal result = popLiteralArray(&interpreter->stack);
|
Literal result = popLiteralArray(&interpreter->stack);
|
||||||
if (!setScopeVariable(interpreter->scope, idn, result, true)) {//TODO: check this const-ness
|
|
||||||
|
//if idn is NOT an identifier, assign backwards while there are things on the stack (inner-compound assignment, BIG assumptions here)
|
||||||
|
if (!IS_IDENTIFIER(idn)) {
|
||||||
|
while (interpreter->stack.count > 1) {
|
||||||
|
//read the new values
|
||||||
|
freeLiteral(idn);
|
||||||
|
freeLiteral(third);
|
||||||
|
freeLiteral(second);
|
||||||
|
freeLiteral(first);
|
||||||
|
freeLiteralArray(&arguments);
|
||||||
|
initLiteralArray(&arguments);
|
||||||
|
freeLiteral(op);
|
||||||
|
|
||||||
|
third = popLiteralArray(&interpreter->stack);
|
||||||
|
second = popLiteralArray(&interpreter->stack);
|
||||||
|
first = popLiteralArray(&interpreter->stack);
|
||||||
|
idn = popLiteralArray(&interpreter->stack);
|
||||||
|
|
||||||
|
char* opStr = "="; //shadow, but force assignment
|
||||||
|
int opLength = strlen(opStr);
|
||||||
|
op = TO_STRING_LITERAL(copyString(opStr, opLength), opLength);
|
||||||
|
|
||||||
|
//assign to the idn / compound - with _index
|
||||||
|
pushLiteralArray(&arguments, idn);
|
||||||
|
pushLiteralArray(&arguments, first);
|
||||||
|
pushLiteralArray(&arguments, second);
|
||||||
|
pushLiteralArray(&arguments, third);
|
||||||
|
pushLiteralArray(&arguments, result);
|
||||||
|
pushLiteralArray(&arguments, op);
|
||||||
|
|
||||||
|
fn(interpreter, &arguments);
|
||||||
|
|
||||||
|
freeLiteral(result);
|
||||||
|
result = popLiteralArray(&interpreter->stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
freeLiteral(idn);
|
||||||
|
idn = popLiteralArray(&interpreter->stack);
|
||||||
|
compound = idn;
|
||||||
|
// freeIdn = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_IDENTIFIER(idn) && !setScopeVariable(interpreter->scope, idn, result, true)) {
|
||||||
interpreter->errorOutput("Incorrect type assigned to compound member: ");
|
interpreter->errorOutput("Incorrect type assigned to compound member: ");
|
||||||
printLiteralCustom(result, interpreter->errorOutput);
|
printLiteralCustom(result, interpreter->errorOutput);
|
||||||
interpreter->errorOutput("\n");
|
interpreter->errorOutput("\n");
|
||||||
@@ -1629,9 +1682,11 @@ static bool execIndexAssign(Interpreter* interpreter) {
|
|||||||
freeLiteral(second);
|
freeLiteral(second);
|
||||||
freeLiteral(first);
|
freeLiteral(first);
|
||||||
freeLiteral(compound);
|
freeLiteral(compound);
|
||||||
|
if (freeIdn) {
|
||||||
freeLiteral(idn);
|
freeLiteral(idn);
|
||||||
|
}
|
||||||
freeLiteral(func);
|
freeLiteral(func);
|
||||||
freeLiteral(type);
|
// freeLiteral(type);
|
||||||
freeLiteral(key);
|
freeLiteral(key);
|
||||||
freeLiteral(op);
|
freeLiteral(op);
|
||||||
freeLiteralArray(&arguments);
|
freeLiteralArray(&arguments);
|
||||||
@@ -1645,9 +1700,11 @@ static bool execIndexAssign(Interpreter* interpreter) {
|
|||||||
freeLiteral(second);
|
freeLiteral(second);
|
||||||
freeLiteral(first);
|
freeLiteral(first);
|
||||||
freeLiteral(compound);
|
freeLiteral(compound);
|
||||||
|
if (freeIdn) {
|
||||||
freeLiteral(idn);
|
freeLiteral(idn);
|
||||||
|
}
|
||||||
freeLiteral(func);
|
freeLiteral(func);
|
||||||
freeLiteral(type);
|
// freeLiteral(type);
|
||||||
freeLiteral(key);
|
freeLiteral(key);
|
||||||
freeLiteral(op);
|
freeLiteral(op);
|
||||||
freeLiteralArray(&arguments);
|
freeLiteralArray(&arguments);
|
||||||
@@ -1871,7 +1928,13 @@ static void execInterpreter(Interpreter* interpreter) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_INDEX:
|
case OP_INDEX:
|
||||||
if (!execIndex(interpreter)) {
|
if (!execIndex(interpreter, false)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OP_INDEX_ASSIGN_INTERMEDIATE:
|
||||||
|
if (!execIndex(interpreter, true)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ typedef enum Opcode {
|
|||||||
//for indexing
|
//for indexing
|
||||||
OP_INDEX,
|
OP_INDEX,
|
||||||
OP_INDEX_ASSIGN,
|
OP_INDEX_ASSIGN,
|
||||||
|
OP_INDEX_ASSIGN_INTERMEDIATE,
|
||||||
OP_DOT,
|
OP_DOT,
|
||||||
|
|
||||||
//comparison of values
|
//comparison of values
|
||||||
|
|||||||
Reference in New Issue
Block a user