aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/function.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2020-12-04 08:39:35 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2020-12-04 08:39:35 +0200
commit4168cda2363f3d796d0b9922852e249aac3131ba (patch)
tree3e74f8926ad2efe57ac8ffbeb03a8585f285e618 /libbuild2/function.cxx
parent864d84abcf1579b81f54d8d3f79520137d81f629 (diff)
Mark Buildfile functions as pure or impure
Diffstat (limited to 'libbuild2/function.cxx')
-rw-r--r--libbuild2/function.cxx111
1 files changed, 50 insertions, 61 deletions
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<value, bool> 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<const function_overload*, 2> 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<value> args,
- const function_overload& f)
- {
- // Call the cast thunk.
- //
- struct cast_data // Prefix of function_cast::data.
- {
- value (*const thunk) (const scope*, vector_view<value>, const void*);
- };
-
- auto d (reinterpret_cast<const cast_data*> (&f.data));
- return d->thunk (base, move (args), d);
- }
-
-#if !defined(_WIN32)
- constexpr const optional<const value_type*>* function_args<>::types;
-#else
- const optional<const value_type*>* 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<value> 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<value>, const void*);
+ };
+
+ auto d (reinterpret_cast<const cast_data*> (&f.data));
+ return d->thunk (base, move (args), d);
}
+#if !defined(_WIN32)
+ constexpr const optional<const value_type*>* function_args<>::types;
+#else
+ const optional<const value_type*>* const function_args<>::types = nullptr;
+#endif
+
// Static-initialize the function map and populate with builtin functions.
//