]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Genie: Briought Genie up to date with Vala
authorJamie McCracken <jamiemcc gnome org>
Sun, 27 Sep 2009 15:42:47 +0000 (11:42 -0400)
committerJamie McCracken <jamiemcc gnome org>
Sun, 27 Sep 2009 15:44:24 +0000 (11:44 -0400)
Added Async support
Added bug fixes
Added improved warnings
Added improved array handling code
Added support for constants in interfaces

vala/valagenieparser.vala
vala/valageniescanner.vala
vala/valagenietokentype.vala

index 9aa9652c5f3a587bd6e740879810c6ef8594912d..0741593f8b33fa905582a5ae459253d0ab398890 100644 (file)
@@ -65,7 +65,8 @@ public class Vala.Genie.Parser : CodeVisitor {
                OVERRIDE = 1 << 5,
                STATIC = 1 << 6,
                VIRTUAL = 1 << 7,
-               PRIVATE = 1 << 8
+               PRIVATE = 1 << 8,
+               ASYNC = 1 << 9
        }
 
        public Parser () {
@@ -218,6 +219,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                case TokenType.ABSTRACT:
                case TokenType.AS:
                case TokenType.ASSERT:
+               case TokenType.ASYNC:
                case TokenType.BREAK:
                case TokenType.CLASS:
                case TokenType.CONST:
@@ -290,7 +292,6 @@ public class Vala.Genie.Parser : CodeVisitor {
                case TokenType.WHEN:
                case TokenType.WHILE:
                case TokenType.YIELD:
-               case TokenType.YIELDS:
                        next ();
                        return;
                case TokenType.INTEGER_LITERAL:
@@ -379,7 +380,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                                }
                        }
                        
-                       parse_using_directives ();
+                       parse_using_directives (context.root);
                        parse_declarations (context.root, true);
                } catch (ParseError e) {
                        // already reported
@@ -522,18 +523,15 @@ public class Vala.Genie.Parser : CodeVisitor {
                                prev ();
                        
                                while (accept (TokenType.OPEN_BRACKET)) {               
-                                       int array_length = -1;
+                                       bool invalid_array = false;
                                        int array_rank = 0;
                                        do {
                                                array_rank++;
-                                               // support for stack-allocated arrays
-                                               // also required for decision between expression and declaration statement
+                                               // required for decision between expression and declaration statement
                                                if (current () != TokenType.COMMA && current () != TokenType.CLOSE_BRACKET) {
-                                                       var length_expression = parse_expression ();
-                                                       var length_literal = length_expression as IntegerLiteral;
-                                                       if (length_literal != null) {
-                                                               array_length = length_literal.value.to_int ();
-                                                       }
+                                                       parse_expression ();
+                                                       // only used for parsing, reject use as real type
+                                                       invalid_array = true;
                                                }
                                        }
                                        while (accept (TokenType.COMMA));
@@ -543,11 +541,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                                        var array_type = new ArrayType (type, array_rank, get_src (begin));
                                        array_type.nullable = accept (TokenType.INTERR);
                                        
-                                       if (array_rank == 1 && array_length > 0) {
-                                               // fixed length (stack-allocated) array
-                                               array_type.fixed_length = true;
-                                               array_type.length = array_length;
-                                       }
+                                       array_type.invalid_syntax = invalid_array;
                                        
                                        type = array_type;
                                }
@@ -563,6 +557,36 @@ public class Vala.Genie.Parser : CodeVisitor {
                return type;
        }
 
+       DataType? parse_inline_array_type (DataType? type) throws ParseError {
+               var begin = get_location ();
+
+               // inline-allocated array
+               if (type != null && accept (TokenType.OPEN_BRACKET)) {
+                       int array_length = -1;
+
+                       if (current () != TokenType.CLOSE_BRACKET) {
+                               if (current () != TokenType.INTEGER_LITERAL) {
+                                       throw new ParseError.SYNTAX (get_error ("expected `]' or integer literal"));
+                               }
+
+                               var length_literal = (IntegerLiteral) parse_literal ();
+                               array_length = length_literal.value.to_int ();
+                       }
+                       expect (TokenType.CLOSE_BRACKET);
+
+                       var array_type = new ArrayType (type, 1, get_src (begin));
+                       array_type.inline_allocated = true;
+                       if (array_length > 0) {
+                               array_type.fixed_length = true;
+                               array_type.length = array_length;
+                       }
+
+                       return array_type;
+               }
+               return type;
+       }
+
+
        Gee.List<Expression> parse_argument_list () throws ParseError {
                var list = new ArrayList<Expression> ();
                if (current () != TokenType.CLOSE_PARENS) {
@@ -628,6 +652,9 @@ public class Vala.Genie.Parser : CodeVisitor {
                case TokenType.TYPEOF:
                        expr = parse_typeof_expression ();
                        break;
+               case TokenType.YIELD:
+                       expr = parse_yield_expression ();
+                       break;  
                default:
                        expr = parse_simple_name ();
                        break;
@@ -1059,6 +1086,15 @@ public class Vala.Genie.Parser : CodeVisitor {
                return new MemberInitializer (id, expr, get_src (begin));
        }
 
+       Expression parse_yield_expression () throws ParseError {
+               var begin = get_location ();
+               expect (TokenType.YIELD);
+               var member = parse_member_name ();
+               var call = (MethodCall) parse_method_call (begin, member);
+               call.is_yield_expression = true;
+               return call;
+       }
+
        Expression parse_sizeof_expression () throws ParseError {
                var begin = get_location ();
                expect (TokenType.SIZEOF);
@@ -1784,11 +1820,12 @@ public class Vala.Genie.Parser : CodeVisitor {
                expect (TokenType.COLON);
 
                variable_type = parse_type ();
+               var type = parse_inline_array_type (variable_type);
 
                foreach (string id in id_list) {
                        DataType type_copy = null;
-                       if (variable_type != null) {
-                               type_copy = variable_type.copy ();
+                       if (type != null) {
+                               type_copy = type.copy ();
                        }
                        var local = parse_local_variable (type_copy, id);
                        block.add_statement (new DeclarationStatement (local, local.source_reference));
@@ -2065,14 +2102,18 @@ public class Vala.Genie.Parser : CodeVisitor {
                        expr = parse_expression ();
                }
                expect_terminator ();
-               return new ReturnStatement (expr, get_src (begin));
+               return new ReturnStatement (expr, get_src (begin)); 
        }
 
        Statement parse_yield_statement () throws ParseError {
                var begin = get_location ();
                expect (TokenType.YIELD);
+               if (current () != TokenType.SEMICOLON && current () != TokenType.EOL && current () != TokenType.RETURN) {
+                       prev ();
+                       return parse_expression_statement ();
+               }
                Expression expr = null;
-               if (current () != TokenType.SEMICOLON && current () != TokenType.EOL) {
+               if (accept (TokenType.RETURN)) {
                        expr = parse_expression ();
                }
                expect_terminator ();
@@ -2205,7 +2246,11 @@ public class Vala.Genie.Parser : CodeVisitor {
                        if (is_root) {
                                return parse_main_method_declaration (attrs);
                        }
-                       return parse_constructor_declaration (attrs);
+                       if (context.profile == Profile.GOBJECT) {
+                               rollback (begin);
+                               return parse_constructor_declaration (attrs);
+                       }
+                       break;
                case TokenType.DELEGATE:        
                        return parse_delegate_declaration (attrs);      
                case TokenType.DEF:
@@ -2396,29 +2441,29 @@ public class Vala.Genie.Parser : CodeVisitor {
        }
 
 
-       void add_uses_clause () throws ParseError {
+       void add_uses_clause (Namespace ns) throws ParseError {
                var begin = get_location ();
                var sym = parse_symbol_name ();
                var ns_ref = new UsingDirective (sym, get_src (begin));
-
+               
                scanner.source_file.add_using_directive (ns_ref);
-               context.root.add_using_directive (ns_ref);
+               ns.add_using_directive (ns_ref);
        }
 
-       void parse_using_directives () throws ParseError {
+       void parse_using_directives (Namespace ns) throws ParseError {
                while (accept (TokenType.USES)) {
                        if (accept_block ()) {
                                expect (TokenType.INDENT);
 
                                while (current () != TokenType.DEDENT && current () != TokenType.EOF) {
-                                       add_uses_clause ();
+                                       add_uses_clause (ns);
                                        expect (TokenType.EOL); 
                                }
 
                                expect (TokenType.DEDENT);
                        } else {
                                do {
-                                       add_uses_clause ();     
+                                       add_uses_clause (ns);   
                                } while (accept (TokenType.COMMA));
 
                                expect_terminator ();
@@ -2480,7 +2525,6 @@ public class Vala.Genie.Parser : CodeVisitor {
 
                // ensure there is always a default construction method
                if (!scanner.source_file.external_package
-                   && !cl.is_abstract
                    && cl.default_construction_method == null) {
                        var m = new CreationMethod (cl.name, null, cl.source_reference);
                        m.access = SymbolAccessibility.PUBLIC;
@@ -2554,8 +2598,10 @@ public class Vala.Genie.Parser : CodeVisitor {
                var flags = parse_member_declaration_modifiers ();
 
                string id = parse_identifier ();
+       
                expect (TokenType.COLON);
                var type = parse_type (false);
+               type = parse_inline_array_type (type);
 
                Expression initializer = null;
                if (accept (TokenType.ASSIGN)) {
@@ -2591,8 +2637,10 @@ public class Vala.Genie.Parser : CodeVisitor {
                var flags = parse_member_declaration_modifiers ();
 
                var type = parse_type ();
+               
+               type = parse_inline_array_type (type);
 
-               var f = new Field (id, type, null, get_src (begin), comment);
+               var f = new Field (id, type, null, get_src (begin), comment); 
 
                if (ModifierFlags.ABSTRACT in flags || ModifierFlags.VIRTUAL in flags || ModifierFlags.OVERRIDE in flags) {
                        Report.error (f.source_reference, "abstract, virtual, and override modifiers are not applicable to fields");
@@ -2701,13 +2749,15 @@ public class Vala.Genie.Parser : CodeVisitor {
 
                expect (TokenType.CLOSE_PARENS);
 
+
                /* deal with return value */
                if (accept (TokenType.COLON)) {
                        type = parse_type ();
-                       parse_type_parameter_list ();
                }
+               
+               var type_param_list = parse_type_parameter_list ();
 
-               var method = new Method (id, type, get_src (begin), comment);
+               var method = new Method (id, type, get_src (begin), comment); 
                if (ModifierFlags.PRIVATE in flags) {
                        method.access = SymbolAccessibility.PRIVATE;
                } else {
@@ -2717,12 +2767,13 @@ public class Vala.Genie.Parser : CodeVisitor {
 
                set_attributes (method, attrs);
 
-               foreach (FormalParameter param in params) {
-                       method.add_parameter (param);
+               foreach (TypeParameter type_param in type_param_list) {
+                       method.add_type_parameter (type_param);
                }
+               
 
-               if (accept (TokenType.YIELDS)) {
-                       method.coroutine = true;
+               foreach (FormalParameter param in params) {
+                       method.add_parameter (param);
                }
 
                if (accept (TokenType.RAISES)) {
@@ -2737,6 +2788,10 @@ public class Vala.Genie.Parser : CodeVisitor {
                } else if (ModifierFlags.CLASS in flags) {
                        method.binding = MemberBinding.CLASS;
                }
+               if (ModifierFlags.ASYNC in flags) {
+                       method.coroutine = true;
+               }
+               
                if (ModifierFlags.NEW in flags) {
                        method.hides = true;
                }
@@ -2869,6 +2924,10 @@ public class Vala.Genie.Parser : CodeVisitor {
                if (ModifierFlags.EXTERN in flags || scanner.source_file.external_package) {
                        prop.external = true;
                }
+               
+               if (ModifierFlags.ASYNC in flags) {
+                       Report.error (prop.source_reference, "async properties are not supported yet");
+               }
 
                if (accept (TokenType.ASSIGN)) {
                        prop.default_expression = parse_expression ();
@@ -2902,8 +2961,8 @@ public class Vala.Genie.Parser : CodeVisitor {
                                                if (readonly) {
                                                        throw new ParseError.SYNTAX (get_error ("set block not allowed for a read only property"));
                                                }
-                                               _construct = accept (TokenType.CONSTRUCT);
-                                       } else if (accept (TokenType.CONSTRUCT)) {
+                                               _construct = (context.profile == Profile.GOBJECT) && accept (TokenType.CONSTRUCT);
+                                       } else if (context.profile == Profile.GOBJECT && accept (TokenType.CONSTRUCT)) {
                                                _construct = true;
                                        } else if (!accept (TokenType.EOL)) {
                                                throw new ParseError.SYNTAX (get_error ("expected get, set, or construct"));
@@ -2956,6 +3015,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                                var field_type = prop.property_type.copy ();
                                prop.field = new Field ("_%s".printf (prop.name), field_type, prop.default_expression, prop.source_reference);
                                prop.field.access = SymbolAccessibility.PRIVATE;
+                               prop.field.binding = prop.binding;
                        }
                }
 
@@ -3003,11 +3063,19 @@ public class Vala.Genie.Parser : CodeVisitor {
                }
                set_attributes (sig, attrs);
                
+               if (ModifierFlags.STATIC in flags) {
+                       throw new ParseError.SYNTAX (get_error ("`static' modifier not allowed on signals"));
+               } else if (ModifierFlags.CLASS in flags) {
+                       throw new ParseError.SYNTAX (get_error ("`class' modifier not allowed on signals"));
+               }
+               
                foreach (FormalParameter formal_param in params) {
                        sig.add_parameter (formal_param);
                }
 
-               expect_terminator ();
+               if (!accept_terminator ()) {
+                       sig.body = parse_block ();
+               }
                return sig;
        }
 
@@ -3165,6 +3233,8 @@ public class Vala.Genie.Parser : CodeVisitor {
                        iface.add_signal ((Vala.Signal) sym);
                } else if (sym is Field) {
                        iface.add_field ((Field) sym);
+               } else if (sym is Constant) {
+                       iface.add_constant ((Constant) sym);
                } else if (sym is Property) {
                        iface.add_property ((Property) sym);
                } else {
@@ -3270,6 +3340,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                while (sym.inner != null) {
                        sym = sym.inner;
                        var ns = new Namespace (sym.name, ed.source_reference);
+                       
                        if (result is Namespace) {
                                ns.add_namespace ((Namespace) result);
                        } else {
@@ -3319,6 +3390,10 @@ public class Vala.Genie.Parser : CodeVisitor {
                                next ();
                                flags |= ModifierFlags.ABSTRACT;
                                break;
+                       case TokenType.ASYNC:
+                               next ();
+                               flags |= ModifierFlags.ASYNC;
+                               break;  
                        case TokenType.CLASS:
                                next ();
                                flags |= ModifierFlags.CLASS;
@@ -3425,9 +3500,6 @@ public class Vala.Genie.Parser : CodeVisitor {
                        } while (accept (TokenType.COMMA));
                }
                expect (TokenType.CLOSE_PARENS);
-               if (accept (TokenType.YIELDS)) {
-                       method.coroutine = true;
-               }
                if (accept (TokenType.RAISES)) {
                        do {
                                method.add_error_type (parse_type ());
@@ -3520,6 +3592,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                while (sym.inner != null) {
                        sym = sym.inner;
                        var ns = new Namespace (sym.name, d.source_reference);
+
                        if (result is Namespace) {
                                ns.add_namespace ((Namespace) result);
                        } else {
index e39191c4899383c70fa1d5f769500d73e60f4fd6..718a70b96a0323ca29888259ecf893466a96106c 100644 (file)
@@ -226,7 +226,14 @@ public class Vala.Genie.Scanner {
                case 5:
                        switch (begin[0]) {
                        case 'a':
-                               if (matches (begin, "array")) return TokenType.ARRAY;
+                               switch (begin[1]) {
+                               case 'r':
+                                       if (matches (begin, "array")) return TokenType.ARRAY;
+                                       break;
+                               case 's':
+                                       if (matches (begin, "async")) return TokenType.ASYNC;
+                                       break;  
+                               }
                                break;
                        case 'b':
                                if (matches (begin, "break")) return TokenType.BREAK;
@@ -346,9 +353,6 @@ public class Vala.Genie.Scanner {
                        case 't':
                                if (matches (begin, "typeof")) return TokenType.TYPEOF;
                                break;
-                       case 'y':
-                               if (matches (begin, "yields")) return TokenType.YIELDS;
-                               break;
                        }
                        break;
                case 7:
@@ -884,7 +888,24 @@ public class Vala.Genie.Scanner {
                                        if (current[0] == '\\') {
                                                current++;
                                                token_length_in_chars++;
-                                               if (current < end && current[0] == 'x') {
+                                               if (current >= end) {
+                                                       break;
+                                               }
+
+                                               switch (current[0]) {
+                                               case '\'':
+                                               case '"':
+                                               case '\\':
+                                               case '0':
+                                               case 'b':
+                                               case 'f':
+                                               case 'n':
+                                               case 'r':
+                                               case 't':
+                                                       current++;
+                                                       token_length_in_chars++;
+                                                       break;
+                                               case 'x':
                                                        // hexadecimal escape character
                                                        current++;
                                                        token_length_in_chars++;
@@ -892,9 +913,10 @@ public class Vala.Genie.Scanner {
                                                                current++;
                                                                token_length_in_chars++;
                                                        }
-                                               } else {
-                                                       current++;
-                                                       token_length_in_chars++;
+                                                       break;
+                                               default:
+                                                       Report.error (new SourceReference (source_file, line, column + token_length_in_chars, line, column + token_length_in_chars), "invalid escape sequence");
+                                                       break;
                                                }
                                        } else if (current[0] == '\n') {
                                                break;
@@ -904,6 +926,7 @@ public class Vala.Genie.Scanner {
                                                        current += u.to_utf8 (null);
                                                        token_length_in_chars++;
                                                } else {
+                                                       current++;
                                                        Report.error (new SourceReference (source_file, line, column + token_length_in_chars, line, column + token_length_in_chars), "invalid UTF-8 character");
                                                }
                                        }
@@ -978,7 +1001,7 @@ public class Vala.Genie.Scanner {
        }
 
        bool matches (char* begin, string keyword) {
-               char* keyword_array = keyword;
+               char* keyword_array = (char *) keyword;
                long len = keyword.len ();
                for (int i = 0; i < len; i++) {
                        if (begin[i] != keyword_array[i]) {
@@ -997,7 +1020,7 @@ public class Vala.Genie.Scanner {
                        column++;
                }
                
-               if ((column == 1) && (current[0] == '#')) {
+               if ((column == 1) && (current < end) && (current[0] == '#')) {
                        pp_directive ();
                        return true;
                }
index 700902991dc1741d180fa5bb76932c88a5db75dd..a814ade8b78870411a4c7f80781918c43d096925 100644 (file)
@@ -39,6 +39,7 @@ public enum Vala.Genie.TokenType {
        ASSIGN_PERCENT,
        ASSIGN_SHIFT_LEFT,
        ASSIGN_SUB,
+       ASYNC,
        BITWISE_AND,
        BITWISE_OR,
        BREAK,
@@ -163,8 +164,7 @@ public enum Vala.Genie.TokenType {
        WHEN,
        WHILE,
        WRITEONLY,
-       YIELD,
-       YIELDS;
+       YIELD;
 
        public weak string to_string () {
                switch (this) {
@@ -182,6 +182,7 @@ public enum Vala.Genie.TokenType {
                case ASSIGN_PERCENT: return "`%='";
                case ASSIGN_SHIFT_LEFT: return "`<<='";
                case ASSIGN_SUB: return "`-='";
+               case ASYNC: return "`async'";
                case BITWISE_AND: return "`&'";
                case BITWISE_OR: return "`|'";
                case BREAK: return "`break'";
@@ -306,7 +307,6 @@ public enum Vala.Genie.TokenType {
                case WHILE: return "`while'";
                case WRITEONLY: return "`writeonly'";
                case YIELD: return "`yield'";
-               case YIELDS: return "`yields'";
                default: return "unknown token";
                }
        }