[vala/wip/transform: 36/98] Complete the gvariant transformer



commit f25ced160ac581ad07f24c98b32ae6a620e24a15
Author: Luca Bruno <lucabru src gnome org>
Date:   Tue Jan 3 15:34:48 2012 +0100

    Complete the gvariant transformer

 codegen/valagvariantmodule.vala      |  110 ----------------------------------
 codegen/valagvarianttransformer.vala |   98 +++++++++++++++++++++++++-----
 vala/valacodebuilder.vala            |   62 +++++++++++++++++++
 vala/valacodetransformer.vala        |    7 ++-
 4 files changed, 149 insertions(+), 128 deletions(-)
---
diff --git a/codegen/valagvariantmodule.vala b/codegen/valagvariantmodule.vala
index 8b08731..3684fa9 100644
--- a/codegen/valagvariantmodule.vala
+++ b/codegen/valagvariantmodule.vala
@@ -142,29 +142,6 @@ public class Vala.GVariantModule : GAsyncModule {
                }
        }
 
-       public override void visit_enum (Enum en) {
-               base.visit_enum (en);
-
-               if (is_string_marshalled_enum (en)) {
-                       // strcmp
-                       cfile.add_include ("string.h");
-
-                       cfile.add_function (generate_enum_from_string_function (en));
-                       cfile.add_function (generate_enum_to_string_function (en));
-               }
-       }
-
-       public override bool generate_enum_declaration (Enum en, CCodeFile decl_space) {
-               if (base.generate_enum_declaration (en, decl_space)) {
-                       if (is_string_marshalled_enum (en)) {
-                               decl_space.add_function_declaration 
(generate_enum_from_string_function_declaration (en));
-                               decl_space.add_function_declaration 
(generate_enum_to_string_function_declaration (en));
-                       }
-                       return true;
-               }
-               return false;
-       }
-
        CCodeExpression? get_array_length (CCodeExpression expr, int dim) {
                var id = expr as CCodeIdentifier;
                var ma = expr as CCodeMemberAccess;
@@ -195,58 +172,6 @@ public class Vala.GVariantModule : GAsyncModule {
                return from_string_call;
        }
 
-       public CCodeFunction generate_enum_from_string_function_declaration (Enum en) {
-               var from_string_name = "%s_from_string".printf (get_ccode_lower_case_name (en, null));
-
-               var from_string_func = new CCodeFunction (from_string_name, get_ccode_name (en));
-               from_string_func.add_parameter (new CCodeParameter ("str", "const char*"));
-               from_string_func.add_parameter (new CCodeParameter ("error", "GError**"));
-
-               return from_string_func;
-       }
-
-       public CCodeFunction generate_enum_from_string_function (Enum en) {
-               var from_string_name = "%s_from_string".printf (get_ccode_lower_case_name (en, null));
-
-               var from_string_func = new CCodeFunction (from_string_name, get_ccode_name (en));
-               from_string_func.add_parameter (new CCodeParameter ("str", "const char*"));
-               from_string_func.add_parameter (new CCodeParameter ("error", "GError**"));
-
-               push_function (from_string_func);
-
-               ccode.add_declaration (get_ccode_name (en), new CCodeVariableDeclarator.zero ("value", new 
CCodeConstant ("0")));
-
-               bool firstif = true;
-               foreach (EnumValue enum_value in en.get_values ()) {
-                       string dbus_value = get_dbus_value (enum_value, enum_value.name);
-                       var string_comparison = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
-                       string_comparison.add_argument (new CCodeIdentifier ("str"));
-                       string_comparison.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_value)));
-                       var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, 
string_comparison, new CCodeConstant ("0"));
-                       if (firstif) {
-                               ccode.open_if (cond);
-                               firstif = false;
-                       } else {
-                               ccode.else_if (cond);
-                       }
-                       ccode.add_assignment (new CCodeIdentifier ("value"), new CCodeIdentifier 
(get_ccode_name (enum_value)));
-               }
-
-               ccode.add_else ();
-               var set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error"));
-               set_error.add_argument (new CCodeIdentifier ("error"));
-               set_error.add_argument (new CCodeIdentifier ("G_DBUS_ERROR"));
-               set_error.add_argument (new CCodeIdentifier ("G_DBUS_ERROR_INVALID_ARGS"));
-               set_error.add_argument (new CCodeConstant ("\"Invalid value for enum `%s'\"".printf 
(get_ccode_name (en))));
-               ccode.add_expression (set_error);
-               ccode.close ();
-
-               ccode.add_return (new CCodeIdentifier ("value"));
-
-               pop_function ();
-               return from_string_func;
-       }
-
        CCodeExpression deserialize_basic (BasicTypeInfo basic_type, CCodeExpression variant_expr, bool 
transfer = false) {
                var get_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_get_" + 
basic_type.type_name));
                get_call.add_argument (variant_expr);
@@ -523,41 +448,6 @@ public class Vala.GVariantModule : GAsyncModule {
                return to_string_call;
        }
 
-       public CCodeFunction generate_enum_to_string_function_declaration (Enum en) {
-               var to_string_name = "%s_to_string".printf (get_ccode_lower_case_name (en, null));
-
-               var to_string_func = new CCodeFunction (to_string_name, "const char*");
-               to_string_func.add_parameter (new CCodeParameter ("value", get_ccode_name (en)));
-
-               return to_string_func;
-       }
-
-       public CCodeFunction generate_enum_to_string_function (Enum en) {
-               var to_string_name = "%s_to_string".printf (get_ccode_lower_case_name (en, null));
-
-               var to_string_func = new CCodeFunction (to_string_name, "const char*");
-               to_string_func.add_parameter (new CCodeParameter ("value", get_ccode_name (en)));
-
-               push_function (to_string_func);
-
-               ccode.add_declaration ("const char *", new CCodeVariableDeclarator ("str"));
-
-               ccode.open_switch (new CCodeIdentifier ("value"));
-               foreach (EnumValue enum_value in en.get_values ()) {
-                       string dbus_value = get_dbus_value (enum_value, enum_value.name);
-                       ccode.add_case (new CCodeIdentifier (get_ccode_name (enum_value)));
-                       ccode.add_assignment (new CCodeIdentifier ("str"), new CCodeConstant ("\"%s\"".printf 
(dbus_value)));
-                       ccode.add_break ();
-               }
-
-               ccode.close();
-
-               ccode.add_return (new CCodeIdentifier ("str"));
-
-               pop_function ();
-               return to_string_func;
-       }
-
        CCodeExpression? serialize_basic (BasicTypeInfo basic_type, CCodeExpression expr) {
                var new_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_new_" + 
basic_type.type_name));
                new_call.add_argument (expr);
diff --git a/codegen/valagvarianttransformer.vala b/codegen/valagvarianttransformer.vala
index 170595f..686c8f8 100644
--- a/codegen/valagvarianttransformer.vala
+++ b/codegen/valagvarianttransformer.vala
@@ -45,6 +45,13 @@ public class Vala.GVariantTransformer : CodeTransformer {
                { "g", "signature", true }
        };
 
+       static bool is_string_marshalled_enum (TypeSymbol? symbol) {
+               if (symbol != null && symbol is Enum) {
+                       return symbol.get_attribute_bool ("DBus", "use_string_marshalling");
+               }
+               return false;
+       }
+
        bool get_basic_type_info (string signature, out BasicTypeInfo basic_type) {
                foreach (BasicTypeInfo info in basic_types) {
                        if (info.signature == signature) {
@@ -56,10 +63,6 @@ public class Vala.GVariantTransformer : CodeTransformer {
                return false;
        }
 
-       Expression expression (string str) {
-               return new Parser().parse_expression_string (str, b.source_reference);
-       }
-
        Expression serialize_basic (BasicTypeInfo basic_type, Expression expr) {
                var new_call = (ObjectCreationExpression) expression (@"new 
GLib.Variant.$(basic_type.type_name)()");
                new_call.add_argument (expr);
@@ -70,13 +73,6 @@ public class Vala.GVariantTransformer : CodeTransformer {
                return symbol.get_attribute_string ("DBus", "signature");
        }
 
-       static bool is_string_marshalled_enum (TypeSymbol? symbol) {
-               if (symbol != null && symbol is Enum) {
-                       return symbol.get_attribute_bool ("DBus", "use_string_marshalling");
-               }
-               return false;
-       }
-
        public static string? get_type_signature (DataType datatype, Symbol? symbol = null) {
                if (symbol != null) {
                        string sig = get_dbus_signature (symbol);
@@ -400,10 +396,70 @@ public class Vala.GVariantTransformer : CodeTransformer {
                return call;
        }
 
-       public override void visit_cast_expression (CastExpression expr) {
-               base.visit_cast_expression (expr);
+       string get_dbus_value (EnumValue value, string default_value) {
+               var dbus_value = value.get_attribute_string ("DBus", "value");
+               if (dbus_value != null) {
+                       return dbus_value;;
+               }
+               return default_value;
+       }
 
+       void add_enum_from_string_method (Enum en) {
+               if (en.scope.lookup ("from_string") != null) {
+                       return;
+               }
+               var m = new Method ("from_string", context.analyzer.get_data_type_for_symbol (en), 
en.source_reference);
+               m.add_error_type (data_type ("GLib.DBusError.INVALID_ARGS"));
+               m.add_parameter (new Parameter ("str", data_type ("string", false), en.source_reference));
+               en.add_method (m);
+               m.binding = MemberBinding.STATIC;
+               m.access = SymbolAccessibility.PUBLIC;
+               b = new CodeBuilder.for_method (m);
+
+               b.open_switch (expression ("str"), null);
+               b.add_throw (expression ("new GLib.DBusError.INVALID_ARGS (\"Invalid value for enum 
`%s'\")".printf (CCodeBaseModule.get_ccode_name (en))));
+               foreach (var enum_value in en.get_values ()) {
+                       string dbus_value = get_dbus_value (enum_value, enum_value.name);
+                       b.add_section (expression (@"\"$dbus_value\""));
+                       b.add_return (expression (@"$(en.get_full_name()).$(enum_value.name)"));
+               }
+               b.close ();
+
+               check (m);
+       }
+
+       void add_enum_to_string_method (Enum en) {
+               if (en.scope.lookup ("to_string") != null) {
+                       return;
+               }
+               var m = new Method ("to_string", data_type ("string", false, true), en.source_reference);
+               en.add_method (m);
+               m.access = SymbolAccessibility.PUBLIC;
+               b = new CodeBuilder.for_method (m);
+
+               b.open_switch (expression ("this"), null);
+               b.add_return (expression ("null"));
+               foreach (var enum_value in en.get_values ()) {
+                       string dbus_value = get_dbus_value (enum_value, enum_value.name);
+                       b.add_section (expression (@"$(en.get_full_name()).$(enum_value.name)"));
+                       b.add_return (expression (@"\"$dbus_value\""));
+               }
+               b.close ();
+
+               check (m);
+       }
+
+       public override void visit_enum (Enum en) {
+               if (!en.external && is_string_marshalled_enum (en) && context.has_package ("gio-2.0")) {
+                       add_enum_from_string_method (en);
+                       add_enum_to_string_method (en);
+               }
+               base.visit_enum (en);
+       }
+
+       public override void visit_cast_expression (CastExpression expr) {
                if (!(expr.inner.value_type.data_type == context.analyzer.gvariant_type.data_type && 
expr.type_reference.data_type != context.analyzer.gvariant_type.data_type)) {
+                       base.visit_cast_expression (expr);
                        return;
                }
 
@@ -414,7 +470,13 @@ public class Vala.GVariantTransformer : CodeTransformer {
 
                BasicTypeInfo basic_type;
                Expression result = null;
-               if (get_basic_type_info (get_type_signature (type), out basic_type)) {
+               if (is_string_marshalled_enum (type.data_type)) {
+                       get_basic_type_info ("s", out basic_type);
+                       result = deserialize_basic (basic_type, expr.inner);
+                       var call = (MethodCall) expression (@"$(type.data_type.get_full_name()).from_string 
()");
+                       call.add_argument (result);
+                       result = call;
+               } else if (get_basic_type_info (get_type_signature (type), out basic_type)) {
                        result = deserialize_basic (basic_type, expr.inner);
                } else if (type is ArrayType) {
                        result = deserialize_array ((ArrayType) type, expr.inner);
@@ -436,10 +498,9 @@ public class Vala.GVariantTransformer : CodeTransformer {
        }
 
        public override void visit_expression (Expression expr) {
-               base.visit_expression (expr);
-
                if (!(context.profile == Profile.GOBJECT && expr.target_type != null && 
expr.target_type.data_type == context.analyzer.gvariant_type.data_type && !(expr.value_type is NullType) && 
expr.value_type.data_type != context.analyzer.gvariant_type.data_type)) {
                        // no implicit gvariant boxing
+                       base.visit_expression (expr);
                        return;
                }
 
@@ -450,7 +511,10 @@ public class Vala.GVariantTransformer : CodeTransformer {
 
                BasicTypeInfo basic_type;
                Expression result = null;
-               if (get_basic_type_info (get_type_signature (type), out basic_type)) {
+               if (is_string_marshalled_enum (type.data_type)) {
+                       get_basic_type_info ("s", out basic_type);
+                       result = new MethodCall (new MemberAccess (expr, "to_string"), b.source_reference);
+               } else if (get_basic_type_info (get_type_signature (type), out basic_type)) {
                        result = serialize_basic (basic_type, expr);
                } else if (type is ArrayType) {
                        result = serialize_array ((ArrayType) type, expr);
diff --git a/vala/valacodebuilder.vala b/vala/valacodebuilder.vala
index b981bf2..ec7d370 100644
--- a/vala/valacodebuilder.vala
+++ b/vala/valacodebuilder.vala
@@ -48,6 +48,14 @@ public class Vala.CodeBuilder {
                build_context.check_nodes.add (build_context.current_block);
        }
 
+       public CodeBuilder.for_method (Method m) {
+               source_reference = m.source_reference;
+               build_context = new BuildContext ();
+               build_context.insert_block = m.body = new Block (source_reference);
+               build_context.insert_statement = build_context.current_block = new Block (source_reference);
+               m.body.add_statement (build_context.current_block);
+       }
+
        public void check (CodeTransformer transformer) {
                foreach (var node in build_context.check_nodes) {
                        transformer.check (node);
@@ -138,6 +146,56 @@ public class Vala.CodeBuilder {
                parent_block.add_statement (stmt);
        }
 
+       public void open_switch (Expression expression, Expression? first_label) {
+               var parent_block = build_context.current_block;
+
+               var stmt = new SwitchStatement (expression, source_reference);
+               build_context.statement_stack.add (stmt);
+
+               var section = new SwitchSection (source_reference);
+               SwitchLabel label;
+               if (first_label == null) {
+                       label = new SwitchLabel.with_default (source_reference);
+               } else {
+                       label = new SwitchLabel (first_label);
+               }
+               section.add_label (label);
+               build_context.current_block = section;
+               build_context.statement_stack.add (section);
+
+               parent_block.add_statement (stmt);
+               stmt.add_section (section);
+       }
+
+       public void add_section (Expression? expression) {
+               build_context.statement_stack.remove_at (build_context.statement_stack.size - 1);
+
+               var stmt = (SwitchStatement) build_context.statement_stack[build_context.statement_stack.size 
- 1];
+               var section = new SwitchSection (source_reference);
+               SwitchLabel label;
+               if (expression == null) {
+                       label = new SwitchLabel.with_default (source_reference);
+               } else {
+                       label = new SwitchLabel (expression);
+               }
+               section.add_label (label);
+               build_context.current_block = section;
+               build_context.statement_stack.add (section);
+
+               stmt.add_section (section);     
+       }
+
+       public void add_label (Expression? expression) {
+               var section = (SwitchSection) 
build_context.statement_stack[build_context.statement_stack.size - 1];
+               SwitchLabel label;
+               if (expression == null) {
+                       label = new SwitchLabel.with_default (source_reference);
+               } else {
+                       label = new SwitchLabel (expression);
+               }
+               section.add_label (label);
+       }
+
        public void add_statement (Statement statement) {
                build_context.current_block.add_statement (statement);
        }
@@ -150,6 +208,10 @@ public class Vala.CodeBuilder {
                add_expression (new Assignment (left, right, AssignmentOperator.SIMPLE, source_reference));
        }
 
+       public void add_throw (Expression expression) {
+               add_statement (new ThrowStatement (expression, source_reference));
+       }
+
        public void add_return (Expression? expression = null) {
                add_statement (new ReturnStatement (expression, source_reference));
        }
diff --git a/vala/valacodetransformer.vala b/vala/valacodetransformer.vala
index 47dc721..77c0dec 100644
--- a/vala/valacodetransformer.vala
+++ b/vala/valacodetransformer.vala
@@ -86,12 +86,17 @@ public class Vala.CodeTransformer : CodeVisitor {
        }
 
        // only qualified types, will slightly simplify the work of SymbolResolver
-       public DataType data_type (string s, bool value_owned = true) {
+       public DataType data_type (string s, bool value_owned = true, bool nullable = false) {
                DataType type = context.analyzer.get_data_type_for_symbol ((TypeSymbol) symbol_from_string 
(s));
                type.value_owned = value_owned;
+               type.nullable = nullable;
                return type;
        }
 
+       public Expression expression (string str) {
+               return new Parser().parse_expression_string (str, b.source_reference);
+       }
+
        public void check (CodeNode node) {
                node.accept (context.resolver);
                if (!node.check (context)) {


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