2024-01-12 14:10:23 +01:00
|
|
|
#include "include/memory.hpp"
|
|
|
|
#include "include/errors.hpp"
|
|
|
|
#include "include/utils.hpp"
|
|
|
|
#include "include/types.hpp"
|
2023-12-08 15:29:30 +01:00
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
Memory::Memory(void) {
|
2024-01-05 19:05:44 +01:00
|
|
|
make_global_scope();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Memory::make_global_scope(void) {
|
2023-12-08 15:29:30 +01:00
|
|
|
scopes.emplace_back();
|
2024-01-05 19:05:44 +01:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2023-12-08 15:29:30 +01:00
|
|
|
}
|
|
|
|
|
2024-01-05 19:05:44 +01:00
|
|
|
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);
|
|
|
|
};
|
|
|
|
|
2023-12-08 15:29:30 +01:00
|
|
|
bool Memory::contains(string identifier) {
|
|
|
|
for (auto rit = scopes.rbegin(); rit != scopes.rend(); ++rit) {
|
|
|
|
Scope& scope = *rit;
|
|
|
|
if (scope.vars.contains(identifier)) return true;
|
2024-01-04 21:53:47 +01:00
|
|
|
if (scope.type == ScopeType::Function) {
|
2024-01-05 19:05:44 +01:00
|
|
|
Closure closure = std::get<1>(std::get<UserFunction>(std::get<Function>(scope.fn->value)));
|
2024-01-04 21:53:47 +01:00
|
|
|
if (closure.contains(identifier)) return true;
|
|
|
|
break;
|
|
|
|
}
|
2023-12-08 15:29:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Memory::contains_top(string identifier) {
|
|
|
|
Scope& top = scopes.back();
|
|
|
|
return top.vars.contains(identifier);
|
|
|
|
}
|
|
|
|
|
2024-01-04 13:50:03 +01:00
|
|
|
void Memory::add_scope(ScopeType type, MemoryVar* fn, CodePosition entry_pos) {
|
2023-12-08 15:29:30 +01:00
|
|
|
Scope& top = scopes.back();
|
2024-01-10 15:42:30 +01:00
|
|
|
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;
|
2023-12-08 15:29:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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];
|
2024-01-04 21:53:47 +01:00
|
|
|
if (scope.type == ScopeType::Function) {
|
2024-01-05 19:05:44 +01:00
|
|
|
Closure closure = std::get<1>(std::get<UserFunction>(std::get<Function>(scope.fn->value)));
|
2024-01-04 21:53:47 +01:00
|
|
|
if (closure.contains(identifier)) return closure.at(identifier);
|
|
|
|
break;
|
|
|
|
}
|
2023-12-08 15:29:30 +01:00
|
|
|
}
|
|
|
|
|
2023-12-09 11:41:14 +01:00
|
|
|
throw exception();
|
2023-12-08 15:29:30 +01:00
|
|
|
}
|
|
|
|
|
2024-01-03 11:51:31 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-01-03 15:52:41 +01:00
|
|
|
// Tmp: no flow control
|
2024-01-03 12:48:11 +01:00
|
|
|
throw InternalError();
|
2024-01-03 11:51:31 +01:00
|
|
|
}
|
|
|
|
|
2024-01-03 20:30:37 +01:00
|
|
|
void Memory::declare(string identifier, Type type) {
|
2023-12-08 15:29:30 +01:00
|
|
|
Scope& top = scopes.back();
|
|
|
|
top.vars[identifier].type = type;
|
2024-01-04 13:50:03 +01:00
|
|
|
top.vars[identifier].identifier = identifier;
|
2023-12-08 15:29:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2024-01-04 22:07:57 +01:00
|
|
|
if (scope.type == ScopeType::Function) {
|
2024-01-05 19:05:44 +01:00
|
|
|
Closure closure = std::get<1>(std::get<UserFunction>(std::get<Function>(scope.fn->value)));
|
2024-01-04 22:07:57 +01:00
|
|
|
if (closure.contains(identifier)) {
|
|
|
|
MemoryVar& var = closure.at(identifier);
|
|
|
|
var.value = value;
|
|
|
|
var.initialized = true;
|
|
|
|
}
|
|
|
|
}
|
2023-12-08 15:29:30 +01:00
|
|
|
}
|
|
|
|
|
2023-12-09 11:41:14 +01:00
|
|
|
throw exception();
|
2023-12-08 15:29:30 +01:00
|
|
|
}
|
|
|
|
|
2024-01-04 21:53:47 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-01-04 13:50:03 +01:00
|
|
|
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) {
|
2024-01-04 21:53:47 +01:00
|
|
|
StackTraceEntry entry = { scope.fn->identifier, pos };
|
2024-01-04 13:50:03 +01:00
|
|
|
trace.push_back(entry);
|
|
|
|
pos = scope.entry_pos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
StackTraceEntry top = { "<repl>", pos };
|
|
|
|
trace.push_back(top);
|
|
|
|
|
|
|
|
return trace;
|
|
|
|
}
|
|
|
|
|
2024-01-05 19:05:44 +01:00
|
|
|
void Memory::_debug_clear(void) {
|
|
|
|
scopes.clear();
|
|
|
|
make_global_scope();
|
|
|
|
}
|
|
|
|
|
2023-12-08 15:29:30 +01:00
|
|
|
Scope& Memory::_debug_top(void) {
|
|
|
|
Scope& top = scopes.back();
|
|
|
|
return top;
|
2023-12-09 12:27:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
2024-01-10 11:50:13 +01:00
|
|
|
if (it.first.length() > 14) {
|
|
|
|
cout << it.first.substr(0, 14) << "..";
|
2023-12-09 12:27:59 +01:00
|
|
|
} else {
|
2024-01-10 11:50:13 +01:00
|
|
|
cout << setw (14) << it.first << " ";
|
2023-12-09 12:27:59 +01:00
|
|
|
}
|
|
|
|
cout << "|";
|
2024-01-12 15:40:03 +01:00
|
|
|
cout << setw (9) << type_type_to_string(it.second.type.type) << " |";
|
2023-12-09 12:27:59 +01:00
|
|
|
|
|
|
|
_debug_print_memory_var(it.second);
|
|
|
|
cout << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Memory::_debug_print(void) {
|
2024-01-10 11:50:13 +01:00
|
|
|
cout << BOLD " Name | Type | Value" RESET << endl;
|
2023-12-09 12:27:59 +01:00
|
|
|
for (auto rit = scopes.rbegin(); rit != scopes.rend(); ++rit) {
|
|
|
|
Scope& scope = *rit;
|
|
|
|
if (rit != scopes.rbegin()) {
|
|
|
|
cout << " --- New Scope ---" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
_debug_print_scope(scope);
|
|
|
|
}
|
2023-12-08 15:29:30 +01:00
|
|
|
}
|