vala r2009 - in trunk: . vala



Author: juergbi
Date: Mon Nov 10 18:56:28 2008
New Revision: 2009
URL: http://svn.gnome.org/viewvc/vala?rev=2009&view=rev

Log:
2008-11-10  JÃrg Billeter  <j bitron ch>

	* vala/valaaddressofexpression.vala:
	* vala/valabaseaccess.vala:
	* vala/valabooleanliteral.vala:
	* vala/valacastexpression.vala:
	* vala/valacharacterliteral.vala:
	* vala/valaconditionalexpression.vala:
	* vala/valaintegerliteral.vala:
	* vala/valalambdaexpression.vala:
	* vala/valanullliteral.vala:
	* vala/valaobjectcreationexpression.vala:
	* vala/valaparenthesizedexpression.vala:
	* vala/valapointerindirection.vala:
	* vala/valapostfixexpression.vala:
	* vala/valarealliteral.vala:
	* vala/valareferencetransferexpression.vala:
	* vala/valasemanticanalyzer.vala:
	* vala/valasizeofexpression.vala:
	* vala/valastringliteral.vala:
	* vala/valatypecheck.vala:
	* vala/valatypeofexpression.vala:
	* vala/valaunaryexpression.vala:

	Move expression checking to code nodes


Modified:
   trunk/ChangeLog
   trunk/vala/valaaddressofexpression.vala
   trunk/vala/valabaseaccess.vala
   trunk/vala/valabooleanliteral.vala
   trunk/vala/valacastexpression.vala
   trunk/vala/valacharacterliteral.vala
   trunk/vala/valaconditionalexpression.vala
   trunk/vala/valaintegerliteral.vala
   trunk/vala/valalambdaexpression.vala
   trunk/vala/valanullliteral.vala
   trunk/vala/valaobjectcreationexpression.vala
   trunk/vala/valaparenthesizedexpression.vala
   trunk/vala/valapointerindirection.vala
   trunk/vala/valapostfixexpression.vala
   trunk/vala/valarealliteral.vala
   trunk/vala/valareferencetransferexpression.vala
   trunk/vala/valasemanticanalyzer.vala
   trunk/vala/valasizeofexpression.vala
   trunk/vala/valastringliteral.vala
   trunk/vala/valatypecheck.vala
   trunk/vala/valatypeofexpression.vala
   trunk/vala/valaunaryexpression.vala

Modified: trunk/vala/valaaddressofexpression.vala
==============================================================================
--- trunk/vala/valaaddressofexpression.vala	(original)
+++ trunk/vala/valaaddressofexpression.vala	Mon Nov 10 18:56:28 2008
@@ -1,6 +1,6 @@
 /* valaaddressofexpression.vala
  *
- * Copyright (C) 2007  JÃrg Billeter
+ * Copyright (C) 2007-2008  JÃrg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -69,4 +69,31 @@
 	public override bool is_pure () {
 		return inner.is_pure ();
 	}
+
+	public override bool check (SemanticAnalyzer analyzer) {
+		if (checked) {
+			return !error;
+		}
+
+		checked = true;
+
+		if (inner.error) {
+			return false;
+		}
+		if (!(inner.value_type is ValueType
+		      || inner.value_type is ObjectType
+		      || inner.value_type is PointerType)) {
+			error = true;
+			Report.error (source_reference, "Address-of operator not supported for this expression");
+			return false;
+		}
+
+		if (inner.value_type.is_reference_type_or_type_parameter ()) {
+			value_type = new PointerType (new PointerType (inner.value_type));
+		} else {
+			value_type = new PointerType (inner.value_type);
+		}
+
+		return !error;
+	}
 }

Modified: trunk/vala/valabaseaccess.vala
==============================================================================
--- trunk/vala/valabaseaccess.vala	(original)
+++ trunk/vala/valabaseaccess.vala	Mon Nov 10 18:56:28 2008
@@ -1,6 +1,6 @@
 /* valabaseaccess.vala
  *
- * Copyright (C) 2006-2007  JÃrg Billeter
+ * Copyright (C) 2006-2008  JÃrg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -20,7 +20,7 @@
  * 	JÃrg Billeter <j bitron ch>
  */
 
-using GLib;
+using Gee;
 
 /**
  * Represents an access to base class members in the source code.
@@ -49,4 +49,43 @@
 	public override bool is_pure () {
 		return true;
 	}
+
+	public override bool check (SemanticAnalyzer analyzer) {
+		if (checked) {
+			return !error;
+		}
+
+		checked = true;
+
+		if (!analyzer.is_in_instance_method ()) {
+			error = true;
+			Report.error (source_reference, "Base access invalid outside of instance methods");
+			return false;
+		}
+
+		if (analyzer.current_class == null) {
+			if (analyzer.current_struct == null) {
+				error = true;
+				Report.error (source_reference, "Base access invalid outside of class and struct");
+				return false;
+			} else if (analyzer.current_struct.get_base_types ().size != 1) {
+				error = true;
+				Report.error (source_reference, "Base access invalid without base type %d".printf (analyzer.current_struct.get_base_types ().size));
+				return false;
+			}
+			Iterator<DataType> base_type_it = analyzer.current_struct.get_base_types ().iterator ();
+			base_type_it.next ();
+			value_type = base_type_it.get ();
+		} else if (analyzer.current_class.base_class == null) {
+			error = true;
+			Report.error (source_reference, "Base access invalid without base class");
+			return false;
+		} else {
+			value_type = new ObjectType (analyzer.current_class.base_class);
+		}
+
+		symbol_reference = value_type.data_type;
+
+		return !error;
+	}
 }

Modified: trunk/vala/valabooleanliteral.vala
==============================================================================
--- trunk/vala/valabooleanliteral.vala	(original)
+++ trunk/vala/valabooleanliteral.vala	Mon Nov 10 18:56:28 2008
@@ -60,4 +60,16 @@
 	public override bool is_pure () {
 		return true;
 	}
+
+	public override bool check (SemanticAnalyzer analyzer) {
+		if (checked) {
+			return !error;
+		}
+
+		checked = true;
+
+		value_type = analyzer.bool_type;
+
+		return !error;
+	}
 }

Modified: trunk/vala/valacastexpression.vala
==============================================================================
--- trunk/vala/valacastexpression.vala	(original)
+++ trunk/vala/valacastexpression.vala	Mon Nov 10 18:56:28 2008
@@ -1,6 +1,6 @@
 /* valacastexpression.vala
  *
- * Copyright (C) 2006-2007  JÃrg Billeter
+ * Copyright (C) 2006-2008  JÃrg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -97,4 +97,28 @@
 			type_reference = new_type;
 		}
 	}
+
+	public override bool check (SemanticAnalyzer analyzer) {
+		if (checked) {
+			return !error;
+		}
+
+		checked = true;
+
+		if (inner.error) {
+			error = true;
+			return false;
+		}
+
+		// FIXME: check whether cast is allowed
+
+		analyzer.current_source_file.add_type_dependency (type_reference, SourceFileDependencyType.SOURCE);
+
+		value_type = type_reference;
+		value_type.value_owned = inner.value_type.value_owned;
+
+		inner.target_type = inner.value_type.copy ();
+
+		return !error;
+	}
 }

Modified: trunk/vala/valacharacterliteral.vala
==============================================================================
--- trunk/vala/valacharacterliteral.vala	(original)
+++ trunk/vala/valacharacterliteral.vala	Mon Nov 10 18:56:28 2008
@@ -77,4 +77,16 @@
 	public override bool is_pure () {
 		return true;
 	}
+
+	public override bool check (SemanticAnalyzer analyzer) {
+		if (checked) {
+			return !error;
+		}
+
+		checked = true;
+
+		value_type = new ValueType ((TypeSymbol) analyzer.root_symbol.scope.lookup ("char"));
+
+		return !error;
+	}
 }

Modified: trunk/vala/valaconditionalexpression.vala
==============================================================================
--- trunk/vala/valaconditionalexpression.vala	(original)
+++ trunk/vala/valaconditionalexpression.vala	Mon Nov 10 18:56:28 2008
@@ -1,6 +1,6 @@
 /* valaconditionalexpression.vala
  *
- * Copyright (C) 2006  JÃrg Billeter
+ * Copyright (C) 2006-2008  JÃrg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -69,4 +69,35 @@
 	public override bool is_pure () {
 		return condition.is_pure () && true_expression.is_pure () && false_expression.is_pure ();
 	}
+
+	public override bool check (SemanticAnalyzer analyzer) {
+		if (checked) {
+			return !error;
+		}
+
+		checked = true;
+
+		if (condition.error || false_expression.error || true_expression.error) {
+			return false;
+		}
+
+		if (!condition.value_type.compatible (analyzer.bool_type)) {
+			error = true;
+			Report.error (condition.source_reference, "Condition must be boolean");
+			return false;
+		}
+
+		/* FIXME: support memory management */
+		if (false_expression.value_type.compatible (true_expression.value_type)) {
+			value_type = true_expression.value_type.copy ();
+		} else if (true_expression.value_type.compatible (false_expression.value_type)) {
+			value_type = false_expression.value_type.copy ();
+		} else {
+			error = true;
+			Report.error (condition.source_reference, "Incompatible expressions");
+			return false;
+		}
+
+		return !error;
+	}
 }

Modified: trunk/vala/valaintegerliteral.vala
==============================================================================
--- trunk/vala/valaintegerliteral.vala	(original)
+++ trunk/vala/valaintegerliteral.vala	Mon Nov 10 18:56:28 2008
@@ -106,4 +106,16 @@
 	public override bool is_pure () {
 		return true;
 	}
+
+	public override bool check (SemanticAnalyzer analyzer) {
+		if (checked) {
+			return !error;
+		}
+
+		checked = true;
+
+		value_type = new IntegerType ((TypeSymbol) analyzer.root_symbol.scope.lookup (get_type_name ()), value, get_type_name ());
+
+		return !error;
+	}
 }

Modified: trunk/vala/valalambdaexpression.vala
==============================================================================
--- trunk/vala/valalambdaexpression.vala	(original)
+++ trunk/vala/valalambdaexpression.vala	Mon Nov 10 18:56:28 2008
@@ -1,6 +1,6 @@
 /* valalambdaexpression.vala
  *
- * Copyright (C) 2006-2007  JÃrg Billeter
+ * Copyright (C) 2006-2008  JÃrg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -111,4 +111,88 @@
 	public override bool is_pure () {
 		return false;
 	}
+
+	string get_lambda_name (SemanticAnalyzer analyzer) {
+		var result = "__lambda%d".printf (analyzer.next_lambda_id);
+
+		analyzer.next_lambda_id++;
+
+		return result;
+	}
+
+	public override bool check (SemanticAnalyzer analyzer) {
+		if (checked) {
+			return !error;
+		}
+
+		checked = true;
+
+		if (!(target_type is DelegateType)) {
+			error = true;
+			Report.error (source_reference, "lambda expression not allowed in this context");
+			return false;
+		}
+
+		bool in_instance_method = false;
+		var current_method = analyzer.find_current_method ();
+		if (current_method != null) {
+			in_instance_method = (current_method.binding == MemberBinding.INSTANCE);
+		} else {
+			in_instance_method = analyzer.is_in_constructor ();
+		}
+
+		var cb = (Delegate) ((DelegateType) target_type).delegate_symbol;
+		method = new Method (get_lambda_name (analyzer), cb.return_type);
+		if (!cb.has_target || !in_instance_method) {
+			method.binding = MemberBinding.STATIC;
+		}
+		method.owner = analyzer.current_symbol.scope;
+
+		var lambda_params = get_parameters ();
+		Iterator<string> lambda_param_it = lambda_params.iterator ();
+		foreach (FormalParameter cb_param in cb.get_parameters ()) {
+			if (!lambda_param_it.next ()) {
+				/* lambda expressions are allowed to have less parameters */
+				break;
+			}
+
+			string lambda_param = lambda_param_it.get ();
+
+			var param = new FormalParameter (lambda_param, cb_param.parameter_type);
+
+			method.add_parameter (param);
+		}
+
+		if (lambda_param_it.next ()) {
+			/* lambda expressions may not expect more parameters */
+			error = true;
+			Report.error (source_reference, "lambda expression: too many parameters");
+			return false;
+		}
+
+		if (expression_body != null) {
+			var block = new Block (source_reference);
+			block.scope.parent_scope = method.scope;
+
+			if (method.return_type.data_type != null) {
+				block.add_statement (new ReturnStatement (expression_body, source_reference));
+			} else {
+				block.add_statement (new ExpressionStatement (expression_body, source_reference));
+			}
+
+			method.body = block;
+		} else {
+			method.body = statement_body;
+		}
+		method.body.owner = method.scope;
+
+		/* lambda expressions should be usable like MemberAccess of a method */
+		symbol_reference = method;
+
+		accept_children (analyzer);
+
+		value_type = new MethodType (method);
+
+		return !error;
+	}
 }

Modified: trunk/vala/valanullliteral.vala
==============================================================================
--- trunk/vala/valanullliteral.vala	(original)
+++ trunk/vala/valanullliteral.vala	Mon Nov 10 18:56:28 2008
@@ -49,4 +49,16 @@
 	public override bool is_pure () {
 		return true;
 	}
+
+	public override bool check (SemanticAnalyzer analyzer) {
+		if (checked) {
+			return !error;
+		}
+
+		checked = true;
+
+		value_type = new NullType (source_reference);
+
+		return !error;
+	}
 }

Modified: trunk/vala/valaobjectcreationexpression.vala
==============================================================================
--- trunk/vala/valaobjectcreationexpression.vala	(original)
+++ trunk/vala/valaobjectcreationexpression.vala	Mon Nov 10 18:56:28 2008
@@ -1,6 +1,6 @@
 /* valaobjectcreationexpression.vala
  *
- * Copyright (C) 2006-2007  JÃrg Billeter
+ * Copyright (C) 2006-2008  JÃrg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public

Modified: trunk/vala/valaparenthesizedexpression.vala
==============================================================================
--- trunk/vala/valaparenthesizedexpression.vala	(original)
+++ trunk/vala/valaparenthesizedexpression.vala	Mon Nov 10 18:56:28 2008
@@ -72,4 +72,38 @@
 	public override bool is_pure () {
 		return inner.is_pure ();
 	}
+
+	public override bool check (SemanticAnalyzer analyzer) {
+		if (checked) {
+			return !error;
+		}
+
+		checked = true;
+
+		inner.target_type = target_type;
+
+		accept_children (analyzer);
+
+		if (inner.error) {
+			// ignore inner error
+			error = true;
+			return false;
+		}
+
+		if (inner.value_type == null) {
+			// static type may be null for method references
+			error = true;
+			Report.error (inner.source_reference, "Invalid expression type");
+			return false;
+		}
+
+		value_type = inner.value_type.copy ();
+		// don't call g_object_ref_sink on inner and outer expression
+		value_type.floating_reference = false;
+
+		// don't transform expression twice
+		inner.target_type = inner.value_type.copy ();
+
+		return !error;
+	}
 }

Modified: trunk/vala/valapointerindirection.vala
==============================================================================
--- trunk/vala/valapointerindirection.vala	(original)
+++ trunk/vala/valapointerindirection.vala	Mon Nov 10 18:56:28 2008
@@ -1,6 +1,6 @@
 /* valapointerindirection.vala
  *
- * Copyright (C) 2007  JÃrg Billeter
+ * Copyright (C) 2007-2008  JÃrg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -69,4 +69,36 @@
 	public override bool is_pure () {
 		return inner.is_pure ();
 	}
+
+	public override bool check (SemanticAnalyzer analyzer) {
+		if (checked) {
+			return !error;
+		}
+
+		checked = true;
+
+		if (inner.error) {
+			return false;
+		}
+		if (inner.value_type == null) {
+			error = true;
+			Report.error (source_reference, "internal error: unknown type of inner expression");
+			return false;
+		}
+		if (inner.value_type is PointerType) {
+			var pointer_type = (PointerType) inner.value_type;
+			if (pointer_type.base_type is ReferenceType) {
+				error = true;
+				Report.error (source_reference, "Pointer indirection not supported for this expression");
+				return false;
+			}
+			value_type = pointer_type.base_type;
+		} else {
+			error = true;
+			Report.error (source_reference, "Pointer indirection not supported for this expression");
+			return false;
+		}
+
+		return !error;
+	}
 }

Modified: trunk/vala/valapostfixexpression.vala
==============================================================================
--- trunk/vala/valapostfixexpression.vala	(original)
+++ trunk/vala/valapostfixexpression.vala	Mon Nov 10 18:56:28 2008
@@ -1,6 +1,6 @@
 /* valapostfixexpression.vala
  *
- * Copyright (C) 2006-2007  JÃrg Billeter
+ * Copyright (C) 2006-2008  JÃrg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -61,4 +61,16 @@
 	public override bool is_pure () {
 		return false;
 	}
+
+	public override bool check (SemanticAnalyzer analyzer) {
+		if (checked) {
+			return !error;
+		}
+
+		checked = true;
+
+		value_type = inner.value_type;
+
+		return !error;
+	}
 }

Modified: trunk/vala/valarealliteral.vala
==============================================================================
--- trunk/vala/valarealliteral.vala	(original)
+++ trunk/vala/valarealliteral.vala	Mon Nov 10 18:56:28 2008
@@ -69,4 +69,16 @@
 	public override string to_string () {
 		return value;
 	}
+
+	public override bool check (SemanticAnalyzer analyzer) {
+		if (checked) {
+			return !error;
+		}
+
+		checked = true;
+
+		value_type = new ValueType ((TypeSymbol) analyzer.root_symbol.scope.lookup (get_type_name ()));
+
+		return !error;
+	}
 }

Modified: trunk/vala/valareferencetransferexpression.vala
==============================================================================
--- trunk/vala/valareferencetransferexpression.vala	(original)
+++ trunk/vala/valareferencetransferexpression.vala	Mon Nov 10 18:56:28 2008
@@ -71,4 +71,40 @@
 	public override bool is_pure () {
 		return false;
 	}
+
+	public override bool check (SemanticAnalyzer analyzer) {
+		if (checked) {
+			return !error;
+		}
+
+		checked = true;
+
+		inner.lvalue = true;
+
+		accept_children (analyzer);
+
+		if (inner.error) {
+			/* if there was an error in the inner expression, skip type check */
+			error = true;
+			return false;
+		}
+
+		if (!(inner is MemberAccess || inner is ElementAccess)) {
+			error = true;
+			Report.error (source_reference, "Reference transfer not supported for this expression");
+			return false;
+		}
+
+		if (!inner.value_type.is_disposable ()
+		    && !(inner.value_type is PointerType)) {
+			error = true;
+			Report.error (source_reference, "No reference to be transferred");
+			return false;
+		}
+
+		value_type = inner.value_type.copy ();
+		value_type.value_owned = true;
+
+		return !error;
+	}
 }

Modified: trunk/vala/valasemanticanalyzer.vala
==============================================================================
--- trunk/vala/valasemanticanalyzer.vala	(original)
+++ trunk/vala/valasemanticanalyzer.vala	Mon Nov 10 18:56:28 2008
@@ -63,7 +63,7 @@
 	public Interface collection_type;
 	public Interface map_type;
 
-	private int next_lambda_id = 0;
+	public int next_lambda_id = 0;
 
 	// keep replaced alive to make sure they remain valid
 	// for the whole execution of CodeNode.accept
@@ -300,27 +300,27 @@
 	}
 
 	public override void visit_boolean_literal (BooleanLiteral expr) {
-		expr.value_type = bool_type;
+		expr.check (this);
 	}
 
 	public override void visit_character_literal (CharacterLiteral expr) {
-		expr.value_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("char"));
+		expr.check (this);
 	}
 
 	public override void visit_integer_literal (IntegerLiteral expr) {
-		expr.value_type = new IntegerType ((TypeSymbol) root_symbol.scope.lookup (expr.get_type_name ()), expr.value, expr.get_type_name ());
+		expr.check (this);
 	}
 
 	public override void visit_real_literal (RealLiteral expr) {
-		expr.value_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup (expr.get_type_name ()));
+		expr.check (this);
 	}
 
 	public override void visit_string_literal (StringLiteral expr) {
-		expr.value_type = string_type.copy ();
+		expr.check (this);
 	}
 
 	public override void visit_null_literal (NullLiteral expr) {
-		expr.value_type = new NullType (expr.source_reference);
+		expr.check (this);
 	}
 
 	public DataType? get_value_type_for_symbol (Symbol sym, bool lvalue) {
@@ -421,29 +421,7 @@
 	}
 
 	public override void visit_parenthesized_expression (ParenthesizedExpression expr) {
-		expr.inner.target_type = expr.target_type;
-
-		expr.accept_children (this);
-
-		if (expr.inner.error) {
-			// ignore inner error
-			expr.error = true;
-			return;
-		}
-
-		if (expr.inner.value_type == null) {
-			// static type may be null for method references
-			expr.error = true;
-			Report.error (expr.inner.source_reference, "Invalid expression type");
-			return;
-		}
-
-		expr.value_type = expr.inner.value_type.copy ();
-		// don't call g_object_ref_sink on inner and outer expression
-		expr.value_type.floating_reference = false;
-
-		// don't transform expression twice
-		expr.inner.target_type = expr.inner.value_type.copy ();
+		expr.check (this);
 	}
 	
 	public override void visit_member_access (MemberAccess expr) {
@@ -799,38 +777,11 @@
 	}
 
 	public override void visit_base_access (BaseAccess expr) {
-		if (!is_in_instance_method ()) {
-			expr.error = true;
-			Report.error (expr.source_reference, "Base access invalid outside of instance methods");
-			return;
-		}
-
-		if (current_class == null) {
-			if (current_struct == null) {
-				expr.error = true;
-				Report.error (expr.source_reference, "Base access invalid outside of class and struct");
-				return;
-			} else if (current_struct.get_base_types ().size != 1) {
-				expr.error = true;
-				Report.error (expr.source_reference, "Base access invalid without base type %d".printf (current_struct.get_base_types ().size));
-				return;
-			}
-			Iterator<DataType> base_type_it = current_struct.get_base_types ().iterator ();
-			base_type_it.next ();
-			expr.value_type = base_type_it.get ();
-		} else if (current_class.base_class == null) {
-			expr.error = true;
-			Report.error (expr.source_reference, "Base access invalid without base class");
-			return;
-		} else {
-			expr.value_type = new ObjectType (current_class.base_class);
-		}
-
-		expr.symbol_reference = expr.value_type.data_type;
+		expr.check (this);
 	}
 
 	public override void visit_postfix_expression (PostfixExpression expr) {
-		expr.value_type = expr.inner.value_type;
+		expr.check (this);
 	}
 
 	public override void visit_object_creation_expression (ObjectCreationExpression expr) {
@@ -872,213 +823,31 @@
 	}
 
 	public override void visit_sizeof_expression (SizeofExpression expr) {
-		expr.value_type = ulong_type;
+		expr.check (this);
 	}
 
 	public override void visit_typeof_expression (TypeofExpression expr) {
-		expr.value_type = type_type;
-	}
-
-	private bool is_numeric_type (DataType type) {
-		if (!(type.data_type is Struct)) {
-			return false;
-		}
-
-		var st = (Struct) type.data_type;
-		return st.is_integer_type () || st.is_floating_type ();
-	}
-
-	private bool is_integer_type (DataType type) {
-		if (!(type.data_type is Struct)) {
-			return false;
-		}
-
-		var st = (Struct) type.data_type;
-		return st.is_integer_type ();
+		expr.check (this);
 	}
 
 	public override void visit_unary_expression (UnaryExpression expr) {
-		if (expr.operator == UnaryOperator.REF || expr.operator == UnaryOperator.OUT) {
-			expr.inner.lvalue = true;
-			expr.inner.target_type = expr.target_type;
-		}
-
-		expr.accept_children (this);
-
-		if (expr.inner.error) {
-			/* if there was an error in the inner expression, skip type check */
-			expr.error = true;
-			return;
-		}
-
-		if (expr.operator == UnaryOperator.PLUS || expr.operator == UnaryOperator.MINUS) {
-			// integer or floating point type
-			if (!is_numeric_type (expr.inner.value_type)) {
-				expr.error = true;
-				Report.error (expr.source_reference, "Operator not supported for `%s'".printf (expr.inner.value_type.to_string ()));
-				return;
-			}
-
-			expr.value_type = expr.inner.value_type;
-		} else if (expr.operator == UnaryOperator.LOGICAL_NEGATION) {
-			// boolean type
-			if (!expr.inner.value_type.compatible (bool_type)) {
-				expr.error = true;
-				Report.error (expr.source_reference, "Operator not supported for `%s'".printf (expr.inner.value_type.to_string ()));
-				return;
-			}
-
-			expr.value_type = expr.inner.value_type;
-		} else if (expr.operator == UnaryOperator.BITWISE_COMPLEMENT) {
-			// integer type
-			if (!is_integer_type (expr.inner.value_type)) {
-				expr.error = true;
-				Report.error (expr.source_reference, "Operator not supported for `%s'".printf (expr.inner.value_type.to_string ()));
-				return;
-			}
-
-			expr.value_type = expr.inner.value_type;
-		} else if (expr.operator == UnaryOperator.INCREMENT ||
-		           expr.operator == UnaryOperator.DECREMENT) {
-			// integer type
-			if (!is_integer_type (expr.inner.value_type)) {
-				expr.error = true;
-				Report.error (expr.source_reference, "Operator not supported for `%s'".printf (expr.inner.value_type.to_string ()));
-				return;
-			}
-
-			var ma = find_member_access (expr.inner);
-			if (ma == null) {
-				expr.error = true;
-				Report.error (expr.source_reference, "Prefix operators not supported for this expression");
-				return;
-			}
-
-			var old_value = new MemberAccess (ma.inner, ma.member_name, expr.inner.source_reference);
-			var bin = new BinaryExpression (expr.operator == UnaryOperator.INCREMENT ? BinaryOperator.PLUS : BinaryOperator.MINUS, old_value, new IntegerLiteral ("1"), expr.source_reference);
-
-			var assignment = new Assignment (ma, bin, AssignmentOperator.SIMPLE, expr.source_reference);
-			var parenthexp = new ParenthesizedExpression (assignment, expr.source_reference);
-			parenthexp.target_type = expr.target_type;
-			replaced_nodes.add (expr);
-			expr.parent_node.replace_expression (expr, parenthexp);
-			parenthexp.accept (this);
-			return;
-		} else if (expr.operator == UnaryOperator.REF || expr.operator == UnaryOperator.OUT) {
-			if (expr.inner.symbol_reference is Field || expr.inner.symbol_reference is FormalParameter || expr.inner.symbol_reference is LocalVariable) {
-				// ref and out can only be used with fields, parameters, and local variables
-				expr.lvalue = true;
-				expr.value_type = expr.inner.value_type;
-			} else {
-				expr.error = true;
-				Report.error (expr.source_reference, "ref and out method arguments can only be used with fields, parameters, and local variables");
-				return;
-			}
-		} else {
-			expr.error = true;
-			Report.error (expr.source_reference, "internal error: unsupported unary operator");
-			return;
-		}
-	}
-
-	private MemberAccess? find_member_access (Expression expr) {
-		if (expr is ParenthesizedExpression) {
-			var pe = (ParenthesizedExpression) expr;
-			return find_member_access (pe.inner);
-		}
-
-		if (expr is MemberAccess) {
-			return (MemberAccess) expr;
-		}
-
-		return null;
+		expr.check (this);
 	}
 
 	public override void visit_cast_expression (CastExpression expr) {
-		if (expr.inner.error) {
-			expr.error = true;
-			return;
-		}
-
-		// FIXME: check whether cast is allowed
-
-		current_source_file.add_type_dependency (expr.type_reference, SourceFileDependencyType.SOURCE);
-
-		expr.value_type = expr.type_reference;
-		expr.value_type.value_owned = expr.inner.value_type.value_owned;
-
-		expr.inner.target_type = expr.inner.value_type.copy ();
+		expr.check (this);
 	}
 
 	public override void visit_pointer_indirection (PointerIndirection expr) {
-		if (expr.inner.error) {
-			return;
-		}
-		if (expr.inner.value_type == null) {
-			expr.error = true;
-			Report.error (expr.source_reference, "internal error: unknown type of inner expression");
-			return;
-		}
-		if (expr.inner.value_type is PointerType) {
-			var pointer_type = (PointerType) expr.inner.value_type;
-			if (pointer_type.base_type is ReferenceType) {
-				expr.error = true;
-				Report.error (expr.source_reference, "Pointer indirection not supported for this expression");
-				return;
-			}
-			expr.value_type = pointer_type.base_type;
-		} else {
-			expr.error = true;
-			Report.error (expr.source_reference, "Pointer indirection not supported for this expression");
-			return;
-		}
+		expr.check (this);
 	}
 
 	public override void visit_addressof_expression (AddressofExpression expr) {
-		if (expr.inner.error) {
-			return;
-		}
-		if (!(expr.inner.value_type is ValueType
-		      || expr.inner.value_type is ObjectType
-		      || expr.inner.value_type is PointerType)) {
-			expr.error = true;
-			Report.error (expr.source_reference, "Address-of operator not supported for this expression");
-			return;
-		}
-
-		if (expr.inner.value_type.is_reference_type_or_type_parameter ()) {
-			expr.value_type = new PointerType (new PointerType (expr.inner.value_type));
-		} else {
-			expr.value_type = new PointerType (expr.inner.value_type);
-		}
+		expr.check (this);
 	}
 
 	public override void visit_reference_transfer_expression (ReferenceTransferExpression expr) {
-		expr.inner.lvalue = true;
-
-		expr.accept_children (this);
-
-		if (expr.inner.error) {
-			/* if there was an error in the inner expression, skip type check */
-			expr.error = true;
-			return;
-		}
-
-		if (!(expr.inner is MemberAccess || expr.inner is ElementAccess)) {
-			expr.error = true;
-			Report.error (expr.source_reference, "Reference transfer not supported for this expression");
-			return;
-		}
-
-		if (!expr.inner.value_type.is_disposable ()
-		    && !(expr.inner.value_type is PointerType)) {
-			expr.error = true;
-			Report.error (expr.source_reference, "No reference to be transferred");
-			return;
-		}
-
-		expr.value_type = expr.inner.value_type.copy ();
-		expr.value_type.value_owned = true;
+		expr.check (this);
 	}
 
 	public DataType? get_arithmetic_result_type (DataType left_type, DataType right_type) {
@@ -1118,46 +887,11 @@
 	}
 
 	public override void visit_type_check (TypeCheck expr) {
-		if (expr.type_reference.data_type == null) {
-			/* if type resolving didn't succeed, skip this check */
-			expr.error = true;
-			return;
-		}
-
-		current_source_file.add_type_dependency (expr.type_reference, SourceFileDependencyType.SOURCE);
-
-		expr.value_type = bool_type;
+		expr.check (this);
 	}
 
 	public override void visit_conditional_expression (ConditionalExpression expr) {
-		if (expr.condition.error || expr.false_expression.error || expr.true_expression.error) {
-			return;
-		}
-
-		if (!expr.condition.value_type.compatible (bool_type)) {
-			expr.error = true;
-			Report.error (expr.condition.source_reference, "Condition must be boolean");
-			return;
-		}
-
-		/* FIXME: support memory management */
-		if (expr.false_expression.value_type.compatible (expr.true_expression.value_type)) {
-			expr.value_type = expr.true_expression.value_type.copy ();
-		} else if (expr.true_expression.value_type.compatible (expr.false_expression.value_type)) {
-			expr.value_type = expr.false_expression.value_type.copy ();
-		} else {
-			expr.error = true;
-			Report.error (expr.condition.source_reference, "Incompatible expressions");
-			return;
-		}
-	}
-
-	private string get_lambda_name () {
-		var result = "__lambda%d".printf (next_lambda_id);
-
-		next_lambda_id++;
-
-		return result;
+		expr.check (this);
 	}
 
 	public Method? find_current_method () {
@@ -1183,71 +917,7 @@
 	}
 
 	public override void visit_lambda_expression (LambdaExpression l) {
-		if (!(l.target_type is DelegateType)) {
-			l.error = true;
-			Report.error (l.source_reference, "lambda expression not allowed in this context");
-			return;
-		}
-
-		bool in_instance_method = false;
-		var current_method = find_current_method ();
-		if (current_method != null) {
-			in_instance_method = (current_method.binding == MemberBinding.INSTANCE);
-		} else {
-			in_instance_method = is_in_constructor ();
-		}
-
-		var cb = (Delegate) ((DelegateType) l.target_type).delegate_symbol;
-		l.method = new Method (get_lambda_name (), cb.return_type);
-		if (!cb.has_target || !in_instance_method) {
-			l.method.binding = MemberBinding.STATIC;
-		}
-		l.method.owner = current_symbol.scope;
-
-		var lambda_params = l.get_parameters ();
-		Iterator<string> lambda_param_it = lambda_params.iterator ();
-		foreach (FormalParameter cb_param in cb.get_parameters ()) {
-			if (!lambda_param_it.next ()) {
-				/* lambda expressions are allowed to have less parameters */
-				break;
-			}
-
-			string lambda_param = lambda_param_it.get ();
-
-			var param = new FormalParameter (lambda_param, cb_param.parameter_type);
-
-			l.method.add_parameter (param);
-		}
-
-		if (lambda_param_it.next ()) {
-			/* lambda expressions may not expect more parameters */
-			l.error = true;
-			Report.error (l.source_reference, "lambda expression: too many parameters");
-			return;
-		}
-
-		if (l.expression_body != null) {
-			var block = new Block (l.source_reference);
-			block.scope.parent_scope = l.method.scope;
-
-			if (l.method.return_type.data_type != null) {
-				block.add_statement (new ReturnStatement (l.expression_body, l.source_reference));
-			} else {
-				block.add_statement (new ExpressionStatement (l.expression_body, l.source_reference));
-			}
-
-			l.method.body = block;
-		} else {
-			l.method.body = l.statement_body;
-		}
-		l.method.body.owner = l.method.scope;
-
-		/* lambda expressions should be usable like MemberAccess of a method */
-		l.symbol_reference = l.method;
-
-		l.accept_children (this);
-
-		l.value_type = new MethodType (l.method);
+		l.check (this);
 	}
 
 	public override void visit_assignment (Assignment a) {

Modified: trunk/vala/valasizeofexpression.vala
==============================================================================
--- trunk/vala/valasizeofexpression.vala	(original)
+++ trunk/vala/valasizeofexpression.vala	Mon Nov 10 18:56:28 2008
@@ -1,6 +1,6 @@
 /* valasizeofexpression.vala
  *
- * Copyright (C) 2006-2007  JÃrg Billeter
+ * Copyright (C) 2006-2008  JÃrg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -68,4 +68,16 @@
 			type_reference = new_type;
 		}
 	}
+
+	public override bool check (SemanticAnalyzer analyzer) {
+		if (checked) {
+			return !error;
+		}
+
+		checked = true;
+
+		value_type = analyzer.ulong_type;
+
+		return !error;
+	}
 }

Modified: trunk/vala/valastringliteral.vala
==============================================================================
--- trunk/vala/valastringliteral.vala	(original)
+++ trunk/vala/valastringliteral.vala	Mon Nov 10 18:56:28 2008
@@ -76,4 +76,16 @@
 	public override string to_string () {
 		return value;
 	}
+
+	public override bool check (SemanticAnalyzer analyzer) {
+		if (checked) {
+			return !error;
+		}
+
+		checked = true;
+
+		value_type = analyzer.string_type.copy ();
+
+		return !error;
+	}
 }

Modified: trunk/vala/valatypecheck.vala
==============================================================================
--- trunk/vala/valatypecheck.vala	(original)
+++ trunk/vala/valatypecheck.vala	Mon Nov 10 18:56:28 2008
@@ -1,6 +1,6 @@
 /* valatypecheck.vala
  *
- * Copyright (C) 2006-2007  JÃrg Billeter
+ * Copyright (C) 2006-2008  JÃrg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -77,4 +77,24 @@
 			type_reference = new_type;
 		}
 	}
+
+	public override bool check (SemanticAnalyzer analyzer) {
+		if (checked) {
+			return !error;
+		}
+
+		checked = true;
+
+		if (type_reference.data_type == null) {
+			/* if type resolving didn't succeed, skip this check */
+			error = true;
+			return false;
+		}
+
+		analyzer.current_source_file.add_type_dependency (type_reference, SourceFileDependencyType.SOURCE);
+
+		value_type = analyzer.bool_type;
+
+		return !error;
+	}
 }

Modified: trunk/vala/valatypeofexpression.vala
==============================================================================
--- trunk/vala/valatypeofexpression.vala	(original)
+++ trunk/vala/valatypeofexpression.vala	Mon Nov 10 18:56:28 2008
@@ -1,6 +1,6 @@
 /* valatypeofexpression.vala
  *
- * Copyright (C) 2006-2007  JÃrg Billeter
+ * Copyright (C) 2006-2008  JÃrg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -68,4 +68,16 @@
 			type_reference = new_type;
 		}
 	}
+
+	public override bool check (SemanticAnalyzer analyzer) {
+		if (checked) {
+			return !error;
+		}
+
+		checked = true;
+
+		value_type = analyzer.type_type;
+
+		return !error;
+	}
 }

Modified: trunk/vala/valaunaryexpression.vala
==============================================================================
--- trunk/vala/valaunaryexpression.vala	(original)
+++ trunk/vala/valaunaryexpression.vala	Mon Nov 10 18:56:28 2008
@@ -104,6 +104,129 @@
 
 		return inner.is_pure ();
 	}
+
+	bool is_numeric_type (DataType type) {
+		if (!(type.data_type is Struct)) {
+			return false;
+		}
+
+		var st = (Struct) type.data_type;
+		return st.is_integer_type () || st.is_floating_type ();
+	}
+
+	bool is_integer_type (DataType type) {
+		if (!(type.data_type is Struct)) {
+			return false;
+		}
+
+		var st = (Struct) type.data_type;
+		return st.is_integer_type ();
+	}
+
+	MemberAccess? find_member_access (Expression expr) {
+		if (expr is ParenthesizedExpression) {
+			var pe = (ParenthesizedExpression) expr;
+			return find_member_access (pe.inner);
+		}
+
+		if (expr is MemberAccess) {
+			return (MemberAccess) expr;
+		}
+
+		return null;
+	}
+
+	public override bool check (SemanticAnalyzer analyzer) {
+		if (checked) {
+			return !error;
+		}
+
+		checked = true;
+
+		if (operator == UnaryOperator.REF || operator == UnaryOperator.OUT) {
+			inner.lvalue = true;
+			inner.target_type = target_type;
+		}
+
+		accept_children (analyzer);
+
+		if (inner.error) {
+			/* if there was an error in the inner expression, skip type check */
+			error = true;
+			return false;
+		}
+
+		if (operator == UnaryOperator.PLUS || operator == UnaryOperator.MINUS) {
+			// integer or floating point type
+			if (!is_numeric_type (inner.value_type)) {
+				error = true;
+				Report.error (source_reference, "Operator not supported for `%s'".printf (inner.value_type.to_string ()));
+				return false;
+			}
+
+			value_type = inner.value_type;
+		} else if (operator == UnaryOperator.LOGICAL_NEGATION) {
+			// boolean type
+			if (!inner.value_type.compatible (analyzer.bool_type)) {
+				error = true;
+				Report.error (source_reference, "Operator not supported for `%s'".printf (inner.value_type.to_string ()));
+				return false;
+			}
+
+			value_type = inner.value_type;
+		} else if (operator == UnaryOperator.BITWISE_COMPLEMENT) {
+			// integer type
+			if (!is_integer_type (inner.value_type)) {
+				error = true;
+				Report.error (source_reference, "Operator not supported for `%s'".printf (inner.value_type.to_string ()));
+				return false;
+			}
+
+			value_type = inner.value_type;
+		} else if (operator == UnaryOperator.INCREMENT ||
+		           operator == UnaryOperator.DECREMENT) {
+			// integer type
+			if (!is_integer_type (inner.value_type)) {
+				error = true;
+				Report.error (source_reference, "Operator not supported for `%s'".printf (inner.value_type.to_string ()));
+				return false;
+			}
+
+			var ma = find_member_access (inner);
+			if (ma == null) {
+				error = true;
+				Report.error (source_reference, "Prefix operators not supported for this expression");
+				return false;
+			}
+
+			var old_value = new MemberAccess (ma.inner, ma.member_name, inner.source_reference);
+			var bin = new BinaryExpression (operator == UnaryOperator.INCREMENT ? BinaryOperator.PLUS : BinaryOperator.MINUS, old_value, new IntegerLiteral ("1"), source_reference);
+
+			var assignment = new Assignment (ma, bin, AssignmentOperator.SIMPLE, source_reference);
+			var parenthexp = new ParenthesizedExpression (assignment, source_reference);
+			parenthexp.target_type = target_type;
+			analyzer.replaced_nodes.add (this);
+			parent_node.replace_expression (this, parenthexp);
+			parenthexp.accept (analyzer);
+			return true;
+		} else if (operator == UnaryOperator.REF || operator == UnaryOperator.OUT) {
+			if (inner.symbol_reference is Field || inner.symbol_reference is FormalParameter || inner.symbol_reference is LocalVariable) {
+				// ref and out can only be used with fields, parameters, and local variables
+				lvalue = true;
+				value_type = inner.value_type;
+			} else {
+				error = true;
+				Report.error (source_reference, "ref and out method arguments can only be used with fields, parameters, and local variables");
+				return false;
+			}
+		} else {
+			error = true;
+			Report.error (source_reference, "internal error: unsupported unary operator");
+			return false;
+		}
+
+		return !error;
+	}
 }
 
 public enum Vala.UnaryOperator {



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