]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Support chaining constructors using `base' and `this'
authorJürg Billeter <j@bitron.ch>
Sat, 11 Oct 2008 11:03:30 +0000 (11:03 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Sat, 11 Oct 2008 11:03:30 +0000 (11:03 +0000)
2008-10-11  Jürg Billeter  <j@bitron.ch>

* vala/valaclass.vala:
* vala/valacreationmethod.vala:
* vala/valainterfacewriter.vala:
* vala/valaobjecttype.vala:
* vala/valasemanticanalyzer.vala:
* vala/valastruct.vala:
* gobject/valaccodeinvocationexpressionbinding.vala:
* gobject/valaccodemethodbinding.vala:
* gobject/valagidlwriter.vala:

Support chaining constructors using `base' and `this'

svn path=/trunk/; revision=1829

ChangeLog
gobject/valaccodeinvocationexpressionbinding.vala
gobject/valaccodemethodbinding.vala
gobject/valagidlwriter.vala
vala/valaclass.vala
vala/valacreationmethod.vala
vala/valainterfacewriter.vala
vala/valaobjecttype.vala
vala/valasemanticanalyzer.vala
vala/valastruct.vala

index d1d150dc7cef78cc1c839be0092de69bb97822c6..00ffbb35cbe84fedc5201ada9d92e5ab0320ea67 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2008-10-11  Jürg Billeter  <j@bitron.ch>
+
+       * vala/valaclass.vala:
+       * vala/valacreationmethod.vala:
+       * vala/valainterfacewriter.vala:
+       * vala/valaobjecttype.vala:
+       * vala/valasemanticanalyzer.vala:
+       * vala/valastruct.vala:
+       * gobject/valaccodeinvocationexpressionbinding.vala:
+       * gobject/valaccodemethodbinding.vala:
+       * gobject/valagidlwriter.vala:
+
+       Support chaining constructors using `base' and `this'
+
 2008-10-11  Jürg Billeter  <j@bitron.ch>
 
        * vala/valacfgbuilder.vala:
index 79d9ab2e925107669ee4903c86970bab36828c5c..342263dd29c87487a25bd375e2d5321565b3d639 100644 (file)
@@ -53,6 +53,12 @@ public class Vala.CCodeInvocationExpressionBinding : CCodeExpressionBinding {
                        m = ((MethodType) itype).method_symbol;
                } else if (itype is SignalType) {
                        ccall = (CCodeFunctionCall) expr.call.ccodenode;
+               } else if (itype is ObjectType) {
+                       // constructor
+                       var cl = (Class) ((ObjectType) itype).type_symbol;
+                       m = cl.default_construction_method;
+                       ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_real_cname ()));
+                       ccall.add_argument (new CCodeIdentifier ("object_type"));
                }
 
                // the complete call expression, might include casts, comma expressions, and/or assignments
@@ -152,6 +158,8 @@ public class Vala.CCodeInvocationExpressionBinding : CCodeExpressionBinding {
                                param.accept (codegen);
                        }
                        codegen.dynamic_method_binding ((DynamicMethod) m).generate_wrapper ();
+               } else if (m is CreationMethod) {
+                       ccall_expr = new CCodeAssignment (new CCodeIdentifier ("self"), new CCodeCastExpression (ccall, codegen.current_class.get_cname () + "*"));
                }
 
                bool ellipsis = false;
index ae3bfd8ad2c21b866d9bded7609a3a77ba33b300..e0b2316fe4e0202cbe5564634733d32e90948e65 100644 (file)
@@ -100,24 +100,31 @@ public class Vala.CCodeMethodBinding : CCodeBinding {
                        if (in_gobject_creation_method && m.body != null) {
                                var cblock = new CCodeBlock ();
 
-                               // set construct properties
-                               foreach (CodeNode stmt in m.body.get_statements ()) {
-                                       var expr_stmt = stmt as ExpressionStatement;
-                                       if (expr_stmt != null) {
-                                               var prop = expr_stmt.assigned_property ();
-                                               if (prop != null && prop.set_accessor.construction) {
-                                                       if (stmt.ccodenode is CCodeFragment) {
-                                                               foreach (CCodeNode cstmt in ((CCodeFragment) stmt.ccodenode).get_children ()) {
-                                                                       cblock.add_statement (cstmt);
+                               if (!((CreationMethod) m).chain_up) {
+                                       // set construct properties
+                                       foreach (CodeNode stmt in m.body.get_statements ()) {
+                                               var expr_stmt = stmt as ExpressionStatement;
+                                               if (expr_stmt != null) {
+                                                       var prop = expr_stmt.assigned_property ();
+                                                       if (prop != null && prop.set_accessor.construction) {
+                                                               if (stmt.ccodenode is CCodeFragment) {
+                                                                       foreach (CCodeNode cstmt in ((CCodeFragment) stmt.ccodenode).get_children ()) {
+                                                                               cblock.add_statement (cstmt);
+                                                                       }
+                                                               } else {
+                                                                       cblock.add_statement (stmt.ccodenode);
                                                                }
-                                                       } else {
-                                                               cblock.add_statement (stmt.ccodenode);
                                                        }
                                                }
                                        }
-                               }
 
-                               add_object_creation (cblock, ((CreationMethod) m).n_construction_params > 0 || codegen.current_class.get_type_parameters ().size > 0);
+                                       add_object_creation (cblock, ((CreationMethod) m).n_construction_params > 0 || codegen.current_class.get_type_parameters ().size > 0);
+                               } else {
+                                       var cdeclaration = new CCodeDeclaration ("%s *".printf (((Class) codegen.current_type_symbol).get_cname ()));
+                                       cdeclaration.add_declarator (new CCodeVariableDeclarator ("self"));
+               
+                                       cblock.add_statement (cdeclaration);
+                               }
 
                                // other initialization code
                                foreach (CodeNode stmt in m.body.get_statements ()) {
index c0c9592d0e78a6ae46dbcb1641a76f0455549549..4944ccc1a121f60f2f4eca12a4207ceff0b04bc0 100644 (file)
@@ -406,13 +406,8 @@ public class Vala.GIdlWriter : CodeVisitor {
                        return;
                }
 
-               string name = "new";
-               if (m.name.has_prefix (".new.")) {
-                       name = m.name.substring (5, m.name.len () - 5);
-               }
-
                write_indent ();
-               stream.printf ("<constructor name=\"%s\" symbol=\"%s\"", name, m.get_cname ());
+               stream.printf ("<constructor name=\"%s\" symbol=\"%s\"", m.name, m.get_cname ());
                stream.printf (">\n");
                indent++;
 
index f259ec1674e32e87c85a29a2ce50bbc32a8a31a9..6a2b712b7ca498d36f15debc72b0164a9478f382 100644 (file)
@@ -318,9 +318,7 @@ public class Vala.Class : ObjectTypeSymbol {
                if (m is CreationMethod) {
                        if (m.name == null) {
                                default_construction_method = m;
-                               m.name = ".new";
-                       } else {
-                               m.name = ".new." + m.name;
+                               m.name = "new";
                        }
 
                        var cm = (CreationMethod) m;
index 5cb194b7b70c3fd6065e388ed04ee47a7d9e0fed..8336e96c93094386f6dae02ebc95a203c39a51f2 100644 (file)
@@ -45,6 +45,12 @@ public class Vala.CreationMethod : Method {
         */
        public string? custom_return_type_cname { get; set; }
 
+       /**
+        * Specifies whether this constructor chains up to a base
+        * constructor or a different constructor of the same class.
+        */
+       public bool chain_up { get; set; }
+
        /**
         * Creates a new method.
         *
@@ -89,10 +95,10 @@ public class Vala.CreationMethod : Method {
                        infix = "init";
                }
 
-               if (name.len () == ".new".len ()) {
+               if (name == "new") {
                        return "%s%s".printf (parent.get_lower_case_cprefix (), infix);
                } else {
-                       return "%s%s_%s".printf (parent.get_lower_case_cprefix (), infix, name.offset (".new.".len ()));
+                       return "%s%s_%s".printf (parent.get_lower_case_cprefix (), infix, name);
                }
        }
 
@@ -109,10 +115,10 @@ public class Vala.CreationMethod : Method {
 
                string infix = "construct";
 
-               if (name.len () == ".new".len ()) {
+               if (name == "new") {
                        return "%s%s".printf (parent.get_lower_case_cprefix (), infix);
                } else {
-                       return "%s%s_%s".printf (parent.get_lower_case_cprefix (), infix, name.offset (".new.".len ()));
+                       return "%s%s_%s".printf (parent.get_lower_case_cprefix (), infix, name);
                }
        }
 }
index 85ec0dd6d4b9fcf50553c0fee3f3e3dd7c7ddeb8..3a83a255c302c8a80f8bc577a803d45ce2645497 100644 (file)
@@ -815,7 +815,10 @@ public class Vala.InterfaceWriter : CodeVisitor {
                if (m is CreationMethod) {
                        var datatype = (TypeSymbol) m.parent_symbol;
                        write_identifier (datatype.name);
-                       write_identifier (m.name.offset (".new".len ()));
+                       if (m.name != "new") {
+                               write_string (".");
+                               write_identifier (m.name);
+                       }
                        write_string (" ");
                } else if (m.binding == MemberBinding.STATIC) {
                        write_string ("static ");
index 953b4883b136c1060a50ad34291fa905c7562bcc..a8aa9dd04b346447030e9ee4c5a49560453b6b4c 100644 (file)
@@ -71,4 +71,31 @@ public class Vala.ObjectType : ReferenceType {
 
                return type_symbol.is_subtype_of (obj_target_type.type_symbol);
        }
+
+       public override bool is_invokable () {
+               var cl = type_symbol as Class;
+               if (cl != null && cl.default_construction_method != null) {
+                       return true;
+               } else {
+                       return false;
+               }
+       }
+
+       public override DataType? get_return_type () {
+               var cl = type_symbol as Class;
+               if (cl != null && cl.default_construction_method != null) {
+                       return cl.default_construction_method.return_type;
+               } else {
+                       return null;
+               }
+       }
+
+       public override Gee.List<FormalParameter>? get_parameters () {
+               var cl = type_symbol as Class;
+               if (cl != null && cl.default_construction_method != null) {
+                       return cl.default_construction_method.get_parameters ();
+               } else {
+                       return null;
+               }
+       }
 }
index 020815c85027212667e5ca3477b4f00e791f9810..f45c6e406406e6e92f89c96452c09e83577783b1 100644 (file)
@@ -1641,11 +1641,6 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        if (expr.inner is MemberAccess || expr.inner is BaseAccess) {
                                base_symbol = expr.inner.symbol_reference;
 
-                               if (expr.creation_member && base_symbol is TypeSymbol) {
-                                       // check for named creation method
-                                       expr.symbol_reference = base_symbol.scope.lookup (".new." + expr.member_name);
-                               }
-
                                if (expr.symbol_reference == null && (base_symbol is Namespace || base_symbol is TypeSymbol)) {
                                        expr.symbol_reference = base_symbol.scope.lookup (expr.member_name);
                                        if (expr.inner is BaseAccess) {
@@ -1672,11 +1667,6 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                                }
                        }
 
-                       if (expr.symbol_reference == null && expr.inner is MemberAccess && base_symbol is Struct) {
-                               // check for named struct creation method
-                               expr.symbol_reference = base_symbol.scope.lookup (".new." + expr.member_name);
-                       }
-
                        if (expr.symbol_reference == null && expr.inner.value_type != null && expr.inner.value_type.is_dynamic) {
                                // allow late bound members for dynamic types
                                var dynamic_object_type = (ObjectType) expr.inner.value_type;
@@ -1934,9 +1924,22 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
 
                var mtype = expr.call.value_type;
 
+               if (mtype is ObjectType) {
+                       // constructor chain-up
+                       var cm = find_current_method () as CreationMethod;
+                       assert (cm != null);
+                       if (cm.chain_up) {
+                               expr.error = true;
+                               Report.error (expr.source_reference, "Multiple constructor calls in the same constructor are not permitted");
+                               return;
+                       }
+                       cm.chain_up = true;
+               }
+
                // check for struct construction
                if (expr.call is MemberAccess &&
-                   (expr.call.symbol_reference is CreationMethod
+                   ((expr.call.symbol_reference is CreationMethod
+                     && expr.call.symbol_reference.parent_symbol is Struct)
                     || expr.call.symbol_reference is Struct)) {
                        var struct_creation_expression = new ObjectCreationExpression ((MemberAccess) expr.call, expr.source_reference);
                        struct_creation_expression.struct_creation = true;
@@ -1948,6 +1951,17 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        expr.parent_node.replace_expression (expr, struct_creation_expression);
                        struct_creation_expression.accept (this);
                        return;
+               } else if (expr.call is MemberAccess
+                          && expr.call.symbol_reference is CreationMethod) {
+                       // constructor chain-up
+                       var cm = find_current_method () as CreationMethod;
+                       assert (cm != null);
+                       if (cm.chain_up) {
+                               expr.error = true;
+                               Report.error (expr.source_reference, "Multiple constructor calls in the same constructor are not permitted");
+                               return;
+                       }
+                       cm.chain_up = true;
                }
 
                Gee.List<FormalParameter> params;
@@ -2673,7 +2687,11 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
 
                                expr.symbol_reference = constructor;
 
-                               type_args = ((MemberAccess) expr.member_name.inner).get_type_arguments ();
+                               // inner expression can also be base access when chaining constructors
+                               var ma = expr.member_name.inner as MemberAccess;
+                               if (ma != null) {
+                                       type_args = ma.get_type_arguments ();
+                               }
                        } else if (constructor_sym is ErrorCode) {
                                type_sym = constructor_sym.parent_symbol;
 
index 74d8297dae9212ea38a8a313a486d0e075041dff..9e3850591ce1b2774e1cec4d49791ddaf49a2264 100644 (file)
@@ -148,9 +148,7 @@ public class Vala.Struct : TypeSymbol {
                if (m is CreationMethod) {
                        if (m.name == null) {
                                default_construction_method = m;
-                               m.name = ".new";
-                       } else {
-                               m.name = ".new." + m.name;
+                               m.name = "new";
                        }
 
                        var cm = (CreationMethod) m;