add CreationMethod type; restrict creation methods bodys to contain only
authorRaffaele Sandrini <rasa@gmx.ch>
Sat, 3 Mar 2007 22:07:17 +0000 (22:07 +0000)
committerRaffaele Sandrini <rasa@src.gnome.org>
Sat, 3 Mar 2007 22:07:17 +0000 (22:07 +0000)
2007-03-03  Raffaele Sandrini  <rasa@gmx.ch>

* vala/valaattributeprocessor.vala, vala/valamethod.vala,
  vala/valacodegenerator.vala, vala/valacreationmethod.vala,
  vala/valasymbolbuilder.vala, vala/valasemanticanalyzer.vala,
  vala/parser.y, vala/valacodevisitor.vala,
  vala/valainterfacewriter.vala, vala/valamemorymanager.vala:
  add CreationMethod type; restrict creation methods bodys to contain
  only property assignment statements
* vala/valacharacterliteral.vala, vala/valacodegenerator.vala,
  vala/valaarray.vala: fix the compiler to obey the new creation
  method rules
* vala/Makefile.am: update

svn path=/trunk/; revision=214

14 files changed:
vala/ChangeLog
vala/vala/Makefile.am
vala/vala/parser.y
vala/vala/valaarray.vala
vala/vala/valaattributeprocessor.vala
vala/vala/valacharacterliteral.vala
vala/vala/valacodegenerator.vala
vala/vala/valacodevisitor.vala
vala/vala/valacreationmethod.vala [new file with mode: 0644]
vala/vala/valainterfacewriter.vala
vala/vala/valamemorymanager.vala
vala/vala/valamethod.vala
vala/vala/valasemanticanalyzer.vala
vala/vala/valasymbolbuilder.vala

index 4adefd5..2f2ac3e 100644 (file)
@@ -1,3 +1,17 @@
+2007-03-03  Raffaele Sandrini  <rasa@gmx.ch>
+
+       * vala/valaattributeprocessor.vala, vala/valamethod.vala,
+         vala/valacodegenerator.vala, vala/valacreationmethod.vala,
+         vala/valasymbolbuilder.vala, vala/valasemanticanalyzer.vala,
+         vala/parser.y, vala/valacodevisitor.vala,
+         vala/valainterfacewriter.vala, vala/valamemorymanager.vala:
+         add CreationMethod type; restrict creation methods bodys to contain
+         only property assignment statements
+       * vala/valacharacterliteral.vala, vala/valacodegenerator.vala,
+         vala/valaarray.vala: fix the compiler to obey the new creation
+         method rules
+       * vala/Makefile.am: update
+
 2007-03-03  Jürg Billeter  <j@bitron.ch>
 
        * vapi/atk.vala, vapi/cairo.vala, vapi/gdk-2.0.vala, vapi/gtk+-2.0.vala,
index d54295e..304ef43 100644 (file)
@@ -91,6 +91,9 @@ libvala_la_SOURCES = \
        valacontinuestatement.c \
        valacontinuestatement.h \
        valacontinuestatement.vala \
+       valacreationmethod.c \
+       valacreationmethod.h \
+       valacreationmethod.vala \
        valadatatype.c \
        valadatatype.h \
        valadatatype.vala \
@@ -333,6 +336,7 @@ valainclude_HEADERS = \
        valaconstant.h \
        valaconstructor.h \
        valacontinuestatement.h \
+       valacreationmethod.h \
        valadatatype.h \
        valadeclarationstatement.h \
        valadestructor.h \
index 1543d4c..2c1a1c7 100644 (file)
@@ -2302,11 +2302,10 @@ method_header
                GList *l;
                
                ValaSourceReference *src = src_com(@5, $1);
-               $$ = vala_method_new ($6, NULL, src);
+               $$ = VALA_METHOD (vala_creation_method_new ($6, src));
                g_free ($5);
                g_free ($6);
                g_object_unref (src);
-               vala_method_set_construction ($$, TRUE);
                vala_method_set_instance ($$, FALSE);
                if ($3 != 0) {
                        $$->access = $3;
index 1c3c203..e318478 100644 (file)
@@ -53,20 +53,12 @@ public class Vala.Array : DataType {
                rank = _rank;
                element_type = _element_type;
                source_reference = _source_reference;
-               
-               if (_rank < 1) {
-                       Report.error (null, "internal: attempt to create an array with rank smaller than 1");
-               }
        }
        
        public Array.with_type_parameter (TypeParameter! _element_type_parameter, int _rank, SourceReference! _source_reference) {
                rank = _rank;
                element_type_parameter = _element_type_parameter;
                source_reference = _source_reference;
-               
-               if (_rank < 1) {
-                       Report.error (null, "internal: attempt to create an array with rank smaller than 1");
-               }
        }
 
        construct {
@@ -81,6 +73,10 @@ public class Vala.Array : DataType {
                        
                name = "%s[%s]".printf (element_type.name, commas); */
                
+               if (rank < 1) {
+                       Report.error (null, "internal: attempt to create an array with rank smaller than 1");
+               }
+               
                int i = rank - 1;
                if (element_type != null) {
                        name = "%s[".printf (element_type.name);
index 15c634a..57120b0 100644 (file)
@@ -58,6 +58,10 @@ public class Vala.AttributeProcessor : CodeVisitor {
        public override void visit_begin_method (Method! m) {
                m.process_attributes ();
        }
+       
+       public override void visit_begin_creation_method (CreationMethod! m) {
+               m.process_attributes ();
+       }
 
        public override void visit_begin_property (Property! prop) {
                prop.process_attributes ();
index e05fea6..a722939 100644 (file)
@@ -55,6 +55,9 @@ public class Vala.CharacterLiteral : Literal {
                value = c;
                source_reference = source;
 
+       }
+       
+       construct {
                if (error) {
                        Report.error (source_reference, "invalid character literal");
                }
index da80b3d..b01e3a6 100644 (file)
@@ -92,7 +92,9 @@ public class Vala.CodeGenerator : CodeVisitor {
        
        public CodeGenerator (bool manage_memory = true) {
                memory_management = manage_memory;
-               
+       }
+       
+       construct {
                predefined_marshal_list = new HashTable (str_hash, str_equal);
                predefined_marshal_list.insert ("VOID:VOID", true);
                predefined_marshal_list.insert ("VOID:BOOLEAN", true);
@@ -1253,11 +1255,11 @@ public class Vala.CodeGenerator : CodeVisitor {
                                }
                                source_type_member_definition.append (function);
                                
-                               if (m.construction && current_class != null) {
+                               if (m is CreationMethod && current_class != null) {
                                        // declare construction parameter array
                                        var cparamsinit = new CCodeFunctionCall (new CCodeIdentifier ("g_new0"));
                                        cparamsinit.add_argument (new CCodeIdentifier ("GParameter"));
-                                       cparamsinit.add_argument (new CCodeConstant (m.n_construction_params.to_string ()));
+                                       cparamsinit.add_argument (new CCodeConstant (((CreationMethod)m).n_construction_params.to_string ()));
                                        
                                        var cdecl = new CCodeDeclaration ("GParameter *");
                                        cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("__params", cparamsinit));
@@ -1316,7 +1318,7 @@ public class Vala.CodeGenerator : CodeVisitor {
                        source_type_member_definition.append (vfunc);
                }
                
-               if (m.construction) {
+               if (m is CreationMethod) {
                        var creturn = new CCodeReturnStatement ();
                        creturn.return_expression = new CCodeIdentifier ("self");
                        function.block.add_statement (creturn);
@@ -1348,6 +1350,15 @@ public class Vala.CodeGenerator : CodeVisitor {
                }
        }
        
+       public override void visit_begin_creation_method (CreationMethod! m) {
+               current_symbol = m.symbol;
+               current_return_type = m.return_type;
+       }
+       
+       public override void visit_end_creation_method (CreationMethod! m) {
+               visit_end_method (m);
+       }
+       
        private bool is_possible_entry_point (Method! m, ref bool return_value, ref bool args_parameter) {
                if (m.name == null || m.name != "main") {
                        // method must be called "main"
index f9bad7d..c0614d3 100644 (file)
@@ -210,6 +210,22 @@ public abstract class Vala.CodeVisitor {
         */
        public virtual void visit_end_method (Method! m) {
        }
+       
+       /**
+        * Visit operation called at beginning of creation methods.
+        *
+        * @param m a method
+        */
+       public virtual void visit_begin_creation_method (CreationMethod! m) {
+       }
+       
+       /**
+        * Visit operation called at end of creation methods.
+        *
+        * @param m a method
+        */
+       public virtual void visit_end_creation_method (CreationMethod! m) {
+       }
 
        /**
         * Visit operation called for formal parameters.
diff --git a/vala/vala/valacreationmethod.vala b/vala/vala/valacreationmethod.vala
new file mode 100644 (file)
index 0000000..de460c5
--- /dev/null
@@ -0,0 +1,80 @@
+/* valacreationmethod.vala
+ *
+ * Copyright (C) 2007  Raffaele Sandrini
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Raffaele Sandrini <j@bitron.ch>
+ */
+
+using GLib;
+
+/**
+ * Represents a type creation method.
+ */
+public class Vala.CreationMethod : Method {
+       /**
+        * Specifies the number of parameters this creation method sets.
+        */
+       public int n_construction_params { get; set; }
+       
+       private string cname;
+       
+       /**
+        * Creates a new method.
+        *
+        * @param name        method name
+        * @param source      reference to source code
+        * @return            newly created method
+        */
+       public CreationMethod (string _name, SourceReference source = null) {
+               name = _name;
+               source_reference = source;
+       }
+
+       public override void accept (CodeVisitor! visitor) {
+               visitor.visit_begin_creation_method (this);
+               
+               foreach (FormalParameter param in get_parameters()) {
+                       param.accept (visitor);
+               }
+               
+               if (body != null) {
+                       body.accept (visitor);
+               }
+
+               visitor.visit_end_creation_method (this);
+       }
+       
+       /**
+        * Returns the interface name of this method as it is used in C code.
+        *
+        * @return the name to be used in C code
+        */
+       public override string! get_cname () {
+               if (cname == null) {
+                       var parent = symbol.parent_symbol.node;
+                       if (parent is DataType) {
+                               if (name == null) {
+                                       cname = "%snew".printf (((DataType) parent).get_lower_case_cprefix ());
+                               } else {
+                                       cname = "%snew_%s".printf (((DataType) parent).get_lower_case_cprefix (), name);
+                               }
+                       }
+               }
+               return cname;
+       }
+}
index ce1af29..bdae1fb 100644 (file)
@@ -390,7 +390,7 @@ public class Vala.InterfaceWriter : CodeVisitor {
                write_indent ();
                write_string ("public");
                
-               if (m.construction) {
+               if (m is CreationMethod) {
                        write_string (" ");
                        var datatype = (DataType) m.symbol.parent_symbol.node;
                        write_identifier (datatype.name);
@@ -407,7 +407,7 @@ public class Vala.InterfaceWriter : CodeVisitor {
                        write_string (" virtual");
                }
                
-               if (!m.construction) {
+               if (!(m is CreationMethod)) {
                        write_string (" ");
 
                        var type = m.return_type.data_type;
@@ -441,6 +441,10 @@ public class Vala.InterfaceWriter : CodeVisitor {
 
                write_newline ();
        }
+       
+       public override void visit_begin_creation_method (CreationMethod! m) {
+               visit_begin_method (m);
+       }
 
        public override void visit_begin_property (Property! prop) {
                if (internal_scope) {
index d9070c7..bd0c27a 100644 (file)
@@ -74,6 +74,10 @@ public class Vala.MemoryManager : CodeVisitor {
                current_symbol = m.symbol;
        }
        
+       public override void visit_begin_creation_method (CreationMethod! m) {
+               current_symbol = m.symbol;
+       }
+       
        public override void visit_begin_property (Property! prop) {
                current_symbol = prop.symbol;
        }
index c2ffdb7..d8395ac 100644 (file)
@@ -77,16 +77,6 @@ public class Vala.Method : Member, Invokable {
         * of a base type.
         */
        public bool overrides { get; set; }
-       
-       /**
-        * Specifies whether this is a construction method.
-        */
-       public bool construction { get; set; }
-       
-       /**
-        * Specifies the number of parameters this construction method sets.
-        */
-       public int n_construction_params { get; set; }
 
        /**
         * Specifies whether the C method returns a new instance pointer which
@@ -207,19 +197,11 @@ public class Vala.Method : Member, Invokable {
         *
         * @return the name to be used in C code
         */
-       public string! get_cname () {
+       public virtual string! get_cname () {
                if (cname == null) {
                        var parent = symbol.parent_symbol.node;
                        if (parent is DataType) {
-                               if (construction) {
-                                       if (name == null) {
-                                               cname = "%snew".printf (((DataType) parent).get_lower_case_cprefix ());
-                                       } else {
-                                               cname = "%snew_%s".printf (((DataType) parent).get_lower_case_cprefix (), name);
-                                       }
-                               } else {
-                                       cname = "%s%s".printf (((DataType) parent).get_lower_case_cprefix (), name);
-                               }
+                               cname = "%s%s".printf (((DataType) parent).get_lower_case_cprefix (), name);
                        } else if (parent is Namespace) {
                                cname = "%s%s".printf (((Namespace) parent).get_lower_case_cprefix (), name);
                        } else {
index df0e79a..07a2ccc 100644 (file)
@@ -168,30 +168,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                }
        }
 
-       public override void visit_begin_method (Method! m) {
-               if (m.construction) {
-                       m.return_type = new TypeReference ();
-                       m.return_type.data_type = (DataType) current_symbol.node;
-                       m.return_type.transfers_ownership = true;
-                       
-                       if (current_symbol.node is Class) {
-                               // check for floating reference
-                               var cl = (Class) current_symbol.node;
-                               while (cl != null) {
-                                       if (cl == initially_unowned_type) {
-                                               m.return_type.floating_reference = true;
-                                               break;
-                                       }
-                               
-                                       cl = cl.base_class;
-                               }
-                       }
-                       
-                       if (m.body != null) {
-                               m.body.construction = true;
-                       }
-               }
-       
+       public override void visit_begin_method (Method! m) {   
                current_symbol = m.symbol;
                current_return_type = m.return_type;
                
@@ -259,13 +236,45 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                                return;
                        }
                }
+       }
+       
+       public override void visit_begin_creation_method (CreationMethod! m) {
+               m.return_type = new TypeReference ();
+               m.return_type.data_type = (DataType) current_symbol.node;
+               m.return_type.transfers_ownership = true;
+               
+               if (current_symbol.node is Class) {
+                       // check for floating reference
+                       var cl = (Class) current_symbol.node;
+                       while (cl != null) {
+                               if (cl == initially_unowned_type) {
+                                       m.return_type.floating_reference = true;
+                                       break;
+                               }
+                       
+                               cl = cl.base_class;
+                       }
+               }
+               
+               if (m.body != null) {
+                       m.body.construction = true;
+               }
                
-               if (m.construction && m.body != null) {
+               current_symbol = m.symbol;
+               current_return_type = m.return_type;
+       }
+       
+       public override void visit_end_creation_method (CreationMethod! m) {
+               visit_end_method (m);
+               
+               if (m.body != null) {
                        int n_params = 0;
                        foreach (Statement stmt in m.body.get_statements ()) {
                                int params = stmt.get_number_of_set_construction_parameters ();
                                if (params == -1) {
-                                       break;
+                                       m.error = true;
+                                       Report.error (stmt.source_reference, "type creation methods only allow property assignment statements");
+                                       return;
                                }
                                n_params += params;
                                stmt.construction = true;
@@ -1125,7 +1134,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                                type_node = constructor_node.symbol.parent_symbol.node;
                                
                                var constructor = (Method) constructor_node;
-                               if (!constructor.construction) {
+                               if (!(constructor_node is CreationMethod)) {
                                        expr.error = true;
                                        Report.error (expr.source_reference, "`%s' is not a construction method".printf (constructor.symbol.get_full_name ()));
                                        return;
index f5e7328..5104bd0 100644 (file)
@@ -186,23 +186,7 @@ public class Vala.SymbolBuilder : CodeVisitor {
                        return;
                }
                
-               if (m.construction) {
-                       var type_node = m.symbol.parent_symbol.node;
-                       if (!(type_node is Class || type_node is Struct)) {
-                               Report.error (m.source_reference, "construction methods may only be declared within classes and structs");
-                       
-                               m.error = true;
-                               return;
-                       }
-               
-                       if (m.name == null) {
-                               if (type_node is Class) {
-                                       ((Class) type_node).default_construction_method = m;
-                               } else if (type_node is Struct) {
-                                       ((Struct) type_node).default_construction_method = m;
-                               }
-                       }
-               } else if (m.instance) {
+               if (m.instance) {
                        if (!(m.symbol.parent_symbol.node is DataType)) {
                                Report.error (m.source_reference, "instance methods not allowed outside of data types");
                        
@@ -227,6 +211,39 @@ public class Vala.SymbolBuilder : CodeVisitor {
                
                current_symbol = current_symbol.parent_symbol;
        }
+       
+       public override void visit_begin_creation_method (CreationMethod! m) {
+               if (add_symbol (m.name, m) == null) {
+                       return;
+               }
+               
+               var type_node = m.symbol.parent_symbol.node;
+               if (!(type_node is Class || type_node is Struct)) {
+                       Report.error (m.source_reference, "construction methods may only be declared within classes and structs");
+               
+                       m.error = true;
+                       return;
+               }
+       
+               if (m.name == null) {
+                       if (type_node is Class) {
+                               ((Class) type_node).default_construction_method = m;
+                       } else if (type_node is Struct) {
+                               ((Struct) type_node).default_construction_method = m;
+                       }
+               }
+               
+               current_symbol = m.symbol;
+       }
+       
+       public override void visit_end_creation_method (CreationMethod! m) {
+               if (m.error) {
+                       /* skip methods with errors */
+                       return;
+               }
+               
+               current_symbol = current_symbol.parent_symbol;
+       }
 
        public override void visit_formal_parameter (FormalParameter! p) {
                if (!p.ellipsis) {