From b85b7ad1e985c14d0420002229665c9edda53ab5 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 23 Aug 2019 16:27:20 +0200 Subject: Functions --- libbuild2/context.cxx | 7 +++- libbuild2/context.hxx | 4 +++ libbuild2/function.cxx | 63 ++++++++++++++++------------------ libbuild2/function.hxx | 18 ++++++---- libbuild2/function.test.cxx | 4 ++- libbuild2/functions-builtin.cxx | 4 +-- libbuild2/functions-filesystem.cxx | 4 +-- libbuild2/functions-name.cxx | 6 ++-- libbuild2/functions-path.cxx | 6 ++-- libbuild2/functions-process-path.cxx | 4 +-- libbuild2/functions-process.cxx | 4 +-- libbuild2/functions-project-name.cxx | 6 ++-- libbuild2/functions-regex.cxx | 4 +-- libbuild2/functions-string.cxx | 6 ++-- libbuild2/functions-target-triplet.cxx | 6 ++-- libbuild2/in/rule.cxx | 8 ++--- libbuild2/install/functions.cxx | 4 +-- libbuild2/install/init.cxx | 8 +++-- libbuild2/parser.cxx | 6 ++-- 19 files changed, 92 insertions(+), 80 deletions(-) diff --git a/libbuild2/context.cxx b/libbuild2/context.cxx index 23cef44..f6b9a90 100644 --- a/libbuild2/context.cxx +++ b/libbuild2/context.cxx @@ -11,6 +11,7 @@ #include #include #include +#include #include #include // uncaught_exceptions @@ -44,6 +45,7 @@ namespace build2 target_set targets; variable_pool var_pool; variable_overrides var_overrides; + function_map functions; data (context& c): scopes (c), targets (c), var_pool (&c /* global */) {} }; @@ -59,7 +61,8 @@ namespace build2 global_scope (create_global_scope (data_->scopes)), targets (data_->targets), var_pool (data_->var_pool), - var_overrides (data_->var_overrides) + var_overrides (data_->var_overrides), + functions (data_->functions) { tracer trace ("context"); @@ -68,6 +71,8 @@ namespace build2 scope_map& sm (data_->scopes); variable_pool& vp (data_->var_pool); + register_builtin_functions (functions); + // Initialize the meta/operation tables. Note that the order should match // the id constants in . // diff --git a/libbuild2/context.hxx b/libbuild2/context.hxx index 1d20acb..2e2be3a 100644 --- a/libbuild2/context.hxx +++ b/libbuild2/context.hxx @@ -33,6 +33,8 @@ namespace build2 class value; using values = small_vector; + class function_map; + struct opspec; class LIBBUILD2_SYMEXPORT run_phase_mutex @@ -277,6 +279,8 @@ namespace build2 const variable_pool& var_pool; const variable_overrides& var_overrides; // Project and relative scope. + function_map& functions; + // Cached variables. // diff --git a/libbuild2/function.cxx b/libbuild2/function.cxx index 2d4dce9..ebf880a 100644 --- a/libbuild2/function.cxx +++ b/libbuild2/function.cxx @@ -275,7 +275,7 @@ namespace build2 { size_t n (name.size ()); - for (auto i (functions.begin ()); i != functions.end (); ++i) + for (auto i (begin ()); i != end (); ++i) { const string& q (i->first); const function_overload& f (i->second); @@ -352,12 +352,12 @@ namespace build2 n.insert (0, qual); } - auto i (qn.empty () ? functions.end () : functions.insert (move (qn), f)); - auto j (functions.insert (move (n), move (f))); + auto i (qn.empty () ? map_.end () : map_.insert (move (qn), f)); + auto j (map_.insert (move (n), move (f))); // If we have both, then set alternative names. // - if (i != functions.end ()) + if (i != map_.end ()) { i->second.alt_name = j->first.c_str (); j->second.alt_name = i->first.c_str (); @@ -366,35 +366,30 @@ namespace build2 // Static-initialize the function map and populate with builtin functions. // - function_map functions; - - void builtin_functions (); // functions-builtin.cxx - void filesystem_functions (); // functions-filesystem.cxx - void name_functions (); // functions-name.cxx - void path_functions (); // functions-path.cxx - void process_functions (); // functions-process.cxx - void process_path_functions (); // functions-process-path.cxx - void regex_functions (); // functions-regex.cxx - void string_functions (); // functions-string.cxx - void target_triplet_functions (); // functions-target-triplet.cxx - void project_name_functions (); // functions-target-triplet.cxx - - struct functions_init - { - functions_init () - { - builtin_functions (); - filesystem_functions (); - name_functions (); - path_functions (); - process_functions (); - process_path_functions (); - regex_functions (); - string_functions (); - target_triplet_functions (); - project_name_functions (); - } - }; - static const functions_init init_; + void builtin_functions (function_map&); // functions-builtin.cxx + void filesystem_functions (function_map&); // functions-filesystem.cxx + void name_functions (function_map&); // functions-name.cxx + void path_functions (function_map&); // functions-path.cxx + void process_functions (function_map&); // functions-process.cxx + void process_path_functions (function_map&); // functions-process-path.cxx + void regex_functions (function_map&); // functions-regex.cxx + void string_functions (function_map&); // functions-string.cxx + void target_triplet_functions (function_map&); // functions-target-triplet.cxx + void project_name_functions (function_map&); // functions-target-triplet.cxx + + void + register_builtin_functions (function_map& m) + { + builtin_functions (m); + filesystem_functions (m); + name_functions (m); + path_functions (m); + process_functions (m); + process_path_functions (m); + regex_functions (m); + string_functions (m); + target_triplet_functions (m); + project_name_functions (m); + } } diff --git a/libbuild2/function.hxx b/libbuild2/function.hxx index 51c17c0..bb3fe3a 100644 --- a/libbuild2/function.hxx +++ b/libbuild2/function.hxx @@ -216,7 +216,8 @@ namespace build2 map_type map_; }; - LIBBUILD2_SYMEXPORT extern function_map functions; + LIBBUILD2_SYMEXPORT void + register_builtin_functions (function_map&); class LIBBUILD2_SYMEXPORT function_family { @@ -237,9 +238,10 @@ namespace build2 // containing a leading dot is a shortcut notation for a qualified-only // name. // - explicit - function_family (string qual, function_impl* thunk = &default_thunk) - : qual_ (qual), thunk_ (thunk) {} + function_family (function_map& map, + string qual, + function_impl* thunk = &default_thunk) + : map_ (map), qual_ (move (qual)), thunk_ (thunk) {} struct entry; @@ -247,13 +249,14 @@ namespace build2 operator[] (string name) const; static bool - defined (string qual) + defined (function_map& map, string qual) { qual += '.'; - return functions.defined (qual); + return map.defined (qual); } private: + function_map& map_; const string qual_; function_impl* thunk_; }; @@ -744,6 +747,7 @@ namespace build2 struct LIBBUILD2_SYMEXPORT function_family::entry { + function_map& map_; string name; const string& qual; function_impl* thunk; @@ -898,7 +902,7 @@ namespace build2 inline auto function_family:: operator[] (string name) const -> entry { - return entry {move (name), qual_, thunk_}; + return entry {map_, move (name), qual_, thunk_}; } } diff --git a/libbuild2/function.test.cxx b/libbuild2/function.test.cxx index 016d846..bd0be62 100644 --- a/libbuild2/function.test.cxx +++ b/libbuild2/function.test.cxx @@ -45,7 +45,9 @@ namespace build2 scheduler sched (1); // Serial execution. context ctx (sched); - function_family f ("dummy"); + auto& functions (ctx.functions); + + function_family f (functions, "dummy"); f["fail"] = []() {fail << "failed" << endf;}; f["fail_arg"] = [](names a) {return convert (move (a[0]));}; diff --git a/libbuild2/functions-builtin.cxx b/libbuild2/functions-builtin.cxx index 44ae534..2acd5b4 100644 --- a/libbuild2/functions-builtin.cxx +++ b/libbuild2/functions-builtin.cxx @@ -24,9 +24,9 @@ namespace build2 } void - builtin_functions () + builtin_functions (function_map& m) { - function_family f ("builtin"); + function_family f (m, "builtin"); f["type"] = [](value* v) {return v->type != nullptr ? v->type->name : "";}; diff --git a/libbuild2/functions-filesystem.cxx b/libbuild2/functions-filesystem.cxx index d98c75d..2fcd305 100644 --- a/libbuild2/functions-filesystem.cxx +++ b/libbuild2/functions-filesystem.cxx @@ -121,9 +121,9 @@ namespace build2 } void - filesystem_functions () + filesystem_functions (function_map& m) { - function_family f ("filesystem"); + function_family f (m, "filesystem"); // path_search // diff --git a/libbuild2/functions-name.cxx b/libbuild2/functions-name.cxx index a8e08b6..8013a0c 100644 --- a/libbuild2/functions-name.cxx +++ b/libbuild2/functions-name.cxx @@ -33,9 +33,9 @@ namespace build2 } void - name_functions () + name_functions (function_map& m) { - function_family f ("name"); + function_family f (m, "name"); // These functions treat a name as a target/prerequisite name. // @@ -97,7 +97,7 @@ namespace build2 // Name-specific overloads from builtins. // - function_family b ("builtin"); + function_family b (m, "builtin"); b[".concat"] = [](dir_path d, name n) { diff --git a/libbuild2/functions-path.cxx b/libbuild2/functions-path.cxx index 6e39812..03f9be3 100644 --- a/libbuild2/functions-path.cxx +++ b/libbuild2/functions-path.cxx @@ -96,9 +96,9 @@ namespace build2 } void - path_functions () + path_functions (function_map& m) { - function_family f ("path", &path_thunk); + function_family f (m, "path", &path_thunk); // string // @@ -343,7 +343,7 @@ namespace build2 // Path-specific overloads from builtins. // - function_family b ("builtin", &path_thunk); + function_family b (m, "builtin", &path_thunk); b[".concat"] = &concat_path_string; b[".concat"] = &concat_dir_path_string; diff --git a/libbuild2/functions-process-path.cxx b/libbuild2/functions-process-path.cxx index 65e426b..124bd55 100644 --- a/libbuild2/functions-process-path.cxx +++ b/libbuild2/functions-process-path.cxx @@ -10,9 +10,9 @@ using namespace std; namespace build2 { void - process_path_functions () + process_path_functions (function_map& m) { - function_family f ("process_path"); + function_family f (m, "process_path"); // As discussed in value_traits, we always have recall. // diff --git a/libbuild2/functions-process.cxx b/libbuild2/functions-process.cxx index 83188d3..2cc3385 100644 --- a/libbuild2/functions-process.cxx +++ b/libbuild2/functions-process.cxx @@ -191,9 +191,9 @@ namespace build2 } void - process_functions () + process_functions (function_map& m) { - function_family f ("process"); + function_family f (m, "process"); // $process.run([ ...]) // diff --git a/libbuild2/functions-project-name.cxx b/libbuild2/functions-project-name.cxx index 163e865..f70a1e7 100644 --- a/libbuild2/functions-project-name.cxx +++ b/libbuild2/functions-project-name.cxx @@ -10,9 +10,9 @@ using namespace std; namespace build2 { void - project_name_functions () + project_name_functions (function_map& m) { - function_family f ("project_name"); + function_family f (m, "project_name"); f["string"] = [](project_name p) {return move (p).string ();}; @@ -31,7 +31,7 @@ namespace build2 // Project name-specific overloads from builtins. // - function_family b ("builtin"); + function_family b (m, "builtin"); b[".concat"] = [](project_name n, string s) { diff --git a/libbuild2/functions-regex.cxx b/libbuild2/functions-regex.cxx index 2c478fe..339224e 100644 --- a/libbuild2/functions-regex.cxx +++ b/libbuild2/functions-regex.cxx @@ -339,9 +339,9 @@ namespace build2 } void - regex_functions () + regex_functions (function_map& m) { - function_family f ("regex"); + function_family f (m, "regex"); // $regex.match(, [, ]) // diff --git a/libbuild2/functions-string.cxx b/libbuild2/functions-string.cxx index 22860cb..1e93943 100644 --- a/libbuild2/functions-string.cxx +++ b/libbuild2/functions-string.cxx @@ -10,9 +10,9 @@ using namespace std; namespace build2 { void - string_functions () + string_functions (function_map& m) { - function_family f ("string"); + function_family f (m, "string"); f["string"] = [](string s) {return s;}; @@ -23,7 +23,7 @@ namespace build2 // String-specific overloads from builtins. // - function_family b ("builtin"); + function_family b (m, "builtin"); b[".concat"] = [](string l, string r) {l += r; return l;}; diff --git a/libbuild2/functions-target-triplet.cxx b/libbuild2/functions-target-triplet.cxx index 4394c5a..9ae2514 100644 --- a/libbuild2/functions-target-triplet.cxx +++ b/libbuild2/functions-target-triplet.cxx @@ -10,15 +10,15 @@ using namespace std; namespace build2 { void - target_triplet_functions () + target_triplet_functions (function_map& m) { - function_family f ("target_triplet"); + function_family f (m, "target_triplet"); f["string"] = [](target_triplet t) {return t.string ();}; // Target triplet-specific overloads from builtins. // - function_family b ("builtin"); + function_family b (m, "builtin"); b[".concat"] = [](target_triplet l, string sr) {return l.string () + sr;}; b[".concat"] = [](string sl, target_triplet r) {return sl + r.string ();}; diff --git a/libbuild2/in/rule.cxx b/libbuild2/in/rule.cxx index 434250e..de7ad88 100644 --- a/libbuild2/in/rule.cxx +++ b/libbuild2/in/rule.cxx @@ -435,10 +435,10 @@ namespace build2 return convert ( v.type == nullptr ? move (v) - : functions.call (&t.base_scope (), - "string", - vector_view (&v, 1), - l)); + : t.ctx.functions.call (&t.base_scope (), + "string", + vector_view (&v, 1), + l)); } catch (const invalid_argument& e) { diff --git a/libbuild2/install/functions.cxx b/libbuild2/install/functions.cxx index f067918..6052dd9 100644 --- a/libbuild2/install/functions.cxx +++ b/libbuild2/install/functions.cxx @@ -14,9 +14,9 @@ namespace build2 namespace install { void - functions () + functions (function_map& m) { - function_family f ("install"); + function_family f (m, "install"); // Resolve potentially relative install.* value to an absolute directory // based on (other) install.* values visible from the calling scope. diff --git a/libbuild2/install/init.cxx b/libbuild2/install/init.cxx index dac337f..d2321b5 100644 --- a/libbuild2/install/init.cxx +++ b/libbuild2/install/init.cxx @@ -127,7 +127,7 @@ namespace build2 } void - functions (); // functions.cxx + functions (function_map&); // functions.cxx bool boot (scope& rs, const location&, unique_ptr&) @@ -135,11 +135,13 @@ namespace build2 tracer trace ("install::boot"); l5 ([&]{trace << "for " << rs;}); + context& ctx (rs.ctx); + // Register install function family if this is the first instance of the // install modules. // - if (!function_family::defined ("install")) - functions (); + if (!function_family::defined (ctx.functions, "install")) + functions (ctx.functions); // Register our operations. // diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx index a05c898..d346afc 100644 --- a/libbuild2/parser.cxx +++ b/libbuild2/parser.cxx @@ -3967,7 +3967,7 @@ namespace build2 info << "use quoting to force untyped concatenation"; })); - p = functions.try_call ( + p = ctx.functions.try_call ( scope_, "builtin.concat", vector_view (a), loc); } @@ -4636,7 +4636,7 @@ namespace build2 // Note that we "move" args to call(). // - result_data = functions.call (scope_, name, args, loc); + result_data = ctx.functions.call (scope_, name, args, loc); what = "function call"; } else @@ -4744,7 +4744,7 @@ namespace build2 info (loc) << "while converting " << t << " to string"; })); - p = functions.try_call ( + p = ctx.functions.try_call ( scope_, "string", vector_view (&result_data, 1), loc); } -- cgit v1.1