#include "include/memory.hpp" #include "include/errors.hpp" #include "include/utils.hpp" #include "include/types.hpp" using namespace std; Memory::Memory(void) { make_global_scope(); } void Memory::make_global_scope(void) { scopes.emplace_back(); Scope& global = scopes.back(); global.depth = 0; { FunctionPrototype proto = { { type_type_to_type(TypeType::Void), "" } }; make_standard_fn("clear_memory", InternalCall::ClearMemory, proto); } { FunctionPrototype proto = { { type_type_to_type(TypeType::Void), "" } }; make_standard_fn("dump_memory", InternalCall::DumpMemory, proto); } { FunctionPrototype proto = { { type_type_to_type(TypeType::Void), "" } }; make_standard_fn("dump_history", InternalCall::DumpHistory, proto); } } void Memory::make_standard_fn(string identifier, InternalCall call, FunctionPrototype prototype) { Type type = { .type = TypeType::Function, .data = prototype }; declare(identifier, type); update(identifier, (Function) call); }; 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(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& new_scope = scopes.emplace_back(); new_scope.depth = top.depth + 1; new_scope.type = type; new_scope.fn = fn; new_scope.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(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(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; } void Memory::_debug_clear(void) { scopes.clear(); make_global_scope(); } 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() > 14) { cout << it.first.substr(0, 14) << ".."; } else { cout << setw (14) << it.first << " "; } cout << "|"; cout << setw (9) << _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); } }