From 4168cda2363f3d796d0b9922852e249aac3131ba Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 4 Dec 2020 08:39:35 +0200 Subject: Mark Buildfile functions as pure or impure --- libbuild2/function.cxx | 111 ++++++++++++++++++++++--------------------------- 1 file changed, 50 insertions(+), 61 deletions(-) (limited to 'libbuild2/function.cxx') diff --git a/libbuild2/function.cxx b/libbuild2/function.cxx index 25dacf9..eaf3f9e 100644 --- a/libbuild2/function.cxx +++ b/libbuild2/function.cxx @@ -80,21 +80,6 @@ namespace build2 return i != map_.end () && i->first.compare (0, n, name) == 0; } - auto function_map:: - insert (string name, function_overload f) -> iterator - { - // Sanity checks. - // - assert (f.arg_min <= f.arg_max && - f.arg_types.size () <= f.arg_max && - f.impl != nullptr); - - auto i (map_.emplace (move (name), move (f))); - - i->second.name = i->first.c_str (); - return i; - } - pair function_map:: call (const scope* base, const string& name, @@ -120,16 +105,17 @@ namespace build2 // See the overall function machinery description for the ranking // semantics. // - auto ip (map_.equal_range (name)); + const function_overloads* all_ovls (find (name)); size_t rank (~0); small_vector ovls; + if (all_ovls != nullptr) { size_t count (args.size ()); - for (auto it (ip.first); it != ip.second; ++it) + for (auto it (all_ovls->begin ()); it != all_ovls->end (); ++it) { - const function_overload& f (it->second); + const function_overload& f (*it); // Argument count match. // @@ -257,8 +243,11 @@ namespace build2 dr << fail (loc) << "unmatched call to "; print_call (dr.os); - for (auto i (ip.first); i != ip.second; ++i) - dr << info << "candidate: " << i->second; + if (all_ovls != nullptr) + { + for (auto i (all_ovls->begin ()); i != all_ovls->end (); ++i) + dr << info << "candidate: " << *i; + } // If this is an unqualified name, then also print qualified // functions that end with this name. But skip functions that we @@ -271,14 +260,20 @@ namespace build2 for (auto i (begin ()); i != end (); ++i) { const string& q (i->first); - const function_overload& f (i->second); - if ((f.alt_name == nullptr || f.alt_name != name) && - q.size () > n) + if (q.size () > n) { - size_t p (q.size () - n); - if (q[p - 1] == '.' && q.compare (p, n, name) == 0) - dr << info << "candidate: " << i->second; + for (auto j (i->second.begin ()); j != i->second.end (); ++j) + { + const function_overload& f (*j); + + if (f.alt_name == nullptr || f.alt_name != name) + { + size_t p (q.size () - n); + if (q[p - 1] == '.' && q.compare (p, n, name) == 0) + dr << info << "candidate: " << f; + } + } } } } @@ -300,30 +295,8 @@ namespace build2 } } - value function_family:: - default_thunk (const scope* base, - vector_view args, - const function_overload& f) - { - // Call the cast thunk. - // - struct cast_data // Prefix of function_cast::data. - { - value (*const thunk) (const scope*, vector_view, const void*); - }; - - auto d (reinterpret_cast (&f.data)); - return d->thunk (base, move (args), d); - } - -#if !defined(_WIN32) - constexpr const optional* function_args<>::types; -#else - const optional* const function_args<>::types = nullptr; -#endif - - void function_family::entry:: - insert (string n, function_overload f) const + auto function_family:: + insert (string n, bool pure) const -> entry { // Figure out qualification. // @@ -332,31 +305,47 @@ namespace build2 if (p == string::npos) { - if (!qual.empty ()) + if (!qual_.empty ()) { - qn = qual; + qn = qual_; qn += '.'; qn += n; } } else if (p == 0) { - assert (!qual.empty ()); - n.insert (0, qual); + assert (!qual_.empty ()); + n.insert (0, qual_); } - auto i (qn.empty () ? map_.end () : map_.insert (move (qn), f)); - auto j (map_.insert (move (n), move (f))); + return entry { + map_.insert (move (n), pure), + qn.empty () ? nullptr : &map_.insert (move (qn), pure), + thunk_}; + } - // If we have both, then set alternative names. + value function_family:: + default_thunk (const scope* base, + vector_view args, + const function_overload& f) + { + // Call the cast thunk. // - if (i != map_.end ()) + struct cast_data // Prefix of function_cast::data. { - i->second.alt_name = j->first.c_str (); - j->second.alt_name = i->first.c_str (); - } + value (*const thunk) (const scope*, vector_view, const void*); + }; + + auto d (reinterpret_cast (&f.data)); + return d->thunk (base, move (args), d); } +#if !defined(_WIN32) + constexpr const optional* function_args<>::types; +#else + const optional* const function_args<>::types = nullptr; +#endif + // Static-initialize the function map and populate with builtin functions. // -- cgit v1.1