[vala] Support chain up to constructv functions.



commit ed8f32bd6696291a1bc49597b70c30335ec2917d
Author: Luca Bruno <lucabru src gnome org>
Date:   Sat Sep 21 11:34:06 2013 +0200

    Support chain up to constructv functions.

 codegen/valaccodebasemodule.vala       |   12 +++++++++
 codegen/valaccodemethodcallmodule.vala |   10 ++++++-
 codegen/valaccodemethodmodule.vala     |   18 ++------------
 tests/Makefile.am                      |    1 +
 tests/objects/chainup.vala             |   39 ++++++++++++++++++++++++++++++++
 vala/valaclass.vala                    |    4 +-
 vala/valamethodcall.vala               |   19 ++++++++++++++-
 vala/valasemanticanalyzer.vala         |    2 +
 8 files changed, 84 insertions(+), 21 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index e42c578..5cdd816 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -6205,6 +6205,18 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                return get_ccode_attribute(sym).real_name;
        }
 
+       public static string get_ccode_constructv_name (CreationMethod m) {
+               const string infix = "constructv";
+
+               var parent = m.parent_symbol as Class;
+
+               if (m.name == ".new") {
+                       return "%s%s".printf (get_ccode_lower_case_prefix (parent), infix);
+               } else {
+                       return "%s%s_%s".printf (get_ccode_lower_case_prefix (parent), infix, m.name);
+               }
+       }
+
        public static string get_ccode_vfunc_name (Method m) {
                return get_ccode_attribute(m).vfunc_name;
        }
diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala
index 0bd462a..728dccd 100644
--- a/codegen/valaccodemethodcallmodule.vala
+++ b/codegen/valaccodemethodcallmodule.vala
@@ -48,6 +48,8 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                // Enum.VALUE.to_string()
                                var en = (Enum) ma.inner.value_type.data_type;
                                ccall.call = new CCodeIdentifier (generate_enum_tostring_function (en));
+                       } else if (expr.is_constructv_chainup) {
+                               ccall.call = new CCodeIdentifier (get_ccode_constructv_name ((CreationMethod) 
m));
                        }
                } else if (itype is SignalType) {
                        var sig_type = (SignalType) itype;
@@ -61,7 +63,11 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                        var cl = (Class) ((ObjectType) itype).type_symbol;
                        m = cl.default_construction_method;
                        generate_method_declaration (m, cfile);
-                       ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_real_name (m)));
+                       var real_name = get_ccode_real_name (m);
+                       if (expr.is_constructv_chainup) {
+                               real_name = get_ccode_constructv_name ((CreationMethod) m);
+                       }
+                       ccall = new CCodeFunctionCall (new CCodeIdentifier (real_name));
                } else if (itype is StructValueType) {
                        // constructor
                        var st = (Struct) ((StructValueType) itype).type_symbol;
@@ -598,7 +604,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                         * except when using printf-style arguments */
                        if (m == null) {
                                in_arg_map.set (get_param_pos (-1, true), new CCodeConstant ("NULL"));
-                       } else if (!m.printf_format && !m.scanf_format && get_ccode_sentinel (m) != "") {
+                       } else if (!m.printf_format && !m.scanf_format && get_ccode_sentinel (m) != "" && 
!expr.is_constructv_chainup) {
                                in_arg_map.set (get_param_pos (-1, true), new CCodeConstant 
(get_ccode_sentinel (m)));
                        }
                }
diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala
index f0cddae..c7c7818 100644
--- a/codegen/valaccodemethodmodule.vala
+++ b/codegen/valaccodemethodmodule.vala
@@ -204,7 +204,7 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
 
                        if (m.is_variadic ()) {
                                // _constructv function
-                               function = new CCodeFunction (get_constructv_name ((CreationMethod) m));
+                               function = new CCodeFunction (get_ccode_constructv_name ((CreationMethod) m));
 
                                cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
                                generate_cparameters (m, decl_space, cparam_map, function);
@@ -214,18 +214,6 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
                }
        }
 
-       private string get_constructv_name (CreationMethod m) {
-               const string infix = "constructv";
-
-               var parent = m.parent_symbol as Class;
-
-               if (m.name == ".new") {
-                       return "%s%s".printf (CCodeBaseModule.get_ccode_lower_case_prefix (parent), infix);
-               } else {
-                       return "%s%s_%s".printf (CCodeBaseModule.get_ccode_lower_case_prefix (parent), infix, 
m.name);
-               }
-       }
-
        void register_plugin_types (Symbol sym, Set<Symbol> registered_types) {
                var ns = sym as Namespace;
                var cl = sym as Class;
@@ -289,7 +277,7 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
        public override void visit_method (Method m) {
                string real_name = get_ccode_real_name (m);
                if (m is CreationMethod && m.is_variadic ()) {
-                       real_name = get_constructv_name ((CreationMethod) m);
+                       real_name = get_ccode_constructv_name ((CreationMethod) m);
                }
 
                push_context (new EmitContext (m));
@@ -1182,7 +1170,7 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
 
                push_function (vfunc);
 
-               string constructor = (m.is_variadic ()) ? get_constructv_name (m) : get_ccode_real_name (m);
+               string constructor = (m.is_variadic ()) ? get_ccode_constructv_name (m) : get_ccode_real_name 
(m);
                var vcall = new CCodeFunctionCall (new CCodeIdentifier (constructor));
 
                if (self_as_first_parameter) {
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b84ee04..b84d433 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -100,6 +100,7 @@ TESTS = \
        delegates/bug638415.vala \
        delegates/bug639751.vala \
        delegates/bug703804.vala \
+       objects/chainup.vala \
        objects/classes.vala \
        objects/fields.vala \
        objects/interfaces.vala \
diff --git a/tests/objects/chainup.vala b/tests/objects/chainup.vala
new file mode 100644
index 0000000..fdca08d
--- /dev/null
+++ b/tests/objects/chainup.vala
@@ -0,0 +1,39 @@
+class FooBase {
+       public int bar;
+
+       public FooBase (int _, ...) {
+               va_list v = va_list ();
+               bar = v.arg ();
+       }
+
+       public FooBase.baz (int _, ...) {
+               va_list v = va_list ();
+               this (_, v);
+       }
+}
+
+class Foo : FooBase {
+       public Foo (int _, ...) {
+               va_list v = va_list ();
+               base (_, v);
+       }
+
+       public Foo.baz (int _, ...) {
+               va_list v = va_list ();
+               base.baz (_, v);
+       }
+
+       public Foo.qux (int _, ...) {
+               va_list v = va_list ();
+               this.baz (_, v);
+       }
+}
+
+void main () {
+       var foo = new Foo (0, 10);
+       assert (foo.bar == 10);
+       foo = new Foo.baz (0, 20);
+       assert (foo.bar == 20);
+       foo = new Foo.qux (0, 30);
+       assert (foo.bar == 30);
+}
diff --git a/vala/valaclass.vala b/vala/valaclass.vala
index 5110a7a..ba23a50 100644
--- a/vala/valaclass.vala
+++ b/vala/valaclass.vala
@@ -151,7 +151,7 @@ public class Vala.Class : ObjectTypeSymbol {
        /**
         * Specifies the default construction method.
         */
-       public Method default_construction_method { get; set; }
+       public CreationMethod default_construction_method { get; set; }
        
        /**
         * Specifies the instance constructor.
@@ -303,7 +303,7 @@ public class Vala.Class : ObjectTypeSymbol {
                }
                if (m is CreationMethod) {
                        if (m.name == null) {
-                               default_construction_method = m;
+                               default_construction_method = (CreationMethod) m;
                                m.name = ".new";
                        }
 
diff --git a/vala/valamethodcall.vala b/vala/valamethodcall.vala
index 5b0ba8a..89d2ba5 100644
--- a/vala/valamethodcall.vala
+++ b/vala/valamethodcall.vala
@@ -41,6 +41,11 @@ public class Vala.MethodCall : Expression {
 
        public bool is_assert { get; private set; }
 
+       /**
+        * Whether this chain up uses the constructv function with va_list.
+        */
+       public bool is_constructv_chainup { get; private set; }
+
        public Expression _call;
        
        private List<Expression> argument_list = new ArrayList<Expression> ();
@@ -213,6 +218,8 @@ public class Vala.MethodCall : Expression {
 
                var mtype = call.value_type;
 
+               CreationMethod base_cm = null;
+
                if (mtype is ObjectType || call.symbol_reference == context.analyzer.object_type) {
                        // constructor chain-up
                        var cm = context.analyzer.find_current_method () as CreationMethod;
@@ -230,7 +237,7 @@ public class Vala.MethodCall : Expression {
                        if (mtype is ObjectType) {
                                var otype = (ObjectType) mtype;
                                var cl = (Class) otype.type_symbol;
-                               var base_cm = cl.default_construction_method;
+                               base_cm = cl.default_construction_method;
                                if (base_cm == null) {
                                        error = true;
                                        Report.error (source_reference, "chain up to `%s' not 
supported".printf (cl.get_full_name ()));
@@ -301,7 +308,7 @@ public class Vala.MethodCall : Expression {
                        }
                        cm.chain_up = true;
 
-                       var base_cm = (CreationMethod) call.symbol_reference;
+                       base_cm = (CreationMethod) call.symbol_reference;
                        if (!base_cm.has_construct_function) {
                                error = true;
                                Report.error (source_reference, "chain up to `%s' not supported".printf 
(base_cm.get_full_name ()));
@@ -720,6 +727,14 @@ public class Vala.MethodCall : Expression {
                        return false;
                }
 
+               /* Check for constructv chain up */
+               if (base_cm != null && base_cm.is_variadic () && args.size == base_cm.get_parameters ().size) 
{
+                       var this_last_arg = args[args.size-1];
+                       if (this_last_arg.value_type is StructValueType && this_last_arg.value_type.data_type 
== context.analyzer.va_list_type.data_type) {
+                               is_constructv_chainup = true;
+                       }
+               }
+
                if (may_throw) {
                        if (parent_node is LocalVariable || parent_node is ExpressionStatement) {
                                // simple statements, no side effects after method call
diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala
index 90923ac..8244896 100644
--- a/vala/valasemanticanalyzer.vala
+++ b/vala/valasemanticanalyzer.vala
@@ -150,6 +150,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        public DataType unichar_type;
        public DataType double_type;
        public DataType type_type;
+       public DataType va_list_type;
        public Class object_type;
        public StructValueType gvalue_type;
        public ObjectType gvariant_type;
@@ -196,6 +197,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                size_t_type = new IntegerType ((Struct) root_symbol.scope.lookup ("size_t"));
                ssize_t_type = new IntegerType ((Struct) root_symbol.scope.lookup ("ssize_t"));
                double_type = new FloatingType ((Struct) root_symbol.scope.lookup ("double"));
+               va_list_type = new StructValueType ((Struct) root_symbol.scope.lookup ("va_list"));
 
                var unichar_struct = (Struct) root_symbol.scope.lookup ("unichar");
                if (unichar_struct != null) {


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