c-repl/src/memory.cpp

207 lines
5.8 KiB
C++

#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<UserFunction>(std::get<Function>(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<UserFunction>(std::get<Function>(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<UserFunction>(std::get<Function>(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 = { "<repl>", 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<monostate>(var.value)) {
cout << " ";
if (holds_alternative<int>(var.value)) {
cout << get<int>(var.value);
} else if (holds_alternative<double>(var.value)) {
cout << get<double>(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);
}
}