vala r2021 - in trunk: . gobject vala



Author: juergbi
Date: Fri Nov 14 20:57:37 2008
New Revision: 2021
URL: http://svn.gnome.org/viewvc/vala?rev=2021&view=rev

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

	* vala/valaformalparameter.vala:
	* vala/valainterfacewriter.vala:
	* vala/valainvocationexpression.vala:
	* vala/valaparser.vala:
	* vala/valascanner.vala:
	* vala/valasemanticanalyzer.vala:
	* vala/valatokentype.vala:
	* gobject/valaccodeinvocationexpressionmodule.vala:

	Support parameter arrays, fixes bug 538897


Modified:
   trunk/ChangeLog
   trunk/gobject/valaccodeinvocationexpressionmodule.vala
   trunk/vala/valaformalparameter.vala
   trunk/vala/valainterfacewriter.vala
   trunk/vala/valainvocationexpression.vala
   trunk/vala/valaparser.vala
   trunk/vala/valascanner.vala
   trunk/vala/valasemanticanalyzer.vala
   trunk/vala/valatokentype.vala

Modified: trunk/gobject/valaccodeinvocationexpressionmodule.vala
==============================================================================
--- trunk/gobject/valaccodeinvocationexpressionmodule.vala	(original)
+++ trunk/gobject/valaccodeinvocationexpressionmodule.vala	Fri Nov 14 20:57:37 2008
@@ -171,7 +171,7 @@
 			CCodeExpression cexpr = (CCodeExpression) arg.ccodenode;
 			if (params_it.next ()) {
 				var param = params_it.get ();
-				ellipsis = param.ellipsis;
+				ellipsis = param.params_array || param.ellipsis;
 				if (!ellipsis) {
 					// if the vala argument expands to multiple C arguments,
 					// we have to make sure that the C arguments don't depend
@@ -311,7 +311,7 @@
 			 * the additional parameter is an ellipsis parameter
 			 * otherwise there is a bug in the semantic analyzer
 			 */
-			assert (param.ellipsis);
+			assert (param.params_array || param.ellipsis);
 			ellipsis = true;
 		}
 

Modified: trunk/vala/valaformalparameter.vala
==============================================================================
--- trunk/vala/valaformalparameter.vala	(original)
+++ trunk/vala/valaformalparameter.vala	Fri Nov 14 20:57:37 2008
@@ -48,6 +48,12 @@
 	public bool ellipsis { get; set; }
 	
 	/**
+	 * Specifies whether the methods accepts an indefinite number of
+	 * parameters.
+	 */
+	public bool params_array { get; set; }
+	
+	/**
 	 * Specifies the expression used when the caller doesn't supply an
 	 * argument for this parameter.
 	 */
@@ -161,6 +167,7 @@
 	public FormalParameter copy () {
 		if (!ellipsis) {
 			var result = new FormalParameter (name, parameter_type, source_reference);
+			result.params_array = params_array;
 			return result;
 		} else {
 			return new FormalParameter.with_ellipsis ();
@@ -191,6 +198,12 @@
 		if (!ellipsis) {
 			parameter_type.check (analyzer);
 			
+			if (params_array && !(parameter_type is ArrayType)) {
+				error = true;
+				Report.error (source_reference, "parameter array expected");
+				return false;
+			}
+
 			if (default_expression != null) {
 				default_expression.check (analyzer);
 			}

Modified: trunk/vala/valainterfacewriter.vala
==============================================================================
--- trunk/vala/valainterfacewriter.vala	(original)
+++ trunk/vala/valainterfacewriter.vala	Fri Nov 14 20:57:37 2008
@@ -721,6 +721,10 @@
 				write_string ("[CCode (%s)] ".printf (ccode_params.str));
 			}
 
+			if (param.params_array) {
+				write_string ("params ");
+			}
+
 			if (param.direction != ParameterDirection.IN) {
 				if (param.direction == ParameterDirection.REF) {
 					write_string ("ref ");

Modified: trunk/vala/valainvocationexpression.vala
==============================================================================
--- trunk/vala/valainvocationexpression.vala	(original)
+++ trunk/vala/valainvocationexpression.vala	Fri Nov 14 20:57:37 2008
@@ -204,6 +204,18 @@
 				break;
 			}
 
+			if (param.params_array) {
+				var array_type = (ArrayType) param.parameter_type;
+				while (arg_it.next ()) {
+					Expression arg = arg_it.get ();
+
+					/* store expected type for callback parameters */
+					arg.target_type = array_type.element_type;
+					arg.target_type.value_owned = array_type.value_owned;
+				}
+				break;
+			}
+
 			if (arg_it.next ()) {
 				Expression arg = arg_it.get ();
 

Modified: trunk/vala/valaparser.vala
==============================================================================
--- trunk/vala/valaparser.vala	(original)
+++ trunk/vala/valaparser.vala	Fri Nov 14 20:57:37 2008
@@ -207,6 +207,7 @@
 		case TokenType.NULL:
 		case TokenType.OUT:
 		case TokenType.OVERRIDE:
+		case TokenType.PARAMS:
 		case TokenType.PRIVATE:
 		case TokenType.PROTECTED:
 		case TokenType.PUBLIC:
@@ -2699,6 +2700,7 @@
 			// varargs
 			return new FormalParameter.with_ellipsis (get_src (begin));
 		}
+		bool params_array = accept (TokenType.PARAMS);
 		bool construct_param = false;
 		if (accept (TokenType.CONSTRUCT)) {
 			Report.warning (get_last_src (), "deprecated syntax, use assignments in the method body");
@@ -2723,6 +2725,7 @@
 		var param = new FormalParameter (id, type, get_src (begin));
 		set_attributes (param, attrs);
 		param.direction = direction;
+		param.params_array = params_array;
 		param.construct_parameter = construct_param;
 		if (accept (TokenType.ASSIGN)) {
 			param.default_expression = parse_expression ();

Modified: trunk/vala/valascanner.vala
==============================================================================
--- trunk/vala/valascanner.vala	(original)
+++ trunk/vala/valascanner.vala	Fri Nov 14 20:57:37 2008
@@ -192,7 +192,14 @@
 				if (matches (begin, "inline")) return TokenType.INLINE;
 				break;
 			case 'p':
-				if (matches (begin, "public")) return TokenType.PUBLIC;
+				switch (begin[1]) {
+				case 'a':
+					if (matches (begin, "params")) return TokenType.PARAMS;
+					break;
+				case 'u':
+					if (matches (begin, "public")) return TokenType.PUBLIC;
+					break;
+				}
 				break;
 			case 'r':
 				if (matches (begin, "return")) return TokenType.RETURN;

Modified: trunk/vala/valasemanticanalyzer.vala
==============================================================================
--- trunk/vala/valasemanticanalyzer.vala	(original)
+++ trunk/vala/valasemanticanalyzer.vala	Fri Nov 14 20:57:37 2008
@@ -287,6 +287,20 @@
 			/* header file necessary if we need to cast argument */
 			current_source_file.add_type_dependency (param.parameter_type, SourceFileDependencyType.SOURCE);
 
+			if (param.params_array) {
+				while (arg_it.next ()) {
+					var arg = arg_it.get ();
+					if (!check_argument (arg, i, param.direction)) {
+						expr.error = true;
+						return false;
+					}
+
+					i++;
+				}
+
+				break;
+			}
+
 			if (arg_it == null || !arg_it.next ()) {
 				if (param.default_expression == null) {
 					expr.error = true;
@@ -306,83 +320,9 @@
 				}
 			} else {
 				var arg = arg_it.get ();
-				if (arg.error) {
-					// ignore inner error
+				if (!check_argument (arg, i, param.direction)) {
 					expr.error = true;
 					return false;
-				} else if (arg.value_type == null) {
-					// disallow untyped arguments except for type inference of callbacks
-					if (!(param.parameter_type is DelegateType) || !(arg.symbol_reference is Method)) {
-						expr.error = true;
-						Report.error (arg.source_reference, "Invalid type for argument %d".printf (i + 1));
-						return false;
-					}
-				} else if (arg.target_type != null && !arg.value_type.compatible (arg.target_type)
-				           && !(arg is NullLiteral && param.direction == ParameterDirection.OUT)) {
-					expr.error = true;
-					Report.error (arg.source_reference, "Argument %d: Cannot convert from `%s' to `%s'".printf (i + 1, arg.value_type.to_string (), arg.target_type.to_string ()));
-					return false;
-				} else {
-					// 0 => null, 1 => in, 2 => ref, 3 => out
-					int arg_type = 1;
-					if (arg.value_type is NullType) {
-						arg_type = 0;
-					} else if (arg is UnaryExpression) {
-						var unary = (UnaryExpression) arg;
-						if (unary.operator == UnaryOperator.REF) {
-							arg_type = 2;
-						} else if (unary.operator == UnaryOperator.OUT) {
-							arg_type = 3;
-						}
-					}
-
-					if (arg_type == 0) {
-						if (param.direction == ParameterDirection.REF) {
-							expr.error = true;
-							Report.error (arg.source_reference, "Argument %d: Cannot pass null to reference parameter".printf (i + 1));
-							return false;
-						} else if (context.non_null && param.direction != ParameterDirection.OUT && !param.parameter_type.nullable) {
-							Report.warning (arg.source_reference, "Argument %d: Cannot pass null to non-null parameter type".printf (i + 1));
-						}
-					} else if (arg_type == 1) {
-						if (param.direction != ParameterDirection.IN) {
-							expr.error = true;
-							Report.error (arg.source_reference, "Argument %d: Cannot pass value to reference or output parameter".printf (i + 1));
-							return false;
-						}
-					} else if (arg_type == 2) {
-						if (param.direction != ParameterDirection.REF) {
-							expr.error = true;
-							Report.error (arg.source_reference, "Argument %d: Cannot pass ref argument to non-reference parameter".printf (i + 1));
-							return false;
-						}
-
-						// weak variables can only be used with weak ref parameters
-						if (param.parameter_type.is_disposable ()) {
-							if (!(arg.value_type is PointerType) && !arg.value_type.value_owned) {
-								/* variable doesn't own the value */
-								expr.error = true;
-								Report.error (arg.source_reference, "Invalid assignment from owned expression to unowned variable");
-								return false;
-							}
-						}
-					} else if (arg_type == 3) {
-						if (param.direction != ParameterDirection.OUT) {
-							expr.error = true;
-							Report.error (arg.source_reference, "Argument %d: Cannot pass out argument to non-output parameter".printf (i + 1));
-							return false;
-						}
-
-						// weak variables can only be used with weak out parameters
-						if (param.parameter_type.is_disposable ()) {
-							if (!(arg.value_type is PointerType) && !arg.value_type.value_owned) {
-								/* variable doesn't own the value */
-								expr.error = true;
-								Report.error (arg.source_reference, "Invalid assignment from owned expression to unowned variable");
-								return false;
-							}
-						}
-					}
 				}
 
 				prev_arg = arg;
@@ -430,6 +370,79 @@
 		return true;
 	}
 
+	bool check_argument (Expression arg, int i, ParameterDirection direction) {
+		if (arg.error) {
+			// ignore inner error
+			return false;
+		} else if (arg.value_type == null) {
+			// disallow untyped arguments except for type inference of callbacks
+			if (!(arg.target_type is DelegateType) || !(arg.symbol_reference is Method)) {
+				Report.error (arg.source_reference, "Invalid type for argument %d".printf (i + 1));
+				return false;
+			}
+		} else if (arg.target_type != null && !arg.value_type.compatible (arg.target_type)
+		           && !(arg is NullLiteral && direction == ParameterDirection.OUT)) {
+			Report.error (arg.source_reference, "Argument %d: Cannot convert from `%s' to `%s'".printf (i + 1, arg.value_type.to_string (), arg.target_type.to_string ()));
+			return false;
+		} else {
+			// 0 => null, 1 => in, 2 => ref, 3 => out
+			int arg_type = 1;
+			if (arg.value_type is NullType) {
+				arg_type = 0;
+			} else if (arg is UnaryExpression) {
+				var unary = (UnaryExpression) arg;
+				if (unary.operator == UnaryOperator.REF) {
+					arg_type = 2;
+				} else if (unary.operator == UnaryOperator.OUT) {
+					arg_type = 3;
+				}
+			}
+
+			if (arg_type == 0) {
+				if (direction == ParameterDirection.REF) {
+					Report.error (arg.source_reference, "Argument %d: Cannot pass null to reference parameter".printf (i + 1));
+					return false;
+				} else if (context.non_null && direction != ParameterDirection.OUT && !arg.target_type.nullable) {
+					Report.warning (arg.source_reference, "Argument %d: Cannot pass null to non-null parameter type".printf (i + 1));
+				}
+			} else if (arg_type == 1) {
+				if (direction != ParameterDirection.IN) {
+					Report.error (arg.source_reference, "Argument %d: Cannot pass value to reference or output parameter".printf (i + 1));
+					return false;
+				}
+			} else if (arg_type == 2) {
+				if (direction != ParameterDirection.REF) {
+					Report.error (arg.source_reference, "Argument %d: Cannot pass ref argument to non-reference parameter".printf (i + 1));
+					return false;
+				}
+
+				// weak variables can only be used with weak ref parameters
+				if (arg.target_type.is_disposable ()) {
+					if (!(arg.value_type is PointerType) && !arg.value_type.value_owned) {
+						/* variable doesn't own the value */
+						Report.error (arg.source_reference, "Invalid assignment from owned expression to unowned variable");
+						return false;
+					}
+				}
+			} else if (arg_type == 3) {
+				if (direction != ParameterDirection.OUT) {
+					Report.error (arg.source_reference, "Argument %d: Cannot pass out argument to non-output parameter".printf (i + 1));
+					return false;
+				}
+
+				// weak variables can only be used with weak out parameters
+				if (arg.target_type.is_disposable ()) {
+					if (!(arg.value_type is PointerType) && !arg.value_type.value_owned) {
+						/* variable doesn't own the value */
+						Report.error (arg.source_reference, "Invalid assignment from owned expression to unowned variable");
+						return false;
+					}
+				}
+			}
+		}
+		return true;
+	}
+
 	private static DataType? get_instance_base_type (DataType instance_type, DataType base_type, CodeNode node_reference) {
 		// construct a new type reference for the base type with correctly linked type arguments
 		ReferenceType instance_base_type;

Modified: trunk/vala/valatokentype.vala
==============================================================================
--- trunk/vala/valatokentype.vala	(original)
+++ trunk/vala/valatokentype.vala	Fri Nov 14 20:57:37 2008
@@ -107,6 +107,7 @@
 	OPEN_BRACKET,
 	OPEN_PARENS,
 	OVERRIDE,
+	PARAMS,
 	PERCENT,
 	PLUS,
 	PRIVATE,
@@ -225,6 +226,7 @@
 		case OPEN_BRACKET: return "`['";
 		case OPEN_PARENS: return "`('";
 		case OVERRIDE: return "`override'";
+		case PARAMS: return "`params'";
 		case PERCENT: return "`%'";
 		case PLUS: return "`+'";
 		case PRIVATE: return "`private'";



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