[vala/wip/issue/767] WIP Extend silent-cast support to type with known type signatures
- From: Rico Tzschichholz <ricotz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/wip/issue/767] WIP Extend silent-cast support to type with known type signatures
- Date: Fri, 22 Mar 2019 07:13:04 +0000 (UTC)
commit 5433e6882520cb515a53ccea27bb53b32ee6232d
Author: Rico Tzschichholz <ricotz ubuntu com>
Date: Thu Mar 21 22:19:26 2019 +0100
WIP Extend silent-cast support to type with known type signatures
codegen/valagvariantmodule.vala | 72 ++++++++++++++++++--------
tests/basic-types/gvariants-unboxing-safe.vala | 7 +++
tests/semantic/cast-gvariant-unsupported.test | 2 +-
vala/valacastexpression.vala | 4 +-
vala/valasemanticanalyzer.vala | 5 --
5 files changed, 59 insertions(+), 31 deletions(-)
---
diff --git a/codegen/valagvariantmodule.vala b/codegen/valagvariantmodule.vala
index 223302aa0..53639021e 100644
--- a/codegen/valagvariantmodule.vala
+++ b/codegen/valagvariantmodule.vala
@@ -160,32 +160,58 @@ public class Vala.GVariantModule : GAsyncModule {
push_function (cfunc);
- CCodeExpression func_result = deserialize_expression (target_type, new CCodeIdentifier
("value"), new CCodeIdentifier ("*result"));
- if (target_type.is_real_non_null_struct_type ()) {
- ccode.add_assignment (new CCodeIdentifier ("*result"), func_result);
- } else {
- if (expr.is_silent_cast && SemanticAnalyzer.is_gvariant_basic_type (target_type)) {
- var ccheck = new CCodeFunctionCall (new CCodeIdentifier
("g_variant_is_of_type"));
- ccheck.add_argument (new CCodeIdentifier ("value"));
- BasicTypeInfo basic_type;
- get_basic_type_info (target_type.get_type_signature (), out basic_type);
- ccheck.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_" +
basic_type.type_name.ascii_up ()));
- ccode.open_if (ccheck);
- if (basic_type.is_string) {
- ccode.add_return (func_result);
- } else {
- var temp_type = expr.target_type.copy ();
- temp_type.nullable = false;
- var temp_value = create_temp_value (temp_type, false, expr);
- store_value (temp_value, new GLibValue (temp_type, func_result),
expr.source_reference);
- ccode.add_return (get_cvalue_ (transform_value (temp_value,
expr.target_type, expr)));
- }
- ccode.add_else ();
- ccode.add_return (new CCodeConstant ("NULL"));
- ccode.close ();
+ CCodeExpression type_expr = null;
+ BasicTypeInfo basic_type = {};
+ bool is_basic_type = false;
+ if (expr.is_silent_cast) {
+ var signature = target_type.get_type_signature ();
+ is_basic_type = get_basic_type_info (signature, out basic_type);
+ var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_is_of_type"));
+ ccheck.add_argument (new CCodeIdentifier ("value"));
+ if (is_basic_type) {
+ type_expr = new CCodeIdentifier ("G_VARIANT_TYPE_" +
basic_type.type_name.ascii_up ());
} else {
+ var gvariant_type_type = new ObjectType ((Class) root_symbol.scope.lookup
("GLib").scope.lookup ("VariantType"));
+ var type_temp = get_temp_variable (gvariant_type_type, true, expr, true);
+ emit_temp_var (type_temp);
+ type_expr = new CCodeFunctionCall (new CCodeIdentifier
("g_variant_type_new"));
+ ((CCodeFunctionCall) type_expr).add_argument (new CCodeIdentifier
("\"%s\"".printf (signature)));
+ store_value (get_local_cvalue (type_temp), new GLibValue (gvariant_type_type,
type_expr), expr.source_reference);
+ type_expr = get_variable_cexpression (type_temp.name);
+ }
+ ccheck.add_argument (type_expr);
+ ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.AND, new
CCodeIdentifier ("value"), ccheck));
+ }
+
+ CCodeExpression func_result = deserialize_expression (target_type, new CCodeIdentifier
("value"), new CCodeIdentifier ("*result"));
+
+ if (expr.is_silent_cast) {
+ if (is_basic_type && basic_type.is_string) {
ccode.add_return (func_result);
+ } else {
+ if (!is_basic_type) {
+ var type_free = new CCodeFunctionCall (new CCodeIdentifier
("g_variant_type_free"));
+ type_free.add_argument (type_expr);
+ ccode.add_expression (type_free);
+ }
+ var temp_type = expr.target_type.copy ();
+ temp_type.nullable = false;
+ var temp_value = create_temp_value (temp_type, false, expr);
+ store_value (temp_value, new GLibValue (temp_type, func_result),
expr.source_reference);
+ ccode.add_return (get_cvalue_ (transform_value (temp_value, expr.target_type,
expr)));
}
+ ccode.add_else ();
+ if (!is_basic_type) {
+ var type_free = new CCodeFunctionCall (new CCodeIdentifier
("g_variant_type_free"));
+ type_free.add_argument (type_expr);
+ ccode.add_expression (type_free);
+ }
+ ccode.add_return (new CCodeConstant ("NULL"));
+ ccode.close ();
+ } else if (target_type.is_real_non_null_struct_type ()) {
+ ccode.add_assignment (new CCodeIdentifier ("*result"), func_result);
+ } else {
+ ccode.add_return (func_result);
}
pop_function ();
diff --git a/tests/basic-types/gvariants-unboxing-safe.vala b/tests/basic-types/gvariants-unboxing-safe.vala
index 55e4eca45..43598d2b5 100644
--- a/tests/basic-types/gvariants-unboxing-safe.vala
+++ b/tests/basic-types/gvariants-unboxing-safe.vala
@@ -28,4 +28,11 @@ void main () {
int32? i32 = v as int32;
assert (i32 == null);
}
+
+ v = new Variant.strv ({ "foo", "bar", "manam" });
+ {
+ string[]? sa = v as string[];
+ assert (sa != null);
+ assert (sa[2] == "manam");
+ }
}
diff --git a/tests/semantic/cast-gvariant-unsupported.test b/tests/semantic/cast-gvariant-unsupported.test
index 80abaac67..2e4ed2d3e 100644
--- a/tests/semantic/cast-gvariant-unsupported.test
+++ b/tests/semantic/cast-gvariant-unsupported.test
@@ -2,5 +2,5 @@ Invalid Code
void main () {
Variant? v = null;
- string[]? array = v as string[];
+ Object? array = v as Object;
}
diff --git a/vala/valacastexpression.vala b/vala/valacastexpression.vala
index e1a4dc7ab..63e356155 100644
--- a/vala/valacastexpression.vala
+++ b/vala/valacastexpression.vala
@@ -184,8 +184,8 @@ public class Vala.CastExpression : Expression {
&& is_gvariant (context, inner.value_type) && !is_gvariant (context, value_type)) {
// GVariant unboxing returns owned value
value_type.value_owned = true;
- if (is_silent_cast && !SemanticAnalyzer.is_gvariant_basic_type (value_type)) {
- Report.error (source_reference, "Silent casts of `GLib.Variant' is only
supported for basic types");
+ if (value_type.get_type_signature () == null) {
+ Report.error (source_reference, "Casting of `GLib.Variant' to `%s' is not
supported".printf (value_type.to_qualified_string ()));
}
}
diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala
index 65bce9014..485ab222d 100644
--- a/vala/valasemanticanalyzer.vala
+++ b/vala/valasemanticanalyzer.vala
@@ -747,11 +747,6 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
return true;
}
- public static bool is_gvariant_basic_type (DataType type) {
- const string[] GVARIANT_BASIC_TYPES = { "y", "b", "n", "q", "i", "u", "x", "t", "d", "s",
"o", "g" };
- return type.get_type_signature () in GVARIANT_BASIC_TYPES;
- }
-
private static DataType? get_instance_base_type (DataType instance_type, DataType base_type, CodeNode
node_reference) {
// construct a new type reference for the base type with correctly linked type arguments
DataType instance_base_type;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]