diff --git a/include/Value/function.hpp b/include/Value/function.hpp index 48741f3..9218edf 100644 --- a/include/Value/function.hpp +++ b/include/Value/function.hpp @@ -24,6 +24,8 @@ namespace Fig std::shared_ptr closureContext; + FunctionStruct() = default; + FunctionStruct(Ast::FunctionParameters _paras, TypeInfo _retType, Ast::BlockStatement _body, ContextPtr _closureContext) : id(nextId()), // εˆ†ι…ε”―δΈ€ ID paras(std::move(_paras)), diff --git a/include/context.hpp b/include/context.hpp index fab559d..3fbb2dc 100644 --- a/include/context.hpp +++ b/include/context.hpp @@ -18,6 +18,8 @@ namespace Fig std::unordered_map variables; std::unordered_map ams; + std::unordered_map functions; + std::unordered_map functionNames; public: ContextPtr parent; @@ -113,13 +115,52 @@ namespace Fig } void def(const FString &name, const TypeInfo &ti, AccessModifier am, const Value &value = Any()) { - if (variables.contains(name)) + if (containsInThisScope(name)) { throw RuntimeError(FStringView(std::format("Variable '{}' already defined in this scope", name.toBasicString()))); } variables[name] = value; varTypes[name] = ti; ams[name] = am; + + if (ti == ValueType::Function and value.getTypeInfo() == ValueType::Function) + { + auto &fn = value.as().getValue(); + functions[fn.id] = fn; + functionNames[fn.id] = name; + } + } + std::optional getFunction(std::size_t id) + { + auto it = functions.find(id); + if (it != functions.end()) + { + return it->second; + } + else if (parent) + { + return parent->getFunction(id); + } + else + { + return std::nullopt; + } + } + std::optional getFunctionName(std::size_t id) + { + auto it = functionNames.find(id); + if (it != functionNames.end()) + { + return it->second; + } + else if (parent) + { + return parent->getFunctionName(id); + } + else + { + return std::nullopt; + } } bool contains(const FString &name) { @@ -133,6 +174,11 @@ namespace Fig } return false; } + bool containsInThisScope(const FString &name) const + { + return variables.contains(name); + } + TypeInfo getTypeInfo(const FString &name) { if (varTypes.contains(name)) diff --git a/include/parser.hpp b/include/parser.hpp index 700b0ff..a104086 100644 --- a/include/parser.hpp +++ b/include/parser.hpp @@ -33,18 +33,18 @@ namespace Fig class SemicolonDisabler { - Parser &p; + Parser *p; bool original; public: - SemicolonDisabler(Parser &parser) : - p(parser), original(p.needSemicolon) + SemicolonDisabler(Parser *parser) : + p(parser), original(p->needSemicolon) { - p.needSemicolon = false; + p->needSemicolon = false; } ~SemicolonDisabler() { - p.needSemicolon = original; + p->needSemicolon = original; } // disable copy and assign SemicolonDisabler(const SemicolonDisabler &) = delete; @@ -253,7 +253,7 @@ namespace Fig [[nodiscard]] SemicolonDisabler disableSemicolon() { - return SemicolonDisabler(*this); + return SemicolonDisabler(this); } void expectSemicolon() diff --git a/src/main.cpp b/src/main.cpp index 3fb1f49..ea09af2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -169,6 +169,12 @@ int main(int argc, char **argv) evaluator.printStackTrace(); return 1; } + catch (const std::exception &e) + { + std::cerr << "uncaught exception of: " << e.what() << '\n'; + evaluator.printStackTrace(); + return 1; + } // try // { diff --git a/test.fig b/test.fig index f5748aa..33bbd94 100644 --- a/test.fig +++ b/test.fig @@ -1,6 +1,9 @@ -const println := __fstdout_println; - -for var i=0;i<10;i=i+1 +var call := 0; +func t() { - println("Loop ", i); -} \ No newline at end of file + call = call + 1; + __fstdout_println(call); + t(); +} + +t(); \ No newline at end of file