diff --git a/src/codegen/SolsScope.c b/src/codegen/SolsScope.c index 23db7db..ad696ea 100644 --- a/src/codegen/SolsScope.c +++ b/src/codegen/SolsScope.c @@ -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); + } +} diff --git a/src/codegen/SolsScope.h b/src/codegen/SolsScope.h index 0fd2eeb..7b0d025 100644 --- a/src/codegen/SolsScope.h +++ b/src/codegen/SolsScope.h @@ -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 diff --git a/src/codegen/codegen.c b/src/codegen/codegen.c index 2262fbf..7ec2867 100644 --- a/src/codegen/codegen.c +++ b/src/codegen/codegen.c @@ -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