Fixed nested assignment bug

This commit is contained in:
2022-09-09 17:55:23 +01:00
parent f8747d8707
commit 4b99ce2fb6
7 changed files with 192 additions and 97 deletions

View File

@@ -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: maximum recursion/function depth
DONE: better sugar for _push, _pop, _length
DONE: nested compound assignment bug
TODO: nested compound assignment
TODO: ternary operator?
TODO: Nullish types?
TODO: hooks on the external libraries, triggered on import

View File

@@ -1,10 +1,11 @@
//test nested indexing
{
var a = [[[0]]];
fn loop(count) {
print count++;
loop(count);
a[0][0][0] = 42;
print a;
assert a[0][0] == [42], "nested indexing failed";
}
loop(0);

View File

@@ -61,4 +61,15 @@
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";

View File

@@ -27,4 +27,17 @@
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";

View File

@@ -267,7 +267,9 @@ static int writeLiteralToCompiler(Compiler* compiler, Literal literal) {
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
if (compiler->count + 32 > compiler->capacity) {
int oldCapacity = compiler->capacity;
@@ -291,7 +293,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
case NODE_UNARY: {
//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
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
case NODE_BINARY: {
//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
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);
compiler->bytecode[compiler->count++] = (unsigned char)override + 1; //1 byte WARNING: enum arithmetic
writeCompilerWithJumps(compiler, node->binary.right, breakAddressesPtr, continueAddressesPtr, jumpOffsets, rootNode);
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
return OP_EOF;
}
@@ -320,7 +322,11 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
}
//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
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: {
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
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
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
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: {
//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
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
}
@@ -427,7 +433,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
initCompiler(fnCompiler);
writeCompiler(fnCompiler, node->fnDecl.arguments); //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
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
//sub-calls
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
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: {
//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
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
//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
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 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
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;
//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
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
//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
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
//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
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
}
//conditional
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
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
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
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;
//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
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: {
//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++) {
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
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);
}
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
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);
}
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
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);
}
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
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) {
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
compiler->bytecode[compiler->count++] = (unsigned char)op; //1 byte

View File

@@ -1397,7 +1397,7 @@ static bool execExport(Interpreter* interpreter) {
return true;
}
static bool execIndex(Interpreter* interpreter) {
static bool execIndex(Interpreter* interpreter, bool assignIntermediate) {
//assume -> compound, first, second, third are all on the stack
Literal third = popLiteralArray(&interpreter->stack);
@@ -1405,26 +1405,19 @@ static bool execIndex(Interpreter* interpreter) {
Literal first = 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;
bool freeIdn = false;
if (!parseIdentifierToValue(interpreter, &compound)) {
freeLiteral(third);
freeLiteral(second);
freeLiteral(first);
freeLiteral(compound);
//freeLiteral(idn); //since compound is freed, idn is still pointing there
return false;
if (IS_IDENTIFIER(compound)) {
freeIdn = true;
if (!parseIdentifierToValue(interpreter, &compound)) {
freeLiteral(third);
freeLiteral(second);
freeLiteral(first);
freeLiteral(compound);
//freeLiteral(idn); //since compound is freed, idn is still pointing there
return false;
}
}
if (!IS_ARRAY(compound) && !IS_DICTIONARY(compound) && !IS_STRING(compound)) {
@@ -1433,7 +1426,9 @@ static bool execIndex(Interpreter* interpreter) {
freeLiteral(second);
freeLiteral(first);
freeLiteral(compound);
freeLiteral(idn);
if (freeIdn) {
freeLiteral(idn);
}
return false;
}
@@ -1449,7 +1444,9 @@ static bool execIndex(Interpreter* interpreter) {
freeLiteral(second);
freeLiteral(first);
freeLiteral(compound);
freeLiteral(idn);
if (freeIdn) {
freeLiteral(idn);
}
freeLiteral(func);
freeLiteral(key);
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 "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
NativeFn fn = (NativeFn)AS_FUNCTION(func).bytecode;
fn(interpreter, &arguments);
@@ -1475,7 +1483,9 @@ static bool execIndex(Interpreter* interpreter) {
freeLiteral(second);
freeLiteral(first);
freeLiteral(compound);
freeLiteral(idn);
if (freeIdn) {
freeLiteral(idn);
}
freeLiteral(func);
freeLiteral(key);
freeLiteralArray(&arguments);
@@ -1492,28 +1502,20 @@ static bool execIndexAssign(Interpreter* interpreter) {
Literal first = 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;
bool freeIdn = false;
if (!parseIdentifierToValue(interpreter, &compound)) {
freeLiteral(assign);
freeLiteral(third);
freeLiteral(second);
freeLiteral(first);
freeLiteral(compound);
freeLiteral(idn);
return false;
if (IS_IDENTIFIER(compound)) {
freeIdn = true;
if (!parseIdentifierToValue(interpreter, &compound)) {
freeLiteral(assign);
freeLiteral(third);
freeLiteral(second);
freeLiteral(first);
freeLiteral(compound);
freeLiteral(idn);
return false;
}
}
if (!IS_ARRAY(compound) && !IS_DICTIONARY(compound) && !IS_STRING(compound)) {
@@ -1523,23 +1525,28 @@ static bool execIndexAssign(Interpreter* interpreter) {
freeLiteral(second);
freeLiteral(first);
freeLiteral(compound);
freeLiteral(idn);
if (freeIdn) {
freeLiteral(idn);
}
return false;
}
//check const-ness of "first" within "compound"
Literal type = getScopeType(interpreter->scope, idn);
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)) {
interpreter->errorOutput("couldn't assign to constant within compound within index assigning notation\n");
freeLiteral(assign);
freeLiteral(third);
freeLiteral(second);
freeLiteral(first);
freeLiteral(compound);
freeLiteral(idn);
freeLiteral(type);
return false;
}
//TODO: come back to this
// //check const-ness of "first" within "compound"
// Literal type = getScopeType(interpreter->scope, idn);
// 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)) {
// interpreter->errorOutput("couldn't assign to constant within compound within index assigning notation\n");
// freeLiteral(assign);
// freeLiteral(third);
// freeLiteral(second);
// freeLiteral(first);
// freeLiteral(compound);
// if (freeIdn) {
// freeLiteral(idn);
// }
// freeLiteral(type);
// return false;
// }
//get the index function
Literal func = TO_NULL_LITERAL;
@@ -1554,8 +1561,10 @@ static bool execIndexAssign(Interpreter* interpreter) {
freeLiteral(second);
freeLiteral(first);
freeLiteral(compound);
freeLiteral(idn);
freeLiteral(type);
if (freeIdn) {
freeLiteral(idn);
}
// freeLiteral(type);
freeLiteral(func);
freeLiteral(key);
return false;
@@ -1591,8 +1600,10 @@ static bool execIndexAssign(Interpreter* interpreter) {
freeLiteral(second);
freeLiteral(first);
freeLiteral(compound);
freeLiteral(idn);
freeLiteral(type);
if (freeIdn) {
freeLiteral(idn);
}
// freeLiteral(type);
freeLiteral(func);
freeLiteral(key);
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)
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: ");
printLiteralCustom(result, interpreter->errorOutput);
interpreter->errorOutput("\n");
@@ -1629,9 +1682,11 @@ static bool execIndexAssign(Interpreter* interpreter) {
freeLiteral(second);
freeLiteral(first);
freeLiteral(compound);
freeLiteral(idn);
if (freeIdn) {
freeLiteral(idn);
}
freeLiteral(func);
freeLiteral(type);
// freeLiteral(type);
freeLiteral(key);
freeLiteral(op);
freeLiteralArray(&arguments);
@@ -1645,9 +1700,11 @@ static bool execIndexAssign(Interpreter* interpreter) {
freeLiteral(second);
freeLiteral(first);
freeLiteral(compound);
freeLiteral(idn);
if (freeIdn) {
freeLiteral(idn);
}
freeLiteral(func);
freeLiteral(type);
// freeLiteral(type);
freeLiteral(key);
freeLiteral(op);
freeLiteralArray(&arguments);
@@ -1871,7 +1928,13 @@ static void execInterpreter(Interpreter* interpreter) {
break;
case OP_INDEX:
if (!execIndex(interpreter)) {
if (!execIndex(interpreter, false)) {
return;
}
break;
case OP_INDEX_ASSIGN_INTERMEDIATE:
if (!execIndex(interpreter, true)) {
return;
}
break;

View File

@@ -51,6 +51,7 @@ typedef enum Opcode {
//for indexing
OP_INDEX,
OP_INDEX_ASSIGN,
OP_INDEX_ASSIGN_INTERMEDIATE,
OP_DOT,
//comparison of values