Don't use UnresolvedType for array and pointer types, add basic support
authorJuerg Billeter <j@bitron.ch>
Sat, 17 May 2008 12:38:49 +0000 (12:38 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Sat, 17 May 2008 12:38:49 +0000 (12:38 +0000)
2008-05-17  Juerg Billeter  <j@bitron.ch>

* vala/valaarraytype.vala:
* vala/valaclass.vala:
* vala/valaparser.vala:
* vala/valapointertype.vala:
* vala/valasymbolresolver.vala:
* vala/valaunresolvedtype.vala:
* vapigen/valagidlparser.vala:

Don't use UnresolvedType for array and pointer types, add basic
support for arrays of arrays

svn path=/trunk/; revision=1395

ChangeLog
vala/valaarraytype.vala
vala/valaclass.vala
vala/valaparser.vala
vala/valapointertype.vala
vala/valasymbolresolver.vala
vala/valaunresolvedtype.vala
vapigen/valagidlparser.vala

index fa3c8a3..ea7a1ef 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2008-05-17  Jürg Billeter  <j@bitron.ch>
+
+       * vala/valaarraytype.vala:
+       * vala/valaclass.vala:
+       * vala/valaparser.vala:
+       * vala/valapointertype.vala:
+       * vala/valasymbolresolver.vala:
+       * vala/valaunresolvedtype.vala:
+       * vapigen/valagidlparser.vala:
+
+       Don't use UnresolvedType for array and pointer types, add basic
+       support for arrays of arrays
+
 2008-05-17  Ali Sabil  <ali.sabil@gmail.com>
 
        * vapigen/valagidlparser.vala: Automatically hide fields
index ba70ab5..7fd6a04 100644 (file)
@@ -29,13 +29,21 @@ public class Vala.ArrayType : ReferenceType {
        /**
         * The element type.
         */
-       public DataType element_type { get; construct set; }
+       public DataType element_type {
+               get { return _element_type; }
+               set {
+                       _element_type = value;
+                       _element_type.parent_node = this;
+               }
+       }
 
        /**
         * The rank of this array.
         */
-       public int rank { get; construct set; }
-       
+       public int rank { get; set; }
+
+       private DataType _element_type;
+
        private ArrayLengthField length_field;
        private ArrayResizeMethod resize_method;
        private ArrayMoveMethod move_method;
@@ -173,4 +181,14 @@ public class Vala.ArrayType : ReferenceType {
 
                return "a" + element_type_signature;
        }
+
+       public override void accept_children (CodeVisitor visitor) {
+               element_type.accept (visitor);
+       }
+
+       public override void replace_type (DataType old_type, DataType new_type) {
+               if (element_type == old_type) {
+                       element_type = new_type;
+               }
+       }
 }
index a8cde3b..c9522d3 100644 (file)
@@ -263,39 +263,15 @@ public class Vala.Class : Typesymbol {
         *
         * @param prop a property
         */
-       public void add_property (Property prop, bool no_field = false) {
+       public void add_property (Property prop) {
                properties.add (prop);
                scope.add (prop.name, prop);
 
                prop.this_parameter = new FormalParameter ("this", new ClassInstanceType (this));
                prop.scope.add (prop.this_parameter.name, prop.this_parameter);
-               
-               if (!no_field && !external_package) {
-                       bool empty_get = (prop.get_accessor != null && prop.get_accessor.body == null);
-                       bool empty_set = (prop.set_accessor != null && prop.set_accessor.body == null);
-
-                       if (empty_get != empty_set) {
-                               if (empty_get) {
-                                       Report.error (prop.source_reference, "property getter must have a body");
-                               } else if (empty_set) {
-                                       Report.error (prop.source_reference, "property setter must have a body");
-                               }
-                               prop.error = true;
-                               return;
-                       }
 
-                       if (empty_get && empty_set) {
-                               /* automatic property accessor body generation */
-                               var field_type = prop.property_type.copy ();
-                               var ut = field_type as UnresolvedType;
-                               if (ut != null) {
-                                       field_type.value_owned = !ut.is_weak;
-                               }
-                               var f = new Field ("_%s".printf (prop.name), field_type, prop.default_expression, prop.source_reference);
-                               f.access = SymbolAccessibility.PRIVATE;
-                               prop.field = f;
-                               add_field (f);
-                       }
+               if (prop.field != null) {
+                       add_field (prop.field);
                }
        }
        
index 59f4530..9886fa5 100644 (file)
@@ -319,7 +319,7 @@ public class Vala.Parser : CodeVisitor {
                skip_type_argument_list ();
                while (accept (TokenType.STAR)) {
                }
-               if (accept (TokenType.OPEN_BRACKET)) {
+               while (accept (TokenType.OPEN_BRACKET)) {
                        do {
                                if (current () != TokenType.COMMA && current () != TokenType.CLOSE_BRACKET) {
                                        parse_expression ();
@@ -332,7 +332,7 @@ public class Vala.Parser : CodeVisitor {
                accept (TokenType.HASH);
        }
 
-       DataType parse_type () throws ParseError {
+       DataType parse_type (bool owned_by_default = true) throws ParseError {
                var begin = get_location ();
 
                if (accept (TokenType.VOID)) {
@@ -345,20 +345,34 @@ public class Vala.Parser : CodeVisitor {
 
                bool is_dynamic = accept (TokenType.DYNAMIC);
 
-               bool is_weak = accept (TokenType.WEAK);
+               bool value_owned = owned_by_default;
+               if (owned_by_default) {
+                       value_owned = !accept (TokenType.WEAK);
+               }
 
                var sym = parse_symbol_name ();
                Gee.List<DataType> type_arg_list = parse_type_argument_list (false);
 
-               int stars = 0;
+               DataType type = new UnresolvedType.from_symbol (sym, get_src (begin));
+               if (type_arg_list != null) {
+                       foreach (DataType type_arg in type_arg_list) {
+                               type.add_type_argument (type_arg);
+                       }
+               }
+
                while (accept (TokenType.STAR)) {
-                       stars++;
+                       type = new PointerType (type, get_src (begin));
                }
 
-               bool nullable = stars > 0 || accept (TokenType.INTERR);
+               if (!(type is PointerType)) {
+                       type.nullable = accept (TokenType.INTERR);
+               }
 
-               int array_rank = 0;
-               if (accept (TokenType.OPEN_BRACKET)) {
+               // array brackets in types are read from right to left,
+               // this is more logical, especially when nullable arrays
+               // or pointers are involved
+               while (accept (TokenType.OPEN_BRACKET)) {
+                       int array_rank = 0;
                        do {
                                array_rank++;
                                // support for stack-allocated arrays
@@ -370,26 +384,22 @@ public class Vala.Parser : CodeVisitor {
                        while (accept (TokenType.COMMA));
                        expect (TokenType.CLOSE_BRACKET);
 
-                       nullable = accept (TokenType.INTERR);
+                       // arrays contain strong references by default
+                       type.value_owned = true;
+
+                       type = new ArrayType (type, array_rank, get_src (begin));
+                       type.nullable = accept (TokenType.INTERR);
                }
 
                if (accept (TokenType.OP_NEG)) {
                        Report.warning (get_last_src (), "obsolete syntax, types are non-null by default");
                }
 
-               bool value_owned = accept (TokenType.HASH);
-
-               var type = new UnresolvedType.from_symbol (sym, get_src (begin));
-               if (type_arg_list != null) {
-                       foreach (DataType type_arg in type_arg_list) {
-                               type.add_type_argument (type_arg);
-                       }
+               if (!owned_by_default) {
+                       value_owned = accept (TokenType.HASH);
                }
+
                type.is_dynamic = is_dynamic;
-               type.is_weak = is_weak;
-               type.pointer_level = stars;
-               type.array_rank = array_rank;
-               type.nullable = nullable;
                type.value_owned = value_owned;
                return type;
        }
@@ -646,21 +656,34 @@ public class Vala.Parser : CodeVisitor {
 
        Expression parse_array_creation_expression (SourceLocation begin, MemberAccess member) throws ParseError {
                bool size_specified = false;
-               var size_specifier_list = new ArrayList<Expression> ();
+               Gee.List<Expression> size_specifier_list;
+               bool first = true;
+               DataType element_type = UnresolvedType.new_from_expression (member);
                do {
-                       Expression size = null;
-                       if (current () != TokenType.CLOSE_BRACKET && current () != TokenType.COMMA) {
-                               size = parse_expression ();
-                               size_specified = true;
+                       if (!first) {
+                               // array of arrays: new T[][42]
+                               element_type = new ArrayType (element_type, size_specifier_list.size, element_type.source_reference);
+                       } else {
+                               first = false;
                        }
-                       size_specifier_list.add (size);
-               } while (accept (TokenType.COMMA));
-               expect (TokenType.CLOSE_BRACKET);
+
+                       size_specifier_list = new ArrayList<Expression> ();
+                       do {
+                               Expression size = null;
+                               if (current () != TokenType.CLOSE_BRACKET && current () != TokenType.COMMA) {
+                                       size = parse_expression ();
+                                       size_specified = true;
+                               }
+                               size_specifier_list.add (size);
+                       } while (accept (TokenType.COMMA));
+                       expect (TokenType.CLOSE_BRACKET);
+               } while (accept (TokenType.OPEN_BRACKET));
+
                InitializerList initializer = null;
                if (current () == TokenType.OPEN_BRACE) {
                        initializer = parse_initializer ();
                }
-               var expr = new ArrayCreationExpression (UnresolvedType.new_from_expression (member), size_specifier_list.size, initializer, get_src (begin));
+               var expr = new ArrayCreationExpression (element_type, size_specifier_list.size, initializer, get_src (begin));
                if (size_specified) {
                        foreach (Expression size in size_specifier_list) {
                                expr.append_size (size);
@@ -763,8 +786,7 @@ public class Vala.Parser : CodeVisitor {
                                        case TokenType.SIZEOF:
                                        case TokenType.TYPEOF:
                                        case TokenType.IDENTIFIER:
-                                               var ut = type as UnresolvedType;
-                                               if (ut != null && ut.is_weak) {
+                                               if (!type.value_owned) {
                                                        Report.warning (get_src (begin), "obsolete syntax, weak type modifier unused in cast expressions");
                                                }
                                                var inner = parse_unary_expression ();
@@ -1312,10 +1334,6 @@ public class Vala.Parser : CodeVisitor {
                        variable_type = null;
                } else {
                        variable_type = parse_type ();
-                       var ut = variable_type as UnresolvedType;
-                       if (ut != null && !ut.is_weak) {
-                               variable_type.value_owned = true;
-                       }
                }
                do {
                        DataType type_copy = null;
@@ -1449,10 +1467,6 @@ public class Vala.Parser : CodeVisitor {
                                        variable_type = null;
                                } else {
                                        variable_type = parse_type ();
-                                       var ut = variable_type as UnresolvedType;
-                                       if (ut != null && !ut.is_weak) {
-                                               variable_type.value_owned = true;
-                                       }
                                }
                                var local = parse_local_variable (variable_type);
                                block.add_statement (new DeclarationStatement (local, local.source_reference));
@@ -1493,10 +1507,6 @@ public class Vala.Parser : CodeVisitor {
                expect (TokenType.FOREACH);
                expect (TokenType.OPEN_PARENS);
                var type = parse_type ();
-               var unresolved_type = type as UnresolvedType;
-               if (unresolved_type != null && !unresolved_type.is_weak) {
-                       unresolved_type.value_owned = true;
-               }
                string id = parse_identifier ();
                expect (TokenType.IN);
                var collection = parse_expression ();
@@ -1966,7 +1976,7 @@ public class Vala.Parser : CodeVisitor {
                var access = parse_access_modifier ();
                parse_member_declaration_modifiers ();
                expect (TokenType.CONST);
-               var type = parse_type ();
+               var type = parse_type (false);
                string id = parse_identifier ();
                Expression initializer = null;
                if (accept (TokenType.ASSIGN)) {
@@ -1984,10 +1994,6 @@ public class Vala.Parser : CodeVisitor {
                var access = parse_access_modifier ();
                var flags = parse_member_declaration_modifiers ();
                var type = parse_type ();
-               var unresolved_type = type as UnresolvedType;
-               if (unresolved_type != null && !unresolved_type.is_weak) {
-                       unresolved_type.value_owned = true;
-               }
                string id = parse_identifier ();
                var f = new Field (id, type, null, get_src_com (begin));
                f.access = access;
@@ -2032,10 +2038,6 @@ public class Vala.Parser : CodeVisitor {
                var access = parse_access_modifier ();
                var flags = parse_member_declaration_modifiers ();
                var type = parse_type ();
-               var unresolved_type = type as UnresolvedType;
-               if (unresolved_type != null && !unresolved_type.is_weak) {
-                       unresolved_type.value_owned = true;
-               }
                string id = parse_identifier ();
                parse_type_parameter_list ();
                var method = new Method (id, type, get_src_com (begin));
@@ -2094,7 +2096,8 @@ public class Vala.Parser : CodeVisitor {
                var begin = get_location ();
                var access = parse_access_modifier ();
                var flags = parse_member_declaration_modifiers ();
-               var type = parse_type ();
+               bool is_weak = accept (TokenType.WEAK);
+               var type = parse_type (false);
                string id = parse_identifier ();
                var prop = new Property (id, type, null, null, get_src_com (begin));
                prop.access = access;
@@ -2161,6 +2164,29 @@ public class Vala.Parser : CodeVisitor {
                        }
                }
                expect (TokenType.CLOSE_BRACE);
+
+               if (!prop.is_abstract && !scanner.source_file.external_package) {
+                       bool empty_get = (prop.get_accessor != null && prop.get_accessor.body == null);
+                       bool empty_set = (prop.set_accessor != null && prop.set_accessor.body == null);
+
+                       if (empty_get != empty_set) {
+                               if (empty_get) {
+                                       Report.error (prop.source_reference, "property getter must have a body");
+                               } else if (empty_set) {
+                                       Report.error (prop.source_reference, "property setter must have a body");
+                               }
+                               prop.error = true;
+                       }
+
+                       if (empty_get && empty_set) {
+                               /* automatic property accessor body generation */
+                               var field_type = prop.property_type.copy ();
+                               field_type.value_owned = !is_weak;
+                               prop.field = new Field ("_%s".printf (prop.name), field_type, prop.default_expression, prop.source_reference);
+                               prop.field.access = SymbolAccessibility.PRIVATE;
+                       }
+               }
+
                return prop;
        }
 
@@ -2543,16 +2569,13 @@ public class Vala.Parser : CodeVisitor {
                        direction = ParameterDirection.REF;
                }
 
-               var type = parse_type ();
-               var ut = type as UnresolvedType;
-               if (ut != null) {
-                       if (direction != ParameterDirection.IN && !ut.is_weak) {
-                               ut.value_owned = true;
-                       } else if (direction == ParameterDirection.IN && ut.is_weak) {
-                               Report.error (type.source_reference, "in parameters are weak by default");
-                       } else if (direction != ParameterDirection.IN && ut.value_owned) {
-                               Report.error (type.source_reference, "out parameters own the value by default");
-                       }
+               DataType type;
+               if (direction == ParameterDirection.IN) {
+                       // in parameters are weak by default
+                       type = parse_type (false);
+               } else {
+                       // out parameters own the value by default
+                       type = parse_type (true);
                }
                string id = parse_identifier ();
                var param = new FormalParameter (id, type, get_src (begin));
@@ -2604,10 +2627,6 @@ public class Vala.Parser : CodeVisitor {
                var flags = parse_member_declaration_modifiers ();
                expect (TokenType.DELEGATE);
                var type = parse_type ();
-               var unresolved_type = type as UnresolvedType;
-               if (unresolved_type != null && !unresolved_type.is_weak) {
-                       unresolved_type.value_owned = true;
-               }
                var sym = parse_symbol_name ();
                var type_param_list = parse_type_parameter_list ();
                var d = new Delegate (sym.name, type, get_src_com (begin));
@@ -2683,10 +2702,6 @@ public class Vala.Parser : CodeVisitor {
                                case TokenType.WEAK:
                                case TokenType.IDENTIFIER:
                                        var type = parse_type ();
-                                       var ut = type as UnresolvedType;
-                                       if (ut != null && !ut.is_weak) {
-                                               type.value_owned = true;
-                                       }
                                        list.add (type);
                                        break;
                                default:
index d180934..9b956ad 100644 (file)
@@ -30,11 +30,20 @@ public class Vala.PointerType : DataType {
        /**
         * The base type the pointer is referring to.
         */
-       public DataType base_type { get; set; }
+       public DataType base_type {
+               get { return _base_type; }
+               set {
+                       _base_type = value;
+                       _base_type.parent_node = this;
+               }
+       }
 
-       public PointerType (DataType base_type) {
+       private DataType _base_type;
+
+       public PointerType (DataType base_type, SourceReference? source_reference = null) {
                this.base_type = base_type;
                nullable = true;
+               this.source_reference = source_reference;
        }
 
        public override string to_string () {
@@ -88,4 +97,14 @@ public class Vala.PointerType : DataType {
        public override string? get_type_id () {
                return "G_TYPE_POINTER";
        }
+
+       public override void accept_children (CodeVisitor visitor) {
+               base_type.accept (visitor);
+       }
+
+       public override void replace_type (DataType old_type, DataType new_type) {
+               if (base_type == old_type) {
+                       base_type = new_type;
+               }
+       }
 }
index 22076c1..40f32c5 100644 (file)
@@ -280,32 +280,12 @@ public class Vala.SymbolResolver : CodeVisitor {
                        type.add_type_argument (type_arg);
                }
 
-               for (int pointer_level = unresolved_type.pointer_level; pointer_level > 0; pointer_level--) {
-                       var base_type = type;
-                       base_type.value_owned = false;
-                       base_type.nullable = false;
-                       base_type.is_dynamic = false;
-
-                       type = new PointerType (base_type);
-               }
-
-               /* check for array */
-               if (unresolved_type.array_rank > 0) {
-                       var element_type = type;
-                       // array contains strong references by default
-                       element_type.value_owned = true;
-                       element_type.nullable = false;
-
-                       type = new ArrayType (element_type, unresolved_type.array_rank, unresolved_type.source_reference);
-
-                       type.value_owned = unresolved_type.value_owned;
-                       type.nullable = unresolved_type.nullable;
-               }
-
                return type;
        }
 
        public override void visit_data_type (DataType data_type) {
+               data_type.accept_children (this);
+
                if (!(data_type is UnresolvedType)) {
                        return;
                }
index 6db0e75..5b9ba14 100644 (file)
@@ -33,23 +33,6 @@ public class Vala.UnresolvedType : DataType {
         */
        public UnresolvedSymbol unresolved_symbol { get; set; }
 
-       /**
-        * Specifies the rank of the array this reference is possibly referring
-        * to. "0" indicates no array.
-        */
-       public int array_rank { get; set; }
-
-       /**
-        * Specifies the level of the pointer if this is a pointer-type. "0"
-        * indicates no pointer-type.
-        */
-       public int pointer_level { get; set; }
-
-       /**
-        * The weak modifier has been specified.
-        */
-       public bool is_weak { get; set; }
-
        public UnresolvedType () {
        }
 
@@ -109,9 +92,6 @@ public class Vala.UnresolvedType : DataType {
                result.nullable = nullable;
                result.is_dynamic = is_dynamic;
                result.unresolved_symbol = unresolved_symbol.copy ();
-               result.array_rank = array_rank;
-               result.pointer_level = pointer_level;
-               result.is_weak = is_weak;
                
                foreach (DataType arg in get_type_arguments ()) {
                        result.add_type_argument (arg.copy ());
index b5425c8..2e482f8 100644 (file)
@@ -874,7 +874,7 @@ public class Vala.GIdlParser : CodeVisitor {
                        } else if (member.type == IdlNodeTypeId.PROPERTY) {
                                var prop = parse_property ((IdlNodeProperty) member);
                                if (prop != null) {
-                                       cl.add_property (prop, true);
+                                       cl.add_property (prop);
                                }
                        } else if (member.type == IdlNodeTypeId.SIGNAL) {
                                var sig = parse_signal ((IdlNodeSignal) member);
@@ -1040,7 +1040,7 @@ public class Vala.GIdlParser : CodeVisitor {
                        if (type == null) {
                                return element_type;
                        }
-                       type.array_rank = 1;
+                       return new ArrayType (element_type, 1, element_type.source_reference);
                } else if (type_node.tag == TypeTag.LIST) {
                        type.unresolved_symbol = new UnresolvedSymbol (new UnresolvedSymbol (null, "GLib"), "List");
                } else if (type_node.tag == TypeTag.SLIST) {
@@ -1073,7 +1073,7 @@ public class Vala.GIdlParser : CodeVisitor {
                        } else if (n == "guchar" || n == "guint8") {
                                type.unresolved_symbol = new UnresolvedSymbol (null, "uchar");
                                if (type_node.is_pointer) {
-                                       type.array_rank = 1;
+                                       return new ArrayType (type, 1, type.source_reference);
                                }
                        } else if (n == "gushort") {
                                type.unresolved_symbol = new UnresolvedSymbol (null, "ushort");
@@ -1104,11 +1104,11 @@ public class Vala.GIdlParser : CodeVisitor {
                        } else if (n == "GType") {
                                type.unresolved_symbol = new UnresolvedSymbol (new UnresolvedSymbol (null, "GLib"), "Type");
                                if (type_node.is_pointer) {
-                                       type.array_rank = 1;
+                                       return new ArrayType (type, 1, type.source_reference);
                                }
                        } else if (n == "GStrv") {
                                type.unresolved_symbol = new UnresolvedSymbol (null, "string");
-                               type.array_rank = 1;
+                               return new ArrayType (type, 1, type.source_reference);
                        } else {
                                var named_type = parse_type_string (n);
                                type = named_type as UnresolvedType;
@@ -1275,7 +1275,8 @@ public class Vala.GIdlParser : CodeVisitor {
                                        m.sentinel = eval (nv[1]);
                                } else if (nv[0] == "is_array") {
                                        if (eval (nv[1]) == "1") {
-                                               ((UnresolvedType) return_type).array_rank = 1;
+                                               return_type = new ArrayType (return_type, 1, return_type.source_reference);
+                                               m.return_type = return_type;
                                        }
                                } else if (nv[0] == "throws") {
                                        if (eval (nv[1]) == "0") {
@@ -1362,7 +1363,8 @@ public class Vala.GIdlParser : CodeVisitor {
                                        var nv = attr.split ("=", 2);
                                        if (nv[0] == "is_array") {
                                                if (eval (nv[1]) == "1") {
-                                                       ((UnresolvedType) param_type).array_rank = 1;
+                                                       param_type = new ArrayType (param_type, 1, param_type.source_reference);
+                                                       p.parameter_type = param_type;
                                                        p.direction = ParameterDirection.IN;
                                                }
                                        } else if (nv[0] == "is_out") {
@@ -1418,7 +1420,8 @@ public class Vala.GIdlParser : CodeVisitor {
 
                        if (last_param != null && p.name == "n_" + last_param.name) {
                                // last_param is array, p is array length
-                               ((UnresolvedType) last_param_type).array_rank = 1;
+                               last_param_type = new ArrayType (last_param_type, 1, last_param_type.source_reference);
+                               last_param.parameter_type = last_param_type;
                                last_param.direction = ParameterDirection.IN;
 
                                // hide array length param
@@ -1618,7 +1621,7 @@ public class Vala.GIdlParser : CodeVisitor {
                                        }
                                } else if (nv[0] == "is_array") {
                                        if (eval (nv[1]) == "1") {
-                                               ((UnresolvedType) type).array_rank = 1;
+                                               type = new ArrayType (type, 1, type.source_reference);
                                        }
                                } else if (nv[0] == "weak") {
                                        if (eval (nv[1]) == "0") {
@@ -1741,7 +1744,8 @@ public class Vala.GIdlParser : CodeVisitor {
                                        var nv = attr.split ("=", 2);
                                        if (nv[0] == "is_array") {
                                                if (eval (nv[1]) == "1") {
-                                                       ((UnresolvedType) param_type).array_rank = 1;
+                                                       param_type = new ArrayType (param_type, 1, param_type.source_reference);
+                                                       p.parameter_type = param_type;
                                                        p.direction = ParameterDirection.IN;
                                                }
                                        } else if (nv[0] == "is_out") {