[vala] Genie: Briought Genie up to date with Vala



commit e53b00f5a50f6b287e8be2e4dbf8a7b997a43ab0
Author: Jamie McCracken <jamiemcc gnome org>
Date:   Sun Sep 27 11:42:47 2009 -0400

    Genie: Briought Genie up to date with Vala
    
    Added Async support
    Added bug fixes
    Added improved warnings
    Added improved array handling code
    Added support for constants in interfaces

 vala/valagenieparser.vala    |  155 +++++++++++++++++++++++++++++++-----------
 vala/valageniescanner.vala   |   43 +++++++++---
 vala/valagenietokentype.vala |    6 +-
 3 files changed, 150 insertions(+), 54 deletions(-)
---
diff --git a/vala/valagenieparser.vala b/vala/valagenieparser.vala
index 9aa9652..0741593 100644
--- a/vala/valagenieparser.vala
+++ b/vala/valagenieparser.vala
@@ -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 {
diff --git a/vala/valageniescanner.vala b/vala/valageniescanner.vala
index e39191c..718a70b 100644
--- a/vala/valageniescanner.vala
+++ b/vala/valageniescanner.vala
@@ -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;
 		}
diff --git a/vala/valagenietokentype.vala b/vala/valagenietokentype.vala
index 7009029..a814ade 100644
--- a/vala/valagenietokentype.vala
+++ b/vala/valagenietokentype.vala
@@ -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";
 		}
 	}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]