[vala/wip/issue/767] WIP Extend silent-cast support to type with known type signatures



commit 0f44bd9134703f92e12e8c7b07e12f18f27c299c
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               | 75 ++++++++++++++++++++-------
 tests/semantic/cast-gvariant-unsupported.test |  2 +-
 vala/valacastexpression.vala                  |  4 +-
 3 files changed, 58 insertions(+), 23 deletions(-)
---
diff --git a/codegen/valagvariantmodule.vala b/codegen/valagvariantmodule.vala
index 223302aa0..55bd9c59f 100644
--- a/codegen/valagvariantmodule.vala
+++ b/codegen/valagvariantmodule.vala
@@ -160,32 +160,67 @@ public class Vala.GVariantModule : GAsyncModule {
 
                push_function (cfunc);
 
+               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 (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);
+
+               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);
+                               if (target_type.is_real_non_null_struct_type ()) {
+                                       ccode.add_assignment (new CCodeIdentifier ("*result"), get_cvalue_ 
(transform_value (temp_value, expr.target_type, expr)));
                                } 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 ();
+                       }
+
+                       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);
+                       }
+                       if (target_type.is_real_non_null_struct_type ()) {
+                               ccode.add_assignment (new CCodeIdentifier ("*result"), new CCodeConstant 
("NULL"));
                        } else {
-                               ccode.add_return (func_result);
+                               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/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 ()));
                        }
                }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]