diff --git a/source/interpreter.c b/source/interpreter.c index dd2d61c..3833a14 100644 --- a/source/interpreter.c +++ b/source/interpreter.c @@ -1531,23 +1531,6 @@ static bool execIndexAssign(Interpreter* interpreter) { 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; char* keyStr = "_index"; @@ -1564,7 +1547,6 @@ static bool execIndexAssign(Interpreter* interpreter) { if (freeIdn) { freeLiteral(idn); } - // freeLiteral(type); freeLiteral(func); freeLiteral(key); return false; @@ -1603,7 +1585,6 @@ static bool execIndexAssign(Interpreter* interpreter) { if (freeIdn) { freeLiteral(idn); } - // freeLiteral(type); freeLiteral(func); freeLiteral(key); return false; @@ -1668,12 +1649,11 @@ static bool execIndexAssign(Interpreter* interpreter) { 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("Incorrect type assigned to compound member "); + printLiteralCustom(idn, interpreter->errorOutput); interpreter->errorOutput("\n"); //clean up @@ -1686,7 +1666,6 @@ static bool execIndexAssign(Interpreter* interpreter) { freeLiteral(idn); } freeLiteral(func); - // freeLiteral(type); freeLiteral(key); freeLiteral(op); freeLiteralArray(&arguments); @@ -1704,7 +1683,6 @@ static bool execIndexAssign(Interpreter* interpreter) { freeLiteral(idn); } freeLiteral(func); - // freeLiteral(type); freeLiteral(key); freeLiteral(op); freeLiteralArray(&arguments); diff --git a/source/scope.c b/source/scope.c index 2c4df07..f1edf37 100644 --- a/source/scope.c +++ b/source/scope.c @@ -22,7 +22,12 @@ static void freeAncestorChain(Scope* scope) { } //return false if invalid type -static bool checkType(Literal typeLiteral, Literal value) { +static bool checkType(Literal typeLiteral, Literal original, Literal value, bool constCheck) { + //for constants, fail if original != value + if (constCheck && AS_TYPE(typeLiteral).constant && !literalsAreEqual(original, value)) { + return false; + } + //for any types if (AS_TYPE(typeLiteral).typeOf == LITERAL_ANY) { return true; @@ -65,9 +70,18 @@ static bool checkType(Literal typeLiteral, Literal value) { return false; } + //if null, assume it's a new entry + if (IS_NULL(original)) { + return true; + } + //check children for (int i = 0; i < AS_ARRAY(value)->count; i++) { - if (!checkType(((Literal*)(AS_TYPE(typeLiteral).subtypes))[0], AS_ARRAY(value)->literals[i])) { + if (AS_ARRAY(original)->count <= i) { + return true; //assume new entry pushed + } + + if (!checkType(((Literal*)(AS_TYPE(typeLiteral).subtypes))[0], AS_ARRAY(original)->literals[i], AS_ARRAY(value)->literals[i], constCheck)) { return false; } } @@ -83,18 +97,40 @@ static bool checkType(Literal typeLiteral, Literal value) { return false; } - //check children - for (int i = 0; i < AS_DICTIONARY(value)->capacity; i++) { - //only assigned and non-tombstoned keys - if (!IS_NULL(AS_DICTIONARY(value)->entries[i].key)) { - if (!checkType(((Literal*)(AS_TYPE(typeLiteral).subtypes))[0], AS_DICTIONARY(value)->entries[i].key)) { - return false; - } + //if null, assume it's a new entry + if (IS_NULL(original)) { + return true; + } - if (!checkType(((Literal*)(AS_TYPE(typeLiteral).subtypes))[1], AS_DICTIONARY(value)->entries[i].value)) { - return false; + //check each child of value against the child of original + for (int i = 0; i < AS_DICTIONARY(value)->capacity; i++) { + if (IS_NULL(AS_DICTIONARY(value)->entries[i].key)) { //only non-tombstones + continue; + } + + //find the internal child of original that matches this child of value + _entry* ptr = NULL; + + for (int j = 0; j < AS_DICTIONARY(original)->capacity; j++) { + if (literalsAreEqual(AS_DICTIONARY(original)->entries[j].key, AS_DICTIONARY(value)->entries[i].key)) { + ptr = &AS_DICTIONARY(original)->entries[j]; + break; } } + + //if not found, assume it's a new entry + if (!ptr) { + continue; + } + + //check the type of key and value + if (!checkType(((Literal*)(AS_TYPE(typeLiteral).subtypes))[0], ptr->key, AS_DICTIONARY(value)->entries[i].key, constCheck)) { + return false; + } + + if (!checkType(((Literal*)(AS_TYPE(typeLiteral).subtypes))[1], ptr->value, AS_DICTIONARY(value)->entries[i].value, constCheck)) { + return false; + } } } @@ -220,15 +256,11 @@ bool setScopeVariable(Scope* scope, Literal key, Literal value, bool constCheck) //type checking Literal typeLiteral = getLiteralDictionary(&scope->types, key); + Literal original = getLiteralDictionary(&scope->variables, key); - if (!checkType(typeLiteral, value)) { - freeLiteral(typeLiteral); - return false; - } - - //const check - if (constCheck && (AS_TYPE(typeLiteral).constant)) { + if (!checkType(typeLiteral, original, value, constCheck)) { freeLiteral(typeLiteral); + freeLiteral(original); return false; } @@ -236,6 +268,7 @@ bool setScopeVariable(Scope* scope, Literal key, Literal value, bool constCheck) setLiteralDictionary(&scope->variables, key, value); freeLiteral(typeLiteral); + freeLiteral(original); return true; }