aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/parser.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2024-02-20 15:40:02 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2024-02-20 16:08:14 +0200
commit0efae7db7b5870246f1e294a5fedaa69e9c90331 (patch)
treefd53e7b4b416a63c8e082dead3ef1d6496fa872a /libbuild2/parser.cxx
parent6ff1cf35f78a24d52603d84eac9349b3d4670c6c (diff)
Add json_map and json_set buildfile value types
These expose the std::map<json_value,json_value> and std::set<json_value> types to buildfiles. New functions: $size(<json-set>) $size(<json-map>) $keys(<json-map>) Note that the $keys() function returns the list of map key as a json array. For example: m = [json_map] 2@([json] a@1 b@2) 1@([json] 1 2) s = [json_set] ([json] x@1 y@2) ([json] a@1 b@2) print ($m[2][b]) # 2 print ($s[([json] y@2 x@1)]) # true
Diffstat (limited to 'libbuild2/parser.cxx')
-rw-r--r--libbuild2/parser.cxx87
1 files changed, 54 insertions, 33 deletions
diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx
index bf806be..5572104 100644
--- a/libbuild2/parser.cxx
+++ b/libbuild2/parser.cxx
@@ -6066,7 +6066,12 @@ namespace build2
{
if (n[4] == '\0') return &value_traits<json_value>::value_type;
if (n == "json_array") return &value_traits<json_array>::value_type;
- if (n == "json_object") return &value_traits<json_object>::value_type;
+ if (n == "json_object")
+ return &value_traits<json_object>::value_type;
+ if (n == "json_set")
+ return &value_traits<set<json_value>>::value_type;
+ if (n == "json_map")
+ return &value_traits<map<json_value, json_value>>::value_type;
}
break;
}
@@ -6266,6 +6271,8 @@ namespace build2
if (n == "null")
{
+ // @@ Looks like here we assume representationally empty?
+ //
if (rhs && !rhs.empty ()) // Note: null means we had an expansion.
fail (l) << "value with null attribute";
@@ -7808,9 +7815,9 @@ namespace build2
// an empty sequence of names rather than a sequence of one empty
// name.
//
- if (!d.empty ())
+ if (size_t n = d.size ())
{
- if (d.size () != 1)
+ if (n != 1)
{
assert (what_expansion != nullptr);
concat_diag_multiple (loc, what_expansion);
@@ -9079,7 +9086,7 @@ namespace build2
// Untyped concatenation. Note that if RHS is NULL/empty, we still
// set the concat flag.
//
- else if (!result->null && !result->empty ())
+ else if (!result->null)
{
// This can only be an untyped value.
//
@@ -9087,33 +9094,36 @@ namespace build2
//
const names& lv (cast<names> (*result));
- // This should be a simple value or a simple directory.
- //
- if (lv.size () > 1)
- concat_diag_multiple (loc, what);
+ if (size_t s = lv.size ())
+ {
+ // This should be a simple value or a simple directory.
+ //
+ if (s > 1)
+ concat_diag_multiple (loc, what);
- const name& n (lv[0]);
+ const name& n (lv[0]);
- if (n.qualified ())
- fail (loc) << "concatenating " << what << " contains project "
- << "name";
+ if (n.qualified ())
+ fail (loc) << "concatenating " << what << " contains project "
+ << "name";
- if (n.typed ())
- fail (loc) << "concatenating " << what << " contains target type";
+ if (n.typed ())
+ fail (loc) << "concatenating " << what << " contains target type";
- if (!n.dir.empty ())
- {
- if (!n.value.empty ())
- fail (loc) << "concatenating " << what << " contains "
- << "directory";
+ if (!n.dir.empty ())
+ {
+ if (!n.value.empty ())
+ fail (loc) << "concatenating " << what << " contains "
+ << "directory";
- // Note that here we cannot assume what's in dir is really a
- // path (think s/foo/bar/) so we have to reverse it exactly.
- //
- concat_data.value += n.dir.representation ();
+ // Note that here we cannot assume what's in dir is really a
+ // path (think s/foo/bar/) so we have to reverse it exactly.
+ //
+ concat_data.value += n.dir.representation ();
+ }
+ else
+ concat_data.value += n.value;
}
- else
- concat_data.value += n.value;
}
// The same little hack as in the word case ($empty+foo).
@@ -9139,16 +9149,27 @@ namespace build2
// Nothing else to do here if the result is NULL or empty.
//
- if (result->null || result->empty ())
- continue;
-
- // @@ Could move if nv is result_data; see untypify().
+ // Note that we cannot use value::empty() here since we are
+ // interested in representationally empty.
//
- names nv_storage;
- names_view nv (reverse (*result, nv_storage, true /* reduce */));
+ if (!result->null)
+ {
+ // @@ Could move if nv is result_data; see untypify().
+ //
+ // Nuance: we should only be reducing empty simple value to empty
+ // list if we are not a second half of a pair.
+ //
+ bool pair (!ns.empty () && ns.back ().pair);
+
+ names nv_storage;
+ names_view nv (reverse (*result, nv_storage, !pair /* reduce */));
- count = splice_names (
- loc, nv, move (nv_storage), ns, what, pairn, pp, dp, tp);
+ if (!nv.empty ())
+ {
+ count = splice_names (
+ loc, nv, move (nv_storage), ns, what, pairn, pp, dp, tp);
+ }
+ }
}
continue;