vala r1983 - in trunk: . vala



Author: juergbi
Date: Wed Nov  5 21:12:56 2008
New Revision: 1983
URL: http://svn.gnome.org/viewvc/vala?rev=1983&view=rev

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

	* vala/valaassignment.vala:
	* vala/valasemanticanalyzer.vala:

	Move assignment checking to Assignment.check


Modified:
   trunk/ChangeLog
   trunk/vala/valaassignment.vala
   trunk/vala/valasemanticanalyzer.vala

Modified: trunk/vala/valaassignment.vala
==============================================================================
--- trunk/vala/valaassignment.vala	(original)
+++ trunk/vala/valaassignment.vala	Wed Nov  5 21:12:56 2008
@@ -1,6 +1,6 @@
 /* valaassignment.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,6 +97,289 @@
 	public override bool is_pure () {
 		return false;
 	}
+
+	public override bool check (SemanticAnalyzer analyzer) {
+		if (checked) {
+			return !error;
+		}
+
+		checked = true;
+
+		left.lvalue = true;
+
+		left.accept (analyzer);
+
+		if (left.error) {
+			// skip on error in inner expression
+			error = true;
+			return false;
+		}
+
+		if (left is MemberAccess) {
+			var ma = (MemberAccess) left;
+
+			if (!(ma.symbol_reference is Signal || ma.symbol_reference is DynamicProperty) && ma.value_type == null) {
+				error = true;
+				Report.error (source_reference, "unsupported lvalue in assignment");
+				return false;
+			}
+			if (ma.prototype_access) {
+				error = true;
+				Report.error (source_reference, "Access to instance member `%s' denied".printf (ma.symbol_reference.get_full_name ()));
+				return false;
+			}
+
+			if (ma.error || ma.symbol_reference == null) {
+				error = true;
+				/* if no symbol found, skip this check */
+				return false;
+			}
+
+			if (ma.symbol_reference is DynamicSignal) {
+				// target_type not available for dynamic signals
+			} else if (ma.symbol_reference is Signal) {
+				var sig = (Signal) ma.symbol_reference;
+				right.target_type = new DelegateType (sig.get_delegate (ma.inner.value_type));
+			} else {
+				right.target_type = ma.value_type;
+			}
+		} else if (left is ElementAccess) {
+			var ea = (ElementAccess) left;
+
+			if (ea.container is MemberAccess && ea.container.symbol_reference is Signal) {
+				var ma = (MemberAccess) ea.container;
+				var sig = (Signal) ea.container.symbol_reference;
+				right.target_type = new DelegateType (sig.get_delegate (ma.inner.value_type));
+			} else {
+				right.target_type = left.value_type;
+			}
+		} else if (left is PointerIndirection) {
+			right.target_type = left.value_type;
+		} else {
+			error = true;
+			Report.error (source_reference, "unsupported lvalue in assignment");
+			return false;
+		}
+
+		right.accept (analyzer);
+
+		if (right.error) {
+			// skip on error in inner expression
+			error = true;
+			return false;
+		}
+
+		if (operator != AssignmentOperator.SIMPLE && left is MemberAccess) {
+			// transform into simple assignment
+			// FIXME: only do this if the backend doesn't support
+			// the assignment natively
+
+			var ma = (MemberAccess) left;
+
+			if (!(ma.symbol_reference is Signal)) {
+				var old_value = new MemberAccess (ma.inner, ma.member_name);
+
+				var bin = new BinaryExpression (BinaryOperator.PLUS, old_value, new ParenthesizedExpression (right, right.source_reference));
+				bin.target_type = right.target_type;
+				right.target_type = right.target_type.copy ();
+				right.target_type.value_owned = false;
+
+				if (operator == AssignmentOperator.BITWISE_OR) {
+					bin.operator = BinaryOperator.BITWISE_OR;
+				} else if (operator == AssignmentOperator.BITWISE_AND) {
+					bin.operator = BinaryOperator.BITWISE_AND;
+				} else if (operator == AssignmentOperator.BITWISE_XOR) {
+					bin.operator = BinaryOperator.BITWISE_XOR;
+				} else if (operator == AssignmentOperator.ADD) {
+					bin.operator = BinaryOperator.PLUS;
+				} else if (operator == AssignmentOperator.SUB) {
+					bin.operator = BinaryOperator.MINUS;
+				} else if (operator == AssignmentOperator.MUL) {
+					bin.operator = BinaryOperator.MUL;
+				} else if (operator == AssignmentOperator.DIV) {
+					bin.operator = BinaryOperator.DIV;
+				} else if (operator == AssignmentOperator.PERCENT) {
+					bin.operator = BinaryOperator.MOD;
+				} else if (operator == AssignmentOperator.SHIFT_LEFT) {
+					bin.operator = BinaryOperator.SHIFT_LEFT;
+				} else if (operator == AssignmentOperator.SHIFT_RIGHT) {
+					bin.operator = BinaryOperator.SHIFT_RIGHT;
+				}
+
+				right = bin;
+				right.accept (analyzer);
+
+				operator = AssignmentOperator.SIMPLE;
+			}
+		}
+
+		if (left.symbol_reference is Signal) {
+			var sig = (Signal) left.symbol_reference;
+
+			var m = right.symbol_reference as Method;
+
+			if (m == null) {
+				error = true;
+				Report.error (right.source_reference, "unsupported expression for signal handler");
+				return false;
+			}
+
+			var dynamic_sig = sig as DynamicSignal;
+			if (dynamic_sig != null) {
+				bool first = true;
+				foreach (FormalParameter param in dynamic_sig.handler.value_type.get_parameters ()) {
+					if (first) {
+						// skip sender parameter
+						first = false;
+					} else {
+						dynamic_sig.add_parameter (param.copy ());
+					}
+				}
+				right.target_type = new DelegateType (sig.get_delegate (new ObjectType ((ObjectTypeSymbol) sig.parent_symbol)));
+			} else if (!right.value_type.compatible (right.target_type)) {
+				var delegate_type = (DelegateType) right.target_type;
+
+				error = true;
+				Report.error (right.source_reference, "method `%s' is incompatible with signal `%s', expected `%s'".printf (right.value_type.to_string (), right.target_type.to_string (), delegate_type.delegate_symbol.get_prototype_string (m.name)));
+				return false;
+			}
+		} else if (left is MemberAccess) {
+			var ma = (MemberAccess) left;
+
+			if (ma.symbol_reference is Property) {
+				var prop = (Property) ma.symbol_reference;
+
+				var dynamic_prop = prop as DynamicProperty;
+				if (dynamic_prop != null) {
+					dynamic_prop.property_type = right.value_type.copy ();
+					left.value_type = dynamic_prop.property_type.copy ();
+				}
+
+				if (prop.set_accessor == null
+				    || (!prop.set_accessor.writable && !(analyzer.find_current_method () is CreationMethod || analyzer.is_in_constructor ()))) {
+					ma.error = true;
+					Report.error (ma.source_reference, "Property `%s' is read-only".printf (prop.get_full_name ()));
+					return false;
+				}
+			} else if (ma.symbol_reference is LocalVariable && right.value_type == null) {
+				var local = (LocalVariable) ma.symbol_reference;
+
+				if (right.symbol_reference is Method &&
+				    local.variable_type is DelegateType) {
+					var m = (Method) right.symbol_reference;
+					var dt = (DelegateType) local.variable_type;
+					var cb = dt.delegate_symbol;
+
+					/* check whether method matches callback type */
+					if (!cb.matches_method (m)) {
+						error = true;
+						Report.error (source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.get_full_name (), cb.get_full_name ()));
+						return false;
+					}
+
+					right.value_type = local.variable_type;
+				} else {
+					error = true;
+					Report.error (source_reference, "Assignment: Invalid callback assignment attempt");
+					return false;
+				}
+			} else if (ma.symbol_reference is Field && right.value_type == null) {
+				var f = (Field) ma.symbol_reference;
+
+				if (right.symbol_reference is Method &&
+				    f.field_type is DelegateType) {
+					var m = (Method) right.symbol_reference;
+					var dt = (DelegateType) f.field_type;
+					var cb = dt.delegate_symbol;
+
+					/* check whether method matches callback type */
+					if (!cb.matches_method (m)) {
+						f.error = true;
+						Report.error (source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.get_full_name (), cb.get_full_name ()));
+						return false;
+					}
+
+					right.value_type = f.field_type;
+				} else {
+					error = true;
+					Report.error (source_reference, "Assignment: Invalid callback assignment attempt");
+					return false;
+				}
+			} else if (left.value_type != null && right.value_type != null) {
+				/* if there was an error on either side,
+				 * i.e. {left|right}.value_type == null, skip type check */
+
+				if (!right.value_type.compatible (left.value_type)) {
+					error = true;
+					Report.error (source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (right.value_type.to_string (), left.value_type.to_string ()));
+					return false;
+				}
+
+				if (right.value_type.is_disposable ()) {
+					/* rhs transfers ownership of the expression */
+					if (!(left.value_type is PointerType) && !left.value_type.value_owned) {
+						/* lhs doesn't own the value */
+						error = true;
+						Report.error (source_reference, "Invalid assignment from owned expression to unowned variable");
+					}
+				} else if (left.value_type.value_owned) {
+					/* lhs wants to own the value
+					 * rhs doesn't transfer the ownership
+					 * code generator needs to add reference
+					 * increment calls */
+				}
+			}
+		} else if (left is ElementAccess) {
+			var ea = (ElementAccess) left;
+
+			if (!right.value_type.compatible (left.value_type)) {
+				error = true;
+				Report.error (source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (right.value_type.to_string (), left.value_type.to_string ()));
+				return false;
+			}
+
+			if (right.value_type.is_disposable ()) {
+				/* rhs transfers ownership of the expression */
+
+				DataType element_type;
+
+				if (ea.container.value_type is ArrayType) {
+					var array_type = (ArrayType) ea.container.value_type;
+					element_type = array_type.element_type;
+				} else {
+					var args = ea.container.value_type.get_type_arguments ();
+					assert (args.size == 1);
+					element_type = args.get (0);
+				}
+
+				if (!(element_type is PointerType) && !element_type.value_owned) {
+					/* lhs doesn't own the value */
+					error = true;
+					Report.error (source_reference, "Invalid assignment from owned expression to unowned variable");
+					return false;
+				}
+			} else if (left.value_type.value_owned) {
+				/* lhs wants to own the value
+				 * rhs doesn't transfer the ownership
+				 * code generator needs to add reference
+				 * increment calls */
+			}
+		} else {
+			return false;
+		}
+
+		if (left.value_type != null) {
+			value_type = left.value_type.copy ();
+			value_type.value_owned = false;
+		} else {
+			value_type = null;
+		}
+
+		add_error_types (left.get_error_types ());
+		add_error_types (right.get_error_types ());
+
+		return !error;
+	}
 }
 	
 public enum Vala.AssignmentOperator {

Modified: trunk/vala/valasemanticanalyzer.vala
==============================================================================
--- trunk/vala/valasemanticanalyzer.vala	(original)
+++ trunk/vala/valasemanticanalyzer.vala	Wed Nov  5 21:12:56 2008
@@ -3314,7 +3314,7 @@
 		return result;
 	}
 
-	private Method? find_current_method () {
+	public Method? find_current_method () {
 		var sym = current_symbol;
 		while (sym != null) {
 			if (sym is Method) {
@@ -3325,7 +3325,7 @@
 		return null;
 	}
 
-	private bool is_in_constructor () {
+	public bool is_in_constructor () {
 		var sym = current_symbol;
 		while (sym != null) {
 			if (sym is Constructor) {
@@ -3405,277 +3405,6 @@
 	}
 
 	public override void visit_assignment (Assignment a) {
-		a.left.lvalue = true;
-
-		a.left.accept (this);
-
-		if (a.left.error) {
-			// skip on error in inner expression
-			a.error = true;
-			return;
-		}
-
-		if (a.left is MemberAccess) {
-			var ma = (MemberAccess) a.left;
-
-			if (!(ma.symbol_reference is Signal || ma.symbol_reference is DynamicProperty) && ma.value_type == null) {
-				a.error = true;
-				Report.error (a.source_reference, "unsupported lvalue in assignment");
-				return;
-			}
-			if (ma.prototype_access) {
-				a.error = true;
-				Report.error (a.source_reference, "Access to instance member `%s' denied".printf (ma.symbol_reference.get_full_name ()));
-				return;
-			}
-
-			if (ma.error || ma.symbol_reference == null) {
-				a.error = true;
-				/* if no symbol found, skip this check */
-				return;
-			}
-
-			if (ma.symbol_reference is DynamicSignal) {
-				// target_type not available for dynamic signals
-			} else if (ma.symbol_reference is Signal) {
-				var sig = (Signal) ma.symbol_reference;
-				a.right.target_type = new DelegateType (sig.get_delegate (ma.inner.value_type));
-			} else {
-				a.right.target_type = ma.value_type;
-			}
-		} else if (a.left is ElementAccess) {
-			var ea = (ElementAccess) a.left;
-
-			if (ea.container is MemberAccess && ea.container.symbol_reference is Signal) {
-				var ma = (MemberAccess) ea.container;
-				var sig = (Signal) ea.container.symbol_reference;
-				a.right.target_type = new DelegateType (sig.get_delegate (ma.inner.value_type));
-			} else {
-				a.right.target_type = a.left.value_type;
-			}
-		} else if (a.left is PointerIndirection) {
-			a.right.target_type = a.left.value_type;
-		} else {
-			a.error = true;
-			Report.error (a.source_reference, "unsupported lvalue in assignment");
-			return;
-		}
-
-		a.right.accept (this);
-
-		if (a.right.error) {
-			// skip on error in inner expression
-			a.error = true;
-			return;
-		}
-
-		if (a.operator != AssignmentOperator.SIMPLE && a.left is MemberAccess) {
-			// transform into simple assignment
-			// FIXME: only do this if the backend doesn't support
-			// the assignment natively
-
-			var ma = (MemberAccess) a.left;
-
-			if (!(ma.symbol_reference is Signal)) {
-				var old_value = new MemberAccess (ma.inner, ma.member_name);
-
-				var bin = new BinaryExpression (BinaryOperator.PLUS, old_value, new ParenthesizedExpression (a.right, a.right.source_reference));
-				bin.target_type = a.right.target_type;
-				a.right.target_type = a.right.target_type.copy ();
-				a.right.target_type.value_owned = false;
-
-				if (a.operator == AssignmentOperator.BITWISE_OR) {
-					bin.operator = BinaryOperator.BITWISE_OR;
-				} else if (a.operator == AssignmentOperator.BITWISE_AND) {
-					bin.operator = BinaryOperator.BITWISE_AND;
-				} else if (a.operator == AssignmentOperator.BITWISE_XOR) {
-					bin.operator = BinaryOperator.BITWISE_XOR;
-				} else if (a.operator == AssignmentOperator.ADD) {
-					bin.operator = BinaryOperator.PLUS;
-				} else if (a.operator == AssignmentOperator.SUB) {
-					bin.operator = BinaryOperator.MINUS;
-				} else if (a.operator == AssignmentOperator.MUL) {
-					bin.operator = BinaryOperator.MUL;
-				} else if (a.operator == AssignmentOperator.DIV) {
-					bin.operator = BinaryOperator.DIV;
-				} else if (a.operator == AssignmentOperator.PERCENT) {
-					bin.operator = BinaryOperator.MOD;
-				} else if (a.operator == AssignmentOperator.SHIFT_LEFT) {
-					bin.operator = BinaryOperator.SHIFT_LEFT;
-				} else if (a.operator == AssignmentOperator.SHIFT_RIGHT) {
-					bin.operator = BinaryOperator.SHIFT_RIGHT;
-				}
-
-				a.right = bin;
-				a.right.accept (this);
-
-				a.operator = AssignmentOperator.SIMPLE;
-			}
-		}
-
-		if (a.left.symbol_reference is Signal) {
-			var sig = (Signal) a.left.symbol_reference;
-
-			var m = a.right.symbol_reference as Method;
-
-			if (m == null) {
-				a.error = true;
-				Report.error (a.right.source_reference, "unsupported expression for signal handler");
-				return;
-			}
-
-			var dynamic_sig = sig as DynamicSignal;
-			if (dynamic_sig != null) {
-				bool first = true;
-				foreach (FormalParameter param in dynamic_sig.handler.value_type.get_parameters ()) {
-					if (first) {
-						// skip sender parameter
-						first = false;
-					} else {
-						dynamic_sig.add_parameter (param.copy ());
-					}
-				}
-				a.right.target_type = new DelegateType (sig.get_delegate (new ObjectType ((ObjectTypeSymbol) sig.parent_symbol)));
-			} else if (!a.right.value_type.compatible (a.right.target_type)) {
-				var delegate_type = (DelegateType) a.right.target_type;
-
-				a.error = true;
-				Report.error (a.right.source_reference, "method `%s' is incompatible with signal `%s', expected `%s'".printf (a.right.value_type.to_string (), a.right.target_type.to_string (), delegate_type.delegate_symbol.get_prototype_string (m.name)));
-				return;
-			}
-		} else if (a.left is MemberAccess) {
-			var ma = (MemberAccess) a.left;
-
-			if (ma.symbol_reference is Property) {
-				var prop = (Property) ma.symbol_reference;
-
-				var dynamic_prop = prop as DynamicProperty;
-				if (dynamic_prop != null) {
-					dynamic_prop.property_type = a.right.value_type.copy ();
-					a.left.value_type = dynamic_prop.property_type.copy ();
-				}
-
-				if (prop.set_accessor == null
-				    || (!prop.set_accessor.writable && !(find_current_method () is CreationMethod || is_in_constructor ()))) {
-					ma.error = true;
-					Report.error (ma.source_reference, "Property `%s' is read-only".printf (prop.get_full_name ()));
-					return;
-				}
-			} else if (ma.symbol_reference is LocalVariable && a.right.value_type == null) {
-				var local = (LocalVariable) ma.symbol_reference;
-
-				if (a.right.symbol_reference is Method &&
-				    local.variable_type is DelegateType) {
-					var m = (Method) a.right.symbol_reference;
-					var dt = (DelegateType) local.variable_type;
-					var cb = dt.delegate_symbol;
-
-					/* check whether method matches callback type */
-					if (!cb.matches_method (m)) {
-						a.error = true;
-						Report.error (a.source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.get_full_name (), cb.get_full_name ()));
-						return;
-					}
-
-					a.right.value_type = local.variable_type;
-				} else {
-					a.error = true;
-					Report.error (a.source_reference, "Assignment: Invalid callback assignment attempt");
-					return;
-				}
-			} else if (ma.symbol_reference is Field && a.right.value_type == null) {
-				var f = (Field) ma.symbol_reference;
-
-				if (a.right.symbol_reference is Method &&
-				    f.field_type is DelegateType) {
-					var m = (Method) a.right.symbol_reference;
-					var dt = (DelegateType) f.field_type;
-					var cb = dt.delegate_symbol;
-
-					/* check whether method matches callback type */
-					if (!cb.matches_method (m)) {
-						f.error = true;
-						Report.error (a.source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.get_full_name (), cb.get_full_name ()));
-						return;
-					}
-
-					a.right.value_type = f.field_type;
-				} else {
-					a.error = true;
-					Report.error (a.source_reference, "Assignment: Invalid callback assignment attempt");
-					return;
-				}
-			} else if (a.left.value_type != null && a.right.value_type != null) {
-				/* if there was an error on either side,
-				 * i.e. a.{left|right}.value_type == null, skip type check */
-
-				if (!a.right.value_type.compatible (a.left.value_type)) {
-					a.error = true;
-					Report.error (a.source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (a.right.value_type.to_string (), a.left.value_type.to_string ()));
-					return;
-				}
-
-				if (a.right.value_type.is_disposable ()) {
-					/* rhs transfers ownership of the expression */
-					if (!(a.left.value_type is PointerType) && !a.left.value_type.value_owned) {
-						/* lhs doesn't own the value */
-						a.error = true;
-						Report.error (a.source_reference, "Invalid assignment from owned expression to unowned variable");
-					}
-				} else if (a.left.value_type.value_owned) {
-					/* lhs wants to own the value
-					 * rhs doesn't transfer the ownership
-					 * code generator needs to add reference
-					 * increment calls */
-				}
-			}
-		} else if (a.left is ElementAccess) {
-			var ea = (ElementAccess) a.left;
-
-			if (!a.right.value_type.compatible (a.left.value_type)) {
-				a.error = true;
-				Report.error (a.source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (a.right.value_type.to_string (), a.left.value_type.to_string ()));
-				return;
-			}
-
-			if (a.right.value_type.is_disposable ()) {
-				/* rhs transfers ownership of the expression */
-
-				DataType element_type;
-
-				if (ea.container.value_type is ArrayType) {
-					var array_type = (ArrayType) ea.container.value_type;
-					element_type = array_type.element_type;
-				} else {
-					var args = ea.container.value_type.get_type_arguments ();
-					assert (args.size == 1);
-					element_type = args.get (0);
-				}
-
-				if (!(element_type is PointerType) && !element_type.value_owned) {
-					/* lhs doesn't own the value */
-					a.error = true;
-					Report.error (a.source_reference, "Invalid assignment from owned expression to unowned variable");
-					return;
-				}
-			} else if (a.left.value_type.value_owned) {
-				/* lhs wants to own the value
-				 * rhs doesn't transfer the ownership
-				 * code generator needs to add reference
-				 * increment calls */
-			}
-		} else {
-			return;
-		}
-
-		if (a.left.value_type != null) {
-			a.value_type = a.left.value_type.copy ();
-			a.value_type.value_owned = false;
-		} else {
-			a.value_type = null;
-		}
-
-		a.add_error_types (a.left.get_error_types ());
-		a.add_error_types (a.right.get_error_types ());
+		a.check (this);
 	}
 }



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