From bab021a6203127f38fb89c61cc41deb3e0abbe62 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 17 Mar 2020 07:33:41 +0200 Subject: Add $defined() function --- libbuild2/function.cxx | 9 ++------ libbuild2/function.hxx | 11 +++++++++- libbuild2/functions-builtin.cxx | 46 ++++++++++++++++++++--------------------- 3 files changed, 35 insertions(+), 31 deletions(-) (limited to 'libbuild2') diff --git a/libbuild2/function.cxx b/libbuild2/function.cxx index 79e7a81..25dacf9 100644 --- a/libbuild2/function.cxx +++ b/libbuild2/function.cxx @@ -117,13 +117,8 @@ namespace build2 // Overload resolution. // - // Ours is pretty simple: we sort all the overloads into three ranks: - // - // 0 -- all the arguments match exactly (perfect match) - // 1 -- one or more arguments match via the derived-to-base conversion - // 2 -- one or more arguments match via the reversal to untyped - // - // More than one match of the same rank is ambiguous. + // See the overall function machinery description for the ranking + // semantics. // auto ip (map_.equal_range (name)); diff --git a/libbuild2/function.hxx b/libbuild2/function.hxx index ce47bd9..b745173 100644 --- a/libbuild2/function.hxx +++ b/libbuild2/function.hxx @@ -32,7 +32,7 @@ namespace build2 // as arguments. There is also higher-level, more convenient support for // defining functions as pointers to functions (including capture-less // lambdas), pointers to member functions (e.g., string::size()), or - // pointers to data members (e.g., name::type). In this case the build2 + // pointers to data members (e.g., name::type). In this case the buildfile // function types are automatically matched to C++ function types according // to these rules: // @@ -43,6 +43,15 @@ namespace build2 // value* - NULL-able any type (never NULL itself, use value::null) // optional - optional argument (here T can be T*, names, value) // + // The overload resolution is pretty simple: we sort all the candidates into + // three ranks: + // + // 0 -- all the arguments match exactly (perfect match) + // 1 -- one or more arguments match via the derived-to-base conversion + // 2 -- one or more arguments match via the reversal to untyped + // + // More than one match of the same rank is ambiguous. + // // Optional arguments must be last. In case of a failure the function is // expected to issue diagnostics and throw failed. Note that the arguments // are conceptually "moved" and can be reused by the implementation. diff --git a/libbuild2/functions-builtin.cxx b/libbuild2/functions-builtin.cxx index 4c5929b..c4f0314 100644 --- a/libbuild2/functions-builtin.cxx +++ b/libbuild2/functions-builtin.cxx @@ -3,6 +3,7 @@ #include +#include #include #include @@ -10,29 +11,23 @@ using namespace std; namespace build2 { - // Return NULL value if an environment variable is not set, untyped value - // otherwise. - // - static inline value - getenvvar (const string& name) - { - optional v (getenv (name)); - - if (!v) - return value (); - - names r; - r.emplace_back (to_name (move (*v))); - return value (move (r)); - } - void builtin_functions (function_map& m) { function_family f (m, "builtin"); - f["type"] = [](value* v) {return v->type != nullptr ? v->type->name : "";}; + // Note that we may want to extend the scope argument to a more general + // notion of "lookup context" (scope, target, prerequisite). + // + f["defined"] = [](const scope* s, names name) + { + if (s == nullptr) + fail << "defined() called out of scope" << endf; + return (*s)[convert (move (name))].defined (); + }; + + f["type"] = [](value* v) {return v->type != nullptr ? v->type->name : "";}; f["null"] = [](value* v) {return v->null;}; f["empty"] = [](value* v) {return v->null || v->empty ();}; @@ -67,14 +62,19 @@ namespace build2 // getenv // - f["getenv"] = [](string name) - { - return getenvvar (name); - }; - + // Return NULL if the environment variable is not set, untyped value + // otherwise. + // f["getenv"] = [](names name) { - return getenvvar (convert (move (name))); + optional v (getenv (convert (move (name)))); + + if (!v) + return value (); + + names r; + r.emplace_back (to_name (move (*v))); + return value (move (r)); }; } } -- cgit v1.1