aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-12-01 11:45:55 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-12-01 11:45:55 +0200
commit12fc75188cc1f0a8c4c443c04e7a022131198c36 (patch)
tree63ba0d83bb5498ee60af803d69e8514a03b4878e
parentbe14801929cf2a6caced87df034ae12a85f42aa6 (diff)
Allow implicit (lexical) typed-to-typed conversion
-rw-r--r--build2/parser.cxx54
-rw-r--r--tests/expansion/type.test9
-rw-r--r--tests/variable/dir-path/buildfile6
3 files changed, 38 insertions, 31 deletions
diff --git a/build2/parser.cxx b/build2/parser.cxx
index 456e3f7..5d4ff0a 100644
--- a/build2/parser.cxx
+++ b/build2/parser.cxx
@@ -560,6 +560,9 @@ namespace build2
// We store prepend/append values untyped (similar to
// overrides).
//
+ if (rhs.type != nullptr && att != type::assign)
+ untypify (rhs);
+
if (p.second)
{
// Note: we are always using assign and we don't pass the
@@ -626,8 +629,7 @@ namespace build2
if (lhs.extra != 0 && lhs.type != nullptr)
fail (at) << "typed prepend/append to target type/pattern-"
- << "specific variable " << var <<
- info << "use quoting to untypify the value";
+ << "specific variable " << var;
}
}
@@ -1160,8 +1162,7 @@ namespace build2
fail (l) << "null value in export";
if (rhs.type != nullptr)
- fail (l) << "typed value in export" <<
- info << "use quoting to untypify the value";
+ untypify (rhs);
export_value_ = move (rhs).as<names> ();
@@ -1649,23 +1650,6 @@ namespace build2
fail (l) << "unexpected value for attribute " << k << ": " << v;
}
- // If we have both attribute and value types, then they better match.
- //
- if (rhs.type != nullptr)
- {
- if (type != nullptr && type != rhs.type)
- {
- fail (l) << "conflicting attribute type " << type->name
- << " and value type " << rhs.type->name <<
- info << "use quoting to untypify the value";
- }
-
- // Reduce this to the untyped value case for simplicity.
- //
- type = rhs.type;
- untypify (rhs);
- }
-
// When do we set the type and when do we keep the original? This gets
// tricky for append/prepend where both values contribute. The guiding
// rule here is that if the user specified the type, then they reasonable
@@ -1685,6 +1669,32 @@ namespace build2
<< var->type->name << " and value type " << type->name;
}
+ // What if both LHS and RHS are typed? For now we do lexical conversion:
+ // if this specific value can be converted, then all is good. The
+ // alternative would be to do type conversion: if any value of RHS type
+ // can be converted to LHS type, then we are good. This may be a better
+ // option in the future but currently our parse_names() implementation
+ // untypifies everything if there are multiple names. And having stricter
+ // rules just for single-element values would be strange.
+ //
+ // We also have "weaker" type propagation for the RHS type.
+ //
+ bool rhs_type (false);
+ if (rhs.type != nullptr)
+ {
+ // Only consider RHS type if there is no explicit or variable type.
+ //
+ if (type == nullptr && (var == nullptr || var->type == nullptr))
+ {
+ type = rhs.type;
+ rhs_type = true;
+ }
+
+ // Reduce this to the untyped value case for simplicity.
+ //
+ untypify (rhs);
+ }
+
if (kind == type::assign)
{
if (type != v.type)
@@ -1699,7 +1709,7 @@ namespace build2
v.type = type;
else if (v.type == nullptr)
typify (v, *type, var);
- else if (v.type != type)
+ else if (v.type != type && !rhs_type)
fail (l) << "conflicting original value type " << v.type->name
<< " and append/prepend value type " << type->name;
}
diff --git a/tests/expansion/type.test b/tests/expansion/type.test
index d524eea..27c646d 100644
--- a/tests/expansion/type.test
+++ b/tests/expansion/type.test
@@ -36,14 +36,11 @@ y = "$x"
assert ($type($y) == "")
EOI
-: type-conflict
+: retypify
:
-$* <'print [bool] ([string] true)' 2>>EOE != 0
-<stdin>:1:7: error: conflicting attribute type bool and value type string
- info: use quoting to untypify the value
-EOE
+$* <'print [bool] ([string] true)' >'true'
-: retypify
+: retypify-quote
:
$* <'print [bool] "([string] true)"' >'true'
diff --git a/tests/variable/dir-path/buildfile b/tests/variable/dir-path/buildfile
index c6fdb46..5c99f07 100644
--- a/tests/variable/dir-path/buildfile
+++ b/tests/variable/dir-path/buildfile
@@ -27,7 +27,7 @@ print [strings] -I $y
print -I $y/baz
print
-z = [strings] "$x" # Re-typed.
+z = [strings] $x # Re-typed.
print $z
print
@@ -37,9 +37,9 @@ r = [dir_path] /
print $r/foo
r += foo
-print [strings] "$r"
+print [strings] $r
r += bar
-print [strings] "$r"
+print [strings] $r
./: