Scoping now works
This commit is contained in:
@@ -22,3 +22,27 @@ SolsVariable* findSolsVariable(SolsScope* scope, const char* name) {
|
||||
HASH_FIND_STR(scope->variables, name, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
SolsScope copySolsScope(SolsScope* scope) {
|
||||
SolsScope newScope = {
|
||||
.variables = NULL,
|
||||
.tmpCounter = scope->tmpCounter
|
||||
};
|
||||
|
||||
SolsVariable *var, *tmp;
|
||||
|
||||
HASH_ITER(hh, scope->variables, var, tmp) {
|
||||
addVariableToScope(&newScope, var->id, var->typeinfo);
|
||||
}
|
||||
|
||||
return newScope;
|
||||
}
|
||||
|
||||
void destroySolsScope(SolsScope* scope) {
|
||||
SolsVariable *var, *tmp;
|
||||
|
||||
HASH_ITER(hh, scope->variables, var, tmp) {
|
||||
HASH_DEL(scope->variables, var);
|
||||
free(var);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,4 +22,10 @@ void addVariableToScope(SolsScope* scope, const char* name, SolsType type);
|
||||
// Finds a variable in the SolsScope.
|
||||
SolsVariable* findSolsVariable(SolsScope* scope, const char* name);
|
||||
|
||||
// Deep copies a SolsScope, usually for being inside a code block
|
||||
SolsScope copySolsScope(SolsScope* scope);
|
||||
|
||||
// Destroys everything in the SolsScope
|
||||
void destroySolsScope(SolsScope* scope);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -202,6 +202,11 @@ static inline ResultType(GroundProgram, charptr) generatePutsNode(SolsNode* node
|
||||
}
|
||||
GroundInstruction inst = groundCreateInstruction(PRINTLN);
|
||||
for (size_t i = 0; i < node->children.count; i++) {
|
||||
// Validate arg
|
||||
ResultType(SolsType, charptr) type = getNodeType(&node->children.at[i], scope);
|
||||
if (type.error) {
|
||||
return Error(GroundProgram, charptr, type.as.error);
|
||||
}
|
||||
groundAddReferenceToInstruction(&inst, node->children.at[i].accessArg);
|
||||
}
|
||||
GroundProgram program = groundCreateProgram();
|
||||
@@ -216,7 +221,7 @@ static inline ResultType(GroundProgram, charptr) generateSetNode(SolsNode* node,
|
||||
if (node->children.at[0].type != SNT_IDENTIFIER) {
|
||||
return Error(GroundProgram, charptr, "set requires an identifier before '='");
|
||||
}
|
||||
SolsVariable* var = findSolsVariable(scope, node->as.idName);
|
||||
SolsVariable* var = findSolsVariable(scope, node->children.at[0].as.idName);
|
||||
ResultType(SolsType, charptr) type = getNodeType(&node->children.at[1], scope);
|
||||
if (type.error) {
|
||||
return Error(GroundProgram, charptr, type.as.error);
|
||||
@@ -232,7 +237,6 @@ static inline ResultType(GroundProgram, charptr) generateSetNode(SolsNode* node,
|
||||
return Error(GroundProgram, charptr, "Type of variable cannot be changed");
|
||||
}
|
||||
}
|
||||
addVariableToScope(scope, node->children.at[0].as.idName, type.as.success);
|
||||
|
||||
GroundProgram gp = groundCreateProgram();
|
||||
GroundInstruction gi = groundCreateInstruction(SET);
|
||||
@@ -664,7 +668,14 @@ ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope
|
||||
|
||||
GroundProgram program = groundCreateProgram();
|
||||
|
||||
SolsScope backupScope = {NULL, 0};
|
||||
|
||||
if (node->type != SNT_IF && node->type != SNT_WHILE) {
|
||||
if (node->type == SNT_CODE_BLOCK) {
|
||||
backupScope = *scope;
|
||||
SolsScope newScope = copySolsScope(scope);
|
||||
*scope = newScope;
|
||||
}
|
||||
// Generate code for all children before generating this node's code
|
||||
for (size_t i = 0; i < node->children.count; i++) {
|
||||
ResultType(GroundProgram, charptr) generated = generateCode(&node->children.at[i], scope);
|
||||
@@ -675,6 +686,10 @@ ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope
|
||||
groundAddInstructionToProgram(&program, generated.as.success.instructions[j]);
|
||||
}
|
||||
}
|
||||
if (node->type == SNT_CODE_BLOCK) {
|
||||
destroySolsScope(scope);
|
||||
*scope = backupScope;
|
||||
}
|
||||
}
|
||||
|
||||
// Now generate code for this node
|
||||
|
||||
Reference in New Issue
Block a user