From c83b0616e24eb41dab082724686919c184251548 Mon Sep 17 00:00:00 2001 From: Piotr Fusik Date: Mon, 25 Mar 2024 11:47:47 +0100 Subject: [PATCH] [ctfe] Fix forward-referenced methods. --- AST.fu | 2 +- Sema.fu | 6 +++++- libfut.cpp | 8 ++++++-- libfut.cs | 6 +++++- libfut.hpp | 2 +- libfut.js | 4 ++++ test/ConstForwardMethod.fu | 9 +++++++++ 7 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 test/ConstForwardMethod.fu diff --git a/AST.fu b/AST.fu index ec63b10d..3dc8936e 100644 --- a/AST.fu +++ b/AST.fu @@ -1198,7 +1198,7 @@ public class FuMethodBase : FuMember { internal FuParameters() Parameters; internal List() Throws; - internal FuStatement#? Body; + internal FuScope#? Body; internal bool IsLive = false; internal HashSet() Calls; public override bool IsStatic() => false; // constructor diff --git a/Sema.fu b/Sema.fu index 132b32fa..70c0b23d 100644 --- a/Sema.fu +++ b/Sema.fu @@ -1357,7 +1357,7 @@ public class FuSema symbol.Symbol = method; if (method.CallType == FuCallType.Static - && method.Body is FuReturn ret + && method.Body is FuReturn! ret && arguments.All(arg => arg is FuLiteral) && !this.CurrentPureMethods.Contains(method)) { this.CurrentPureMethods.Add(method); @@ -1368,7 +1368,11 @@ public class FuSema else this.CurrentPureArguments[param] = param.Value; } + FuScope! callSite = this.CurrentScope; + ret.Parent = method.Parameters; + this.CurrentScope = ret; FuExpr# result = VisitExpr(ret.Value); + this.CurrentScope = callSite; for (FuVar? param = method.FirstParameter(); param != null; param = param.NextVar()) this.CurrentPureArguments.Remove(param); this.CurrentPureMethods.Remove(method); diff --git a/libfut.cpp b/libfut.cpp index 8afbe588..5c9b4104 100644 --- a/libfut.cpp +++ b/libfut.cpp @@ -5730,8 +5730,8 @@ std::shared_ptr FuSema::resolveCallWithArguments(std::shared_ptrname)); } symbol->symbol = method; - const FuReturn * ret; - if (method->callType == FuCallType::static_ && (ret = dynamic_cast(method->body.get())) && std::all_of(arguments->begin(), arguments->end(), [](const std::shared_ptr &arg) { return dynamic_cast(arg.get()); }) && !this->currentPureMethods.contains(method)) { + FuReturn * ret; + if (method->callType == FuCallType::static_ && (ret = dynamic_cast(method->body.get())) && std::all_of(arguments->begin(), arguments->end(), [](const std::shared_ptr &arg) { return dynamic_cast(arg.get()); }) && !this->currentPureMethods.contains(method)) { this->currentPureMethods.insert(method); i = 0; for (const FuVar * param = method->firstParameter(); param != nullptr; param = param->nextVar()) { @@ -5740,7 +5740,11 @@ std::shared_ptr FuSema::resolveCallWithArguments(std::shared_ptrcurrentPureArguments[param] = param->value; } + FuScope * callSite = this->currentScope; + ret->parent = &method->parameters; + this->currentScope = ret; std::shared_ptr result = visitExpr(ret->value); + this->currentScope = callSite; for (const FuVar * param = method->firstParameter(); param != nullptr; param = param->nextVar()) this->currentPureArguments.erase(param); this->currentPureMethods.erase(method); diff --git a/libfut.cs b/libfut.cs index c1525150..12910fca 100644 --- a/libfut.cs +++ b/libfut.cs @@ -2738,7 +2738,7 @@ public class FuMethodBase : FuMember internal readonly List Throws = new List(); - internal FuStatement Body; + internal FuScope Body; internal bool IsLive = false; @@ -5852,7 +5852,11 @@ FuExpr ResolveCallWithArguments(FuCallExpr expr, List arguments) else this.CurrentPureArguments[param] = param.Value; } + FuScope callSite = this.CurrentScope; + ret.Parent = method.Parameters; + this.CurrentScope = ret; FuExpr result = VisitExpr(ret.Value); + this.CurrentScope = callSite; for (FuVar param = method.FirstParameter(); param != null; param = param.NextVar()) this.CurrentPureArguments.Remove(param); this.CurrentPureMethods.Remove(method); diff --git a/libfut.hpp b/libfut.hpp index 9db9ce34..ef3e26ec 100644 --- a/libfut.hpp +++ b/libfut.hpp @@ -1301,7 +1301,7 @@ class FuMethodBase : public FuMember public: FuParameters parameters; std::vector> throws; - std::shared_ptr body; + std::shared_ptr body; bool isLive = false; std::unordered_set calls; }; diff --git a/libfut.js b/libfut.js index 5188c080..19e4c829 100644 --- a/libfut.js +++ b/libfut.js @@ -6153,7 +6153,11 @@ export class FuSema else this.#currentPureArguments[param] = param.value; } + let callSite = this.#currentScope; + ret.parent = method.parameters; + this.#currentScope = ret; let result = this.#visitExpr(ret.value); + this.#currentScope = callSite; for (let param = method.firstParameter(); param != null; param = param.nextVar()) delete this.#currentPureArguments[param]; this.#currentPureMethods.delete(method); diff --git a/test/ConstForwardMethod.fu b/test/ConstForwardMethod.fu new file mode 100644 index 00000000..923950fb --- /dev/null +++ b/test/ConstForwardMethod.fu @@ -0,0 +1,9 @@ +public static class Test +{ + public static bool Run() + { + return Foo(42); + } + + static bool Foo(int answer) => answer == 42; +}