don't require `new' operator for struct initialization, fixes bug 526547
authorJuerg Billeter <j@bitron.ch>
Mon, 14 Apr 2008 06:15:19 +0000 (06:15 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Mon, 14 Apr 2008 06:15:19 +0000 (06:15 +0000)
2008-04-14  Juerg Billeter  <j@bitron.ch>

* vala/valaobjectcreationexpression.vala, vala/valaparser.vala,
  vala/valasemanticanalyzer.vala: don't require `new' operator for
  struct initialization, fixes bug 526547

* tests/structs.vala: port to new syntax

svn path=/trunk/; revision=1219

ChangeLog
tests/structs.vala
vala/valaobjectcreationexpression.vala
vala/valaparser.vala
vala/valasemanticanalyzer.vala

index 1bd8d3c..59be670 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2008-04-14  Jürg Billeter  <j@bitron.ch>
+
+       * vala/valaobjectcreationexpression.vala, vala/valaparser.vala,
+         vala/valasemanticanalyzer.vala: don't require `new' operator for
+         struct initialization, fixes bug 526547
+
+       * tests/structs.vala: port to new syntax
+
 2008-04-13  Jürg Billeter  <j@bitron.ch>
 
        * gobject/valaccodegeneratormethod.vala: remove warning about
index 5f096f8..85db4a8 100644 (file)
@@ -35,7 +35,7 @@ static class StructsTest {
        }
 
        static void test_out_parameter (out SimpleStruct st) {
-               st = new SimpleStruct ();
+               st = SimpleStruct ();
                st.field = 3;
        }
 
@@ -43,16 +43,16 @@ static class StructsTest {
                stdout.printf ("Structs Test:\n");
 
                stdout.printf ("new SimpleStruct ()\n");
-               var simple_struct = new SimpleStruct ();
+               var simple_struct = SimpleStruct ();
                stdout.printf ("new PublicStruct ()\n");
-               var public_struct = new PublicStruct ();
+               var public_struct = PublicStruct ();
                stdout.printf ("new StructWithCreationMethod ()\n");
-               var struct_with_creation_method = new StructWithCreationMethod ();
+               var struct_with_creation_method = StructWithCreationMethod ();
                stdout.printf ("new StructWithNamedCreationMethod ()\n");
-               var struct_with_named_creation_method = new StructWithNamedCreationMethod.named ();
+               var struct_with_named_creation_method = StructWithNamedCreationMethod.named ();
 
                stdout.printf ("new SimpleStruct () { field = 1 }\n");
-               simple_struct = new SimpleStruct () { field = 1 };
+               simple_struct = SimpleStruct () { field = 1 };
                stdout.printf ("simple_struct.field = %d\n", simple_struct.field);
 
                test_in_parameter (simple_struct);
index 97653d4..fb59e02 100644 (file)
@@ -50,6 +50,8 @@ public class Vala.ObjectCreationExpression : Expression {
         */
        public MemberAccess member_name { get; set; }
 
+       public bool struct_creation { get; set; }
+
        private Gee.List<Expression> argument_list = new ArrayList<Expression> ();
 
        private Gee.List<MemberInitializer> object_initializer = new ArrayList<MemberInitializer> ();
index 0f67b22..503d61e 100644 (file)
@@ -537,12 +537,29 @@ public class Vala.Parser : CodeVisitor {
                expect (TokenType.OPEN_PARENS);
                var arg_list = parse_argument_list ();
                expect (TokenType.CLOSE_PARENS);
+               var init_list = parse_object_initializer ();
 
-               var expr = context.create_invocation_expression (inner, get_src (begin));
-               foreach (Expression arg in arg_list) {
-                       expr.add_argument (arg);
+               if (init_list.size > 0 && inner is MemberAccess) {
+                       // struct creation expression
+                       var member = (MemberAccess) inner;
+                       member.creation_member = true;
+
+                       var expr = context.create_object_creation_expression (member, get_src (begin));
+                       expr.struct_creation = true;
+                       foreach (Expression arg in arg_list) {
+                               expr.add_argument (arg);
+                       }
+                       foreach (MemberInitializer initializer in init_list) {
+                               expr.add_member_initializer (initializer);
+                       }
+                       return expr;
+               } else {
+                       var expr = context.create_invocation_expression (inner, get_src (begin));
+                       foreach (Expression arg in arg_list) {
+                               expr.add_argument (arg);
+                       }
+                       return expr;
                }
-               return expr;
        }
 
        Expression parse_element_access (SourceLocation begin, Expression inner) throws ParseError {
@@ -1048,7 +1065,7 @@ public class Vala.Parser : CodeVisitor {
                        if (operator != AssignmentOperator.NONE) {
                                next ();
                                var rhs = parse_expression ();
-                               expr = context.create_assignment (expr, rhs, operator);
+                               expr = context.create_assignment (expr, rhs, operator, get_src (begin));
                        } else if (current () == TokenType.OP_GT) { // >>=
                                char* first_gt_pos = tokens[index].begin.pos;
                                next ();
@@ -1056,7 +1073,7 @@ public class Vala.Parser : CodeVisitor {
                                if (current () == TokenType.OP_GE && tokens[index].begin.pos == first_gt_pos + 1) {
                                        next ();
                                        var rhs = parse_expression ();
-                                       expr = context.create_assignment (expr, rhs, AssignmentOperator.SHIFT_RIGHT);
+                                       expr = context.create_assignment (expr, rhs, AssignmentOperator.SHIFT_RIGHT, get_src (begin));
                                } else {
                                        prev ();
                                        break;
index ecebf76..3172ff0 100644 (file)
@@ -1551,6 +1551,11 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                                        may_access_instance_members = true;
                                }
                        }
+
+                       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) {
@@ -1682,6 +1687,20 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
 
                var mtype = expr.call.static_type;
 
+               // check for struct construction
+               if (expr.call is MemberAccess &&
+                   (expr.call.symbol_reference is CreationMethod
+                    || expr.call.symbol_reference is Struct)) {
+                       var struct_creation_expression = context.create_object_creation_expression ((MemberAccess) expr.call, expr.source_reference);
+                       struct_creation_expression.struct_creation = true;
+                       foreach (Expression arg in expr.get_argument_list ()) {
+                               struct_creation_expression.add_argument (arg);
+                       }
+                       expr.parent_node.replace_expression (expr, struct_creation_expression);
+                       struct_creation_expression.accept (this);
+                       return;
+               }
+
                Collection<FormalParameter> params;
 
                if (mtype != null && mtype.is_invokable ()) {
@@ -2211,6 +2230,12 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                if (type is Class) {
                        var cl = (Class) type;
 
+                       if (expr.struct_creation) {
+                               expr.error = true;
+                               Report.error (expr.source_reference, "syntax error, use `new' to create new objects");
+                               return;
+                       }
+
                        if (cl.is_abstract) {
                                expr.static_type = null;
                                expr.error = true;
@@ -2233,6 +2258,10 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                } else if (type is Struct) {
                        var st = (Struct) type;
 
+                       if (!expr.struct_creation) {
+                               Report.warning (expr.source_reference, "deprecated syntax, don't use `new' to initialize structs");
+                       }
+
                        expr.static_type.transfers_ownership = false;
 
                        if (expr.symbol_reference == null) {
@@ -2291,38 +2320,42 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                }
 
                foreach (MemberInitializer init in expr.get_object_initializer ()) {
-                       init.accept (this);
+                       visit_member_initializer (init, expr.type_reference);
+               }
+       }
 
-                       init.symbol_reference = symbol_lookup_inherited (expr.type_reference.data_type, init.name);
-                       if (!(init.symbol_reference is Field || init.symbol_reference is Property)) {
-                               expr.error = true;
-                               Report.error (expr.source_reference, "Invalid member `%s' in `%s'".printf (init.name, expr.type_reference.data_type.get_full_name ()));
-                               return;
-                       }
-                       if (init.symbol_reference.access != SymbolAccessibility.PUBLIC) {
-                               expr.error = true;
-                               Report.error (expr.source_reference, "Access to private member `%s' denied".printf (init.symbol_reference.get_full_name ()));
-                               return;
-                       }
-                       DataType member_type;
-                       if (init.symbol_reference is Field) {
-                               var f = (Field) init.symbol_reference;
-                               member_type = f.type_reference;
-                       } else if (init.symbol_reference is Property) {
-                               var prop = (Property) init.symbol_reference;
-                               member_type = prop.type_reference;
-                               if (prop.set_accessor == null || !prop.set_accessor.writable) {
-                                       expr.error = true;
-                                       Report.error (expr.source_reference, "Property `%s' is read-only".printf (prop.get_full_name ()));
-                                       return;
-                               }
-                       }
-                       if (init.initializer.static_type == null || !init.initializer.static_type.compatible (member_type)) {
-                               expr.error = true;
-                               Report.error (init.source_reference, "Invalid type for member `%s'".printf (init.name));
+       void visit_member_initializer (MemberInitializer init, DataType type) {
+               init.accept (this);
+
+               init.symbol_reference = symbol_lookup_inherited (type.data_type, init.name);
+               if (!(init.symbol_reference is Field || init.symbol_reference is Property)) {
+                       init.error = true;
+                       Report.error (init.source_reference, "Invalid member `%s' in `%s'".printf (init.name, type.data_type.get_full_name ()));
+                       return;
+               }
+               if (init.symbol_reference.access != SymbolAccessibility.PUBLIC) {
+                       init.error = true;
+                       Report.error (init.source_reference, "Access to private member `%s' denied".printf (init.symbol_reference.get_full_name ()));
+                       return;
+               }
+               DataType member_type;
+               if (init.symbol_reference is Field) {
+                       var f = (Field) init.symbol_reference;
+                       member_type = f.type_reference;
+               } else if (init.symbol_reference is Property) {
+                       var prop = (Property) init.symbol_reference;
+                       member_type = prop.type_reference;
+                       if (prop.set_accessor == null || !prop.set_accessor.writable) {
+                               init.error = true;
+                               Report.error (init.source_reference, "Property `%s' is read-only".printf (prop.get_full_name ()));
                                return;
                        }
                }
+               if (init.initializer.static_type == null || !init.initializer.static_type.compatible (member_type)) {
+                       init.error = true;
+                       Report.error (init.source_reference, "Invalid type for member `%s'".printf (init.name));
+                       return;
+               }
        }
 
        public override void visit_sizeof_expression (SizeofExpression expr) {