#include "include/memory.h" #include "include/errors.h" #include "include/utils.h" #include "include/types.h" using namespace std; Memory::Memory(void) { scopes.emplace_back(); scopes.back().depth = 0; } bool Memory::contains(string identifier) { for (auto rit = scopes.rbegin(); rit != scopes.rend(); ++rit) { Scope& scope = *rit; if (scope.vars.contains(identifier)) return true; if (scope.type == ScopeType::Function) { Closure closure = std::get<1>(std::get(scope.fn->value)); if (closure.contains(identifier)) return true; break; } } return false; } bool Memory::contains_top(string identifier) { Scope& top = scopes.back(); return top.vars.contains(identifier); } void Memory::add_scope(ScopeType type, MemoryVar* fn, CodePosition entry_pos) { Scope& top = scopes.back(); Scope& newScope = scopes.emplace_back(); newScope.depth = top.depth + 1; newScope.type = type; newScope.fn = fn; newScope.entry_pos = entry_pos; } void Memory::remove_scope(void) { scopes.pop_back(); } MemoryVar& Memory::get(string identifier) { for (auto rit = scopes.rbegin(); rit != scopes.rend(); ++rit) { Scope& scope = *rit; if (scope.vars.contains(identifier)) return scope.vars[identifier]; if (scope.type == ScopeType::Function) { Closure closure = std::get<1>(std::get(scope.fn->value)); if (closure.contains(identifier)) return closure.at(identifier); break; } } throw exception(); } Scope& Memory::get_function_scope(void) { for (auto rit = scopes.rbegin(); rit != scopes.rend(); ++rit) { Scope& scope = *rit; if (scope.type == ScopeType::Function) return scope; } // Tmp: no flow control throw InternalError(); } void Memory::declare(string identifier, Type type) { Scope& top = scopes.back(); top.vars[identifier].type = type; top.vars[identifier].identifier = identifier; } void Memory::update(string identifier, EvalResult value) { for (auto rit = scopes.rbegin(); rit != scopes.rend(); ++rit) { Scope& scope = *rit; if (scope.vars.contains(identifier)) { scope.vars[identifier].value = value; scope.vars[identifier].initialized = true; return; } if (scope.type == ScopeType::Function) { Closure closure = std::get<1>(std::get(scope.fn->value)); if (closure.contains(identifier)) { MemoryVar& var = closure.at(identifier); var.value = value; var.initialized = true; } } } throw exception(); } Closure Memory::make_closure(void) { Closure closure; for (auto rit = scopes.rbegin(); rit != scopes.rend(); ++rit) { Scope& scope = *rit; for (auto& [identifier, var] : scope.vars) { if (!closure.contains(identifier)) closure.insert_or_assign(identifier, var); } } return closure; } StackTrace Memory::get_trace(CodePosition pos) { StackTrace trace = {}; for (auto rit = scopes.rbegin(); rit != scopes.rend(); ++rit) { Scope& scope = *rit; if (scope.type == ScopeType::Function) { StackTraceEntry entry = { scope.fn->identifier, pos }; trace.push_back(entry); pos = scope.entry_pos; } } StackTraceEntry top = { "", pos }; trace.push_back(top); return trace; } Scope& Memory::_debug_top(void) { Scope& top = scopes.back(); return top; } void _debug_print_memory_var(MemoryVar var) { if (var.initialized && !holds_alternative(var.value)) { cout << " "; if (holds_alternative(var.value)) { cout << get(var.value); } else if (holds_alternative(var.value)) { cout << get(var.value); } else { cout << "{Unsupported}"; } } else { cout << setw (5) << "{}"; } } void _debug_print_scope(Scope scope) { for (auto it : scope.vars) { if (it.first.length() > 6) { cout << it.first.substr(0, 6) << ".."; } else { cout << setw (6) << it.first << " "; } cout << "|"; cout << setw (7) << _debug_get_type_type_name(it.second.type.type) << " |"; _debug_print_memory_var(it.second); cout << endl; } } void Memory::_debug_print(void) { cout << BOLD " Name | Type | Value" RESET << endl; for (auto rit = scopes.rbegin(); rit != scopes.rend(); ++rit) { Scope& scope = *rit; if (rit != scopes.rbegin()) { cout << " --- New Scope ---" << endl; } _debug_print_scope(scope); } }