diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2024-02-20 15:40:02 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2024-02-20 16:08:14 +0200 |
commit | 0efae7db7b5870246f1e294a5fedaa69e9c90331 (patch) | |
tree | fd53e7b4b416a63c8e082dead3ef1d6496fa872a /libbuild2/parser.cxx | |
parent | 6ff1cf35f78a24d52603d84eac9349b3d4670c6c (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.cxx | 87 |
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; |