From 3207fbbd5f3199feebcda29e1545b02cb637cbb7 Mon Sep 17 00:00:00 2001 From: Juerg Billeter Date: Mon, 14 Apr 2008 06:15:19 +0000 Subject: [PATCH] don't require `new' operator for struct initialization, fixes bug 526547 2008-04-14 Juerg Billeter * 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 | 8 +++ tests/structs.vala | 12 ++--- vala/valaobjectcreationexpression.vala | 2 + vala/valaparser.vala | 29 ++++++++--- vala/valasemanticanalyzer.vala | 89 +++++++++++++++++++++++----------- 5 files changed, 100 insertions(+), 40 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1bd8d3c..59be670 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2008-04-14 Jürg Billeter + + * 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 * gobject/valaccodegeneratormethod.vala: remove warning about diff --git a/tests/structs.vala b/tests/structs.vala index 5f096f8..85db4a8 100644 --- a/tests/structs.vala +++ b/tests/structs.vala @@ -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); diff --git a/vala/valaobjectcreationexpression.vala b/vala/valaobjectcreationexpression.vala index 97653d4..fb59e02 100644 --- a/vala/valaobjectcreationexpression.vala +++ b/vala/valaobjectcreationexpression.vala @@ -50,6 +50,8 @@ public class Vala.ObjectCreationExpression : Expression { */ public MemberAccess member_name { get; set; } + public bool struct_creation { get; set; } + private Gee.List argument_list = new ArrayList (); private Gee.List object_initializer = new ArrayList (); diff --git a/vala/valaparser.vala b/vala/valaparser.vala index 0f67b22..503d61e 100644 --- a/vala/valaparser.vala +++ b/vala/valaparser.vala @@ -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; diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala index ecebf76..3172ff0 100644 --- a/vala/valasemanticanalyzer.vala +++ b/vala/valasemanticanalyzer.vala @@ -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 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) { -- 2.7.4