From 50b56363ec542e82adc382141061c5f3bab9d37c Mon Sep 17 00:00:00 2001 From: LIU Hao Date: Mon, 4 Dec 2023 13:12:14 +0800 Subject: [PATCH] instantiated_function: Remove zero-ary variadic arguers --- asteria/runtime/air_optimizer.cpp | 4 +-- asteria/runtime/executive_context.cpp | 39 ++++++++--------------- asteria/runtime/executive_context.hpp | 14 ++++---- asteria/runtime/instantiated_function.cpp | 20 ++++++------ asteria/runtime/instantiated_function.hpp | 22 +++++++++---- asteria/runtime/reference.cpp | 6 ++-- asteria/runtime/variadic_arguer.hpp | 23 ++----------- 7 files changed, 52 insertions(+), 76 deletions(-) diff --git a/asteria/runtime/air_optimizer.cpp b/asteria/runtime/air_optimizer.cpp index 266463fde..4f2abfddd 100644 --- a/asteria/runtime/air_optimizer.cpp +++ b/asteria/runtime/air_optimizer.cpp @@ -91,9 +91,7 @@ create_function(const Source_Location& sloc, stringR name) } // Instantiate the function object now. - return ::rocket::make_refcnt(this->m_params, - ::rocket::make_refcnt(sloc, ::std::move(func)), - this->m_code); + return ::rocket::make_refcnt(sloc, func, this->m_params, this->m_code); } } // namespace asteria diff --git a/asteria/runtime/executive_context.cpp b/asteria/runtime/executive_context.cpp index 2c2edb11b..f38b79d3b 100644 --- a/asteria/runtime/executive_context.cpp +++ b/asteria/runtime/executive_context.cpp @@ -4,53 +4,52 @@ #include "../precompiled.ipp" #include "executive_context.hpp" #include "runtime_error.hpp" -#include "../runtime/runtime_error.hpp" #include "ptc_arguments.hpp" #include "enums.hpp" #include "variable.hpp" +#include "instantiated_function.hpp" #include "../llds/avm_rod.hpp" #include "../llds/reference_stack.hpp" #include "../utils.hpp" namespace asteria { Executive_Context:: -Executive_Context(M_function, Global_Context& global, Reference_Stack& stack, - Reference_Stack& alt_stack, const refcnt_ptr& zvarg, - const cow_vector& params, Reference&& self) +Executive_Context(M_function, Global_Context& xglobal, Reference_Stack& xstack, + Reference_Stack& ystack, const Instantiated_Function& xfunc, + Reference&& xself) : - m_parent_opt(nullptr), m_global(&global), m_stack(&stack), - m_alt_stack(&alt_stack), m_zvarg(zvarg) + m_parent_opt(nullptr), m_global(&xglobal), m_stack(&xstack), m_alt_stack(&ystack), m_func(&xfunc) { // Set the `this` reference, but only if it is a variable or non-null. When // `this` is null, it is likely that it is never referenced in the function, // so lazy initialization is performed to avoid the overhead here. - if(!self.is_invalid()) - this->do_mut_named_reference(nullptr, sref("__this")) = ::std::move(self); + if(!xself.is_invalid()) + this->do_mut_named_reference(nullptr, sref("__this")) = ::std::move(xself); // Set arguments. Because arguments are evaluated from left to right, the // reference at the top is the last argument. - uint32_t nargs = stack.size(); + uint32_t nargs = this->m_stack->size(); bool has_ellipsis = false; - for(const auto& name : params) + for(const auto& name : this->m_func->params()) if(name != sref("...")) { // Try popping an argument and assign it. auto& param = this->do_mut_named_reference(nullptr, name); if(nargs == 0) param.set_temporary(nullopt); else - param = ::std::move(stack.mut_top(--nargs)); + param = ::std::move(this->m_stack->mut_top(--nargs)); } else has_ellipsis = true; if(!has_ellipsis && (nargs != 0)) throw Runtime_Error(Runtime_Error::M_format(), - "Too many arguments passed to `$1`", zvarg->func()); + "Too many arguments passed to `$1`", this->m_func->func()); // Move all arguments into the variadic argument getter. while(nargs != 0) - this->m_lazy_args.emplace_back(::std::move(stack.mut_top(--nargs))); + this->m_lazy_args.emplace_back(::std::move(this->m_stack->mut_top(--nargs))); } Executive_Context:: @@ -70,23 +69,13 @@ do_create_lazy_reference_opt(Reference* hint_opt, phsh_stringR name) const if(name == sref("__func")) { auto& ref = this->do_mut_named_reference(hint_opt, name); - - // Note: This can only happen inside a function context. - ref.set_temporary(this->m_zvarg->func()); + ref.set_temporary(this->m_func->func()); return &ref; } if(name == sref("__varg")) { auto& ref = this->do_mut_named_reference(hint_opt, name); - - // Use the zero-ary argument getter if there is variadic argument. - // Create a new one otherwise. - auto varg = this->m_zvarg; - if(!this->m_lazy_args.empty()) - varg = ::rocket::make_refcnt(*varg, this->m_lazy_args); - - // Note: This can only happen inside a function context. - ref.set_temporary(::std::move(varg)); + ref.set_temporary(::rocket::make_refcnt(*(this->m_func), this->m_lazy_args)); return &ref; } diff --git a/asteria/runtime/executive_context.hpp b/asteria/runtime/executive_context.hpp index 04e7c6675..4aa403c4f 100644 --- a/asteria/runtime/executive_context.hpp +++ b/asteria/runtime/executive_context.hpp @@ -23,7 +23,7 @@ class Executive_Context Reference_Stack* m_alt_stack; // for nested calls cow_bivector m_defer; - refcnt_ptr m_zvarg; + const Instantiated_Function* m_func = nullptr; cow_vector m_lazy_args; public: @@ -41,19 +41,19 @@ class Executive_Context // contexts of enclosing function will have been destroyed. ASTERIA_INCOMPLET(AVM_Rod) explicit - Executive_Context(M_defer, Global_Context& global, Reference_Stack& stack, - Reference_Stack& alt_stack) + Executive_Context(M_defer, Global_Context& xglobal, Reference_Stack& xstack, + Reference_Stack& ystack) : - m_parent_opt(nullptr), m_global(&global), m_stack(&stack), m_alt_stack(&alt_stack) + m_parent_opt(nullptr), m_global(&xglobal), m_stack(&xstack), m_alt_stack(&ystack) { } // A function context has no parent. // The caller shall define a global context and evaluation stack, both of which // shall outlast this context. explicit - Executive_Context(M_function, Global_Context& global, Reference_Stack& stack, - Reference_Stack& alt_stack, const refcnt_ptr& zvarg, - const cow_vector& params, Reference&& self); + Executive_Context(M_function, Global_Context& xglobal, Reference_Stack& xstack, + Reference_Stack& ystack, const Instantiated_Function& xfunc, + Reference&& xself); private: bool diff --git a/asteria/runtime/instantiated_function.cpp b/asteria/runtime/instantiated_function.cpp index 678734424..f9e3dfb1a 100644 --- a/asteria/runtime/instantiated_function.cpp +++ b/asteria/runtime/instantiated_function.cpp @@ -15,10 +15,10 @@ namespace asteria { Instantiated_Function:: -Instantiated_Function(const cow_vector& params, refcnt_ptr&& zvarg, - const cow_vector& code) +Instantiated_Function(const Source_Location& xsloc, const cow_string& xfunc, + const cow_vector& xparams, const cow_vector& code) : - m_params(params), m_zvarg(::std::move(zvarg)) + m_sloc(xsloc), m_func(xfunc), m_params(xparams) { ::rocket::for_each(code, [&](const AIR_Node& node) { node.solidify(this->m_rod); }); this->m_rod.finalize(); @@ -33,7 +33,7 @@ tinyfmt& Instantiated_Function:: describe(tinyfmt& fmt) const { - return fmt << "`" << this->m_zvarg->func() << "` at '" << this->m_zvarg->sloc() << "'"; + return format(fmt, "`$1` at '$2'", this->m_func, this->m_sloc); } void @@ -49,10 +49,8 @@ invoke_ptc_aware(Reference& self, Global_Context& global, Reference_Stack&& stac { // Create the stack and context for this function. Reference_Stack alt_stack; - Executive_Context ctx_func(Executive_Context::M_function(), global, stack, alt_stack, - this->m_zvarg, this->m_params, ::std::move(self)); - - ASTERIA_CALL_GLOBAL_HOOK(global, on_function_enter, ctx_func, *this, this->m_zvarg->sloc()); + Executive_Context ctx_func(Executive_Context::M_function(), global, stack, alt_stack, *this, ::std::move(self)); + ASTERIA_CALL_GLOBAL_HOOK(global, on_function_enter, ctx_func, *this, this->m_sloc); // Execute the function body, using `stack` for evaluation. AIR_Status status; @@ -61,8 +59,8 @@ invoke_ptc_aware(Reference& self, Global_Context& global, Reference_Stack&& stac } catch(Runtime_Error& except) { ctx_func.on_scope_exit_exceptional(except); - except.push_frame_function(this->m_zvarg->sloc(), this->m_zvarg->func()); - ASTERIA_CALL_GLOBAL_HOOK(global, on_function_except, ctx_func, *this, this->m_zvarg->sloc(), except); + except.push_frame_function(this->m_sloc, this->m_func); + ASTERIA_CALL_GLOBAL_HOOK(global, on_function_except, ctx_func, *this, this->m_sloc, except); throw; } ctx_func.on_scope_exit_normal(status); @@ -99,7 +97,7 @@ invoke_ptc_aware(Reference& self, Global_Context& global, Reference_Stack&& stac ASTERIA_TERMINATE(("Corrupted enumeration `$1`"), status); } - ASTERIA_CALL_GLOBAL_HOOK(global, on_function_return, ctx_func, *this, this->m_zvarg->sloc(), self); + ASTERIA_CALL_GLOBAL_HOOK(global, on_function_return, ctx_func, *this, this->m_sloc, self); return self; } diff --git a/asteria/runtime/instantiated_function.hpp b/asteria/runtime/instantiated_function.hpp index cb6186503..934423fb1 100644 --- a/asteria/runtime/instantiated_function.hpp +++ b/asteria/runtime/instantiated_function.hpp @@ -5,7 +5,6 @@ #define ASTERIA_RUNTIME_INSTANTIATED_FUNCTION_ #include "../fwd.hpp" -#include "variadic_arguer.hpp" #include "../llds/avm_rod.hpp" namespace asteria { @@ -14,21 +13,30 @@ class Instantiated_Function final public Abstract_Function { private: + Source_Location m_sloc; + cow_string m_func; cow_vector m_params; - refcnt_ptr m_zvarg; AVM_Rod m_rod; public: explicit - Instantiated_Function(const cow_vector& params, refcnt_ptr&& zvarg, - const cow_vector& code); + Instantiated_Function(const Source_Location& xsloc, const cow_string& xfunc, + const cow_vector& xparams, const cow_vector& code); public: ASTERIA_NONCOPYABLE_DESTRUCTOR(Instantiated_Function); - const refcnt_ptr& - zvarg() const noexcept - { return this->m_zvarg; } + const Source_Location& + sloc() const noexcept + { return this->m_sloc; } + + const cow_string& + func() const noexcept + { return this->m_func; } + + const cow_vector& + params() const noexcept + { return this->m_params; } tinyfmt& describe(tinyfmt& fmt) const override; diff --git a/asteria/runtime/reference.cpp b/asteria/runtime/reference.cpp index 4cba999c3..035e59f44 100644 --- a/asteria/runtime/reference.cpp +++ b/asteria/runtime/reference.cpp @@ -243,7 +243,7 @@ do_use_function_result_slow(Global_Context& global) // Leave this frame. if(caller) ASTERIA_CALL_GLOBAL_HOOK(global, on_function_return, defer_ctx, *caller, - caller->zvarg()->sloc(), *this); + caller->sloc(), *this); } } catch(Runtime_Error& except) { @@ -259,7 +259,7 @@ do_use_function_result_slow(Global_Context& global) except.push_frame_plain(ptcg->sloc(), sref("[proper tail call]")); if(caller) - except.push_frame_function(caller->zvarg()->sloc(), caller->zvarg()->func()); + except.push_frame_function(caller->sloc(), caller->func()); // Evaluate deferred expressions. defer_ctx.stack() = ::std::move(ptcg->mut_stack()); @@ -269,7 +269,7 @@ do_use_function_result_slow(Global_Context& global) // Leave this frame. if(caller) ASTERIA_CALL_GLOBAL_HOOK(global, on_function_except, defer_ctx, *caller, - caller->zvarg()->sloc(), except); + caller->sloc(), except); } // The exception object has been updated, so rethrow it. diff --git a/asteria/runtime/variadic_arguer.hpp b/asteria/runtime/variadic_arguer.hpp index b7bc19d90..3632c4a1a 100644 --- a/asteria/runtime/variadic_arguer.hpp +++ b/asteria/runtime/variadic_arguer.hpp @@ -6,6 +6,7 @@ #include "../fwd.hpp" #include "reference.hpp" +#include "instantiated_function.hpp" #include "../source_location.hpp" namespace asteria { @@ -21,15 +22,9 @@ class Variadic_Arguer final public: explicit - Variadic_Arguer(const Source_Location& xsloc, stringR xfunc) + Variadic_Arguer(const Instantiated_Function& xfunc, const cow_vector& xvargs) : - m_sloc(xsloc), m_func(xfunc) - { } - - explicit - Variadic_Arguer(const Variadic_Arguer& other, const cow_vector& xvargs) - : - m_sloc(other.m_sloc), m_func(other.m_func), m_vargs(xvargs) + m_sloc(xfunc.sloc()), m_func(xfunc.func()), m_vargs(xvargs) { } public: @@ -37,18 +32,6 @@ class Variadic_Arguer final sloc() const noexcept { return this->m_sloc; } - const cow_string& - file() const noexcept - { return this->m_sloc.file(); } - - int - line() const noexcept - { return this->m_sloc.line(); } - - int - column() const noexcept - { return this->m_sloc.column(); } - const cow_string& func() const noexcept { return this->m_func; }