From bba2e812c48034744a27326b50dcd7048d2515b4 Mon Sep 17 00:00:00 2001 From: ala89 Date: Fri, 5 Jan 2024 19:05:44 +0100 Subject: [PATCH] Add standard functions --- src/analysis.cpp | 4 +-- src/include/memory.h | 4 +++ src/include/types.h | 15 ++++++++--- src/interpreter.cpp | 62 ++++++++++++++++++++++++-------------------- src/memory.cpp | 46 ++++++++++++++++++++++++++++---- 5 files changed, 92 insertions(+), 39 deletions(-) diff --git a/src/analysis.cpp b/src/analysis.cpp index 6db13d6..77db96b 100644 --- a/src/analysis.cpp +++ b/src/analysis.cpp @@ -362,12 +362,12 @@ AnalysisResult analyze(Node &ast, Memory &memory) { memory.declare(function_name, type); Node empty_node = {}; - Function fn = { empty_node, memory.make_closure() }; + UserFunction fn = { empty_node, memory.make_closure() }; memory.update(function_name, fn); memory.add_scope(ScopeType::Function, &memory.get(function_name)); - for (tuple variable : prototype) { + for (ArgDefinition variable : prototype) { Type vtype = get<0>(variable); string vname = get<1>(variable); diff --git a/src/include/memory.h b/src/include/memory.h index cae14c7..9fc69c3 100644 --- a/src/include/memory.h +++ b/src/include/memory.h @@ -25,12 +25,16 @@ class Memory { StackTrace get_trace(CodePosition pos); + void _debug_clear(void); Scope& _debug_top(void); void _debug_print(void); Memory(void); private: + void make_global_scope(void); + void make_standard_fn(string identifier, InternalCall call, FunctionPrototype prototype); + list scopes; }; diff --git a/src/include/types.h b/src/include/types.h index 6aeb1fa..33c15c0 100644 --- a/src/include/types.h +++ b/src/include/types.h @@ -20,7 +20,8 @@ enum class TypeType { Int, Double, Void, Function }; -using FunctionPrototype = vector>; +using ArgDefinition = tuple; +using FunctionPrototype = vector; using TypeData = variant; struct Type { @@ -171,12 +172,12 @@ enum class NodeType { Return, // -> Return ; | Return Expr ; }; -struct InnerNode; - /** * InnerNode: noeud interne * Token: feuille */ +struct InnerNode; + using Node = variant; /** @@ -205,7 +206,13 @@ struct ParseReturn { struct MemoryVar; using Closure = unordered_map>; -using Function = tuple; +using UserFunction = tuple; + +enum class InternalCall { + ClearMemory, DumpMemory, DumpHistory +}; + +using Function = variant; using EvalResult = variant; diff --git a/src/interpreter.cpp b/src/interpreter.cpp index 89a68f2..0c4473d 100644 --- a/src/interpreter.cpp +++ b/src/interpreter.cpp @@ -173,7 +173,7 @@ EvalResult eval(Node &ast, Memory &memory) { .data = prototype }); - Function fn = { node.children[3], memory.make_closure() }; + UserFunction fn = { node.children[3], memory.make_closure() }; memory.update(identifier, fn); @@ -189,45 +189,51 @@ EvalResult eval(Node &ast, Memory &memory) { if (!var.initialized) throw RuntimeError(ErrorType::UninitializedIdentifier, identifierTok.pos, memory.get_trace(identifierTok.pos), identifier); + Function& fn = get(var.value); + FunctionPrototype& prototype = get(var.type.data); + vector argValues = {}; for (Node arg : args) { argValues.push_back(eval(arg, memory)); } - FunctionPrototype prototype = get(var.type.data); - EvalResult res = {}; - memory.add_scope(ScopeType::Function, &var, identifierTok.pos); - - try { - for (size_t i = 1; i < prototype.size(); i++) { - tuple argDef = prototype[i]; - Type argType = get<0>(argDef); - string argName = get<1>(argDef); - memory.declare(argName, argType); - memory.update(argName, cast_from_type(argType, argValues[i - 1])); - } + if (holds_alternative(fn)) { + memory.add_scope(ScopeType::Function, &var, identifierTok.pos); try { - eval(get<0>(get(var.value)), memory); - - // Tmp: no flow control - if (get<0>(prototype[0]).type != TypeType::Void) { - throw ControlError(ErrorType::ControlReachesEndOfNonVoidFn, identifierTok.pos); + for (size_t i = 1; i < prototype.size(); i++) { + ArgDefinition argDef = prototype[i]; + Type argType = get<0>(argDef); + string argName = get<1>(argDef); + memory.declare(argName, argType); + memory.update(argName, cast_from_type(argType, argValues[i - 1])); } - } - catch (const ReturnException& e) { - res = e.val; - } - memory.remove_scope(); + try { + eval(get<0>(get(fn)), memory); + + // Tmp: no flow control + if (get<0>(prototype[0]).type != TypeType::Void) { + throw ControlError(ErrorType::ControlReachesEndOfNonVoidFn, identifierTok.pos); + } + } + catch (const ReturnException& e) { + res = e.val; + } + + memory.remove_scope(); + } + catch (...) { + memory.remove_scope(); + + exception_ptr e = current_exception(); + if (e) rethrow_exception(e); + } } - catch (...) { - memory.remove_scope(); - - exception_ptr e = current_exception(); - if (e) rethrow_exception(e); + else { + memory._debug_clear(); } return cast_from_type(get<0>(prototype[0]), res); diff --git a/src/memory.cpp b/src/memory.cpp index 1f3f620..d47dd6e 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -5,16 +5,47 @@ using namespace std; Memory::Memory(void) { - scopes.emplace_back(); - scopes.back().depth = 0; + 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(scope.fn->value)); + Closure closure = std::get<1>(std::get(std::get(scope.fn->value))); if (closure.contains(identifier)) return true; break; } @@ -46,7 +77,7 @@ MemoryVar& Memory::get(string identifier) { 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)); + Closure closure = std::get<1>(std::get(std::get(scope.fn->value))); if (closure.contains(identifier)) return closure.at(identifier); break; } @@ -80,7 +111,7 @@ void Memory::update(string identifier, EvalResult value) { return; } if (scope.type == ScopeType::Function) { - Closure closure = std::get<1>(std::get(scope.fn->value)); + Closure closure = std::get<1>(std::get(std::get(scope.fn->value))); if (closure.contains(identifier)) { MemoryVar& var = closure.at(identifier); var.value = value; @@ -123,6 +154,11 @@ StackTrace Memory::get_trace(CodePosition pos) { return trace; } +void Memory::_debug_clear(void) { + scopes.clear(); + make_global_scope(); +} + Scope& Memory::_debug_top(void) { Scope& top = scopes.back(); return top;