Files
Toy/source/scope.c

94 lines
2.0 KiB
C

#include "scope.h"
#include "memory.h"
//run up the ancestor chain, freeing anything with 0 references left
static void freeAncestorChain(Scope* scope) {
scope->references--;
//free scope chain
if (scope->ancestor != NULL) {
freeAncestorChain(scope->ancestor);
}
if (scope->references > 0) {
return;
}
freeLiteralDictionary(&scope->variables);
freeLiteralDictionary(&scope->types);
FREE(Scope, scope);
}
//exposed functions
Scope* pushScope(Scope* ancestor) {
Scope* scope = ALLOCATE(Scope, 1);
scope->ancestor = ancestor;
initLiteralDictionary(&scope->variables);
initLiteralDictionary(&scope->types);
//tick up all scope reference counts
scope->references = 0;
for (Scope* ptr = scope; ptr; ptr = ptr->ancestor) {
ptr->references++;
}
return scope;
}
Scope* popScope(Scope* scope) {
Scope* ret = scope->ancestor;
freeAncestorChain(scope);
return ret;
}
//returns false if error
bool declareScopeVariable(Scope* scope, Literal key, Literal type) {
//store the type, for later checking on assignment
setLiteralDictionary(&scope->types, key, type);
//don't redefine a variable within this scope
if (existsLiteralDictionary(&scope->variables, key)) {
return false;
}
setLiteralDictionary(&scope->variables, key, TO_NULL_LITERAL);
return true;
}
//return false if undefined
bool setScopeVariable(Scope* scope, Literal key, Literal value) {
//dead end
if (scope == NULL) {
return false;
}
//TODO: type checking
//if it's not in this scope, keep searching up the chain
if (!existsLiteralDictionary(&scope->variables, key)) {
return setScopeVariable(scope->ancestor, key, value);
}
setLiteralDictionary(&scope->variables, key, value);
return true;
}
bool getScopeVariable(Scope* scope, Literal key, Literal* valueHandle) {
//dead end
if (scope == NULL) {
return false;
}
//if it's not in this scope, keep searching up the chain
if (!existsLiteralDictionary(&scope->variables, key)) {
return getScopeVariable(scope->ancestor, key, valueHandle);
}
*valueHandle = getLiteralDictionary(&scope->variables, key);
return true;
}