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);
|
HASH_FIND_STR(scope->variables, name, s);
|
||||||
return 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.
|
// Finds a variable in the SolsScope.
|
||||||
SolsVariable* findSolsVariable(SolsScope* scope, const char* name);
|
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
|
#endif
|
||||||
|
|||||||
@@ -202,6 +202,11 @@ static inline ResultType(GroundProgram, charptr) generatePutsNode(SolsNode* node
|
|||||||
}
|
}
|
||||||
GroundInstruction inst = groundCreateInstruction(PRINTLN);
|
GroundInstruction inst = groundCreateInstruction(PRINTLN);
|
||||||
for (size_t i = 0; i < node->children.count; i++) {
|
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);
|
groundAddReferenceToInstruction(&inst, node->children.at[i].accessArg);
|
||||||
}
|
}
|
||||||
GroundProgram program = groundCreateProgram();
|
GroundProgram program = groundCreateProgram();
|
||||||
@@ -216,7 +221,7 @@ static inline ResultType(GroundProgram, charptr) generateSetNode(SolsNode* node,
|
|||||||
if (node->children.at[0].type != SNT_IDENTIFIER) {
|
if (node->children.at[0].type != SNT_IDENTIFIER) {
|
||||||
return Error(GroundProgram, charptr, "set requires an identifier before '='");
|
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);
|
ResultType(SolsType, charptr) type = getNodeType(&node->children.at[1], scope);
|
||||||
if (type.error) {
|
if (type.error) {
|
||||||
return Error(GroundProgram, charptr, type.as.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");
|
return Error(GroundProgram, charptr, "Type of variable cannot be changed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addVariableToScope(scope, node->children.at[0].as.idName, type.as.success);
|
|
||||||
|
|
||||||
GroundProgram gp = groundCreateProgram();
|
GroundProgram gp = groundCreateProgram();
|
||||||
GroundInstruction gi = groundCreateInstruction(SET);
|
GroundInstruction gi = groundCreateInstruction(SET);
|
||||||
@@ -664,7 +668,14 @@ ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope
|
|||||||
|
|
||||||
GroundProgram program = groundCreateProgram();
|
GroundProgram program = groundCreateProgram();
|
||||||
|
|
||||||
|
SolsScope backupScope = {NULL, 0};
|
||||||
|
|
||||||
if (node->type != SNT_IF && node->type != SNT_WHILE) {
|
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
|
// Generate code for all children before generating this node's code
|
||||||
for (size_t i = 0; i < node->children.count; i++) {
|
for (size_t i = 0; i < node->children.count; i++) {
|
||||||
ResultType(GroundProgram, charptr) generated = generateCode(&node->children.at[i], scope);
|
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]);
|
groundAddInstructionToProgram(&program, generated.as.success.instructions[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (node->type == SNT_CODE_BLOCK) {
|
||||||
|
destroySolsScope(scope);
|
||||||
|
*scope = backupScope;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now generate code for this node
|
// Now generate code for this node
|
||||||
|
|||||||
Reference in New Issue
Block a user