[vala] Support `in' operator for arrays



commit d962523d21b0a7de631d128d224e5fa8588a4c14
Author: Robin Sonefors <ozamosi flukkost nu>
Date:   Wed Jan 20 05:41:32 2010 +0100

    Support `in' operator for arrays
    
    This is already supported for some non-array types, so this patch
    merely extends it.
    
    Fixes bug 602511.

 codegen/valaccodebasemodule.vala |   75 +++++++++++++++++++++++++++++++++++++-
 tests/basic-types/arrays.vala    |    4 ++
 vala/valabinaryexpression.vala   |    4 ++
 3 files changed, 82 insertions(+), 1 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 101149d..57c990d 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -4425,7 +4425,20 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		} else if (expr.operator == BinaryOperator.OR) {
 			op = CCodeBinaryOperator.OR;
 		} else if (expr.operator == BinaryOperator.IN) {
-			expr.ccodenode = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeBinaryExpression (CCodeBinaryOperator.BITWISE_AND, cright, cleft), cleft);
+			if (expr.right.value_type is ArrayType) {
+				var array_type = (ArrayType) expr.right.value_type;
+				var node = new CCodeFunctionCall (new CCodeIdentifier (generate_array_contains_wrapper (array_type)));
+				node.add_argument (cright);
+				node.add_argument (get_array_length_cexpression (expr.right));
+				if (array_type.element_type is StructValueType) {
+					node.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cleft));
+				} else {
+					node.add_argument (cleft);
+				}
+				expr.ccodenode = node;
+			} else {
+				expr.ccodenode = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeBinaryExpression (CCodeBinaryOperator.BITWISE_AND, cright, cleft), cleft);
+			}
 			return;
 		} else {
 			assert_not_reached ();
@@ -4564,6 +4577,66 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		}
 	}
 
+	string generate_array_contains_wrapper (ArrayType array_type) {
+		string array_contains_func = "_vala_%s_array_contains".printf (array_type.element_type.get_lower_case_cname ());
+
+		if (!add_wrapper (array_contains_func)) {
+			return array_contains_func;
+		}
+
+		var function = new CCodeFunction (array_contains_func, "gboolean");
+		function.modifiers = CCodeModifiers.STATIC;
+
+		function.add_parameter (new CCodeFormalParameter ("stack", array_type.get_cname ()));
+		function.add_parameter (new CCodeFormalParameter ("stack_length", "int"));
+		if (array_type.element_type is StructValueType) {
+			function.add_parameter (new CCodeFormalParameter ("needle", array_type.element_type.get_cname () + "*"));
+		} else {
+			function.add_parameter (new CCodeFormalParameter ("needle", array_type.element_type.get_cname ()));
+		}
+		var block = new CCodeBlock ();
+
+		var idx_decl = new CCodeDeclaration ("int");
+		idx_decl.add_declarator (new CCodeVariableDeclarator ("i"));
+		block.add_statement (idx_decl);
+
+		var celement = new CCodeElementAccess (new CCodeIdentifier ("stack"), new CCodeIdentifier ("i"));
+		var cneedle = new CCodeIdentifier ("needle");
+		CCodeBinaryExpression cif_condition;
+		if (array_type.element_type.compatible (string_type)) {
+			requires_strcmp0 = true;
+			var ccall = new CCodeFunctionCall (new CCodeIdentifier ("_vala_strcmp0"));
+			ccall.add_argument (celement);
+			ccall.add_argument (cneedle);
+			cif_condition = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccall, new CCodeConstant ("0"));
+		} else if (array_type.element_type is StructValueType) {
+			var equalfunc = generate_struct_equal_function ((Struct) array_type.element_type.data_type as Struct);
+			var ccall = new CCodeFunctionCall (new CCodeIdentifier (equalfunc));
+			ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, celement));
+			ccall.add_argument (cneedle);
+			cif_condition = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccall, new CCodeConstant ("TRUE"));
+		} else {
+			cif_condition = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, cneedle, celement);
+		}
+		var cif_found = new CCodeBlock ();
+		cif_found.add_statement (new CCodeReturnStatement (new CCodeConstant ("TRUE")));
+		var cloop_body = new CCodeBlock ();
+		cloop_body.add_statement (new CCodeIfStatement (cif_condition, cif_found));
+
+		var cloop_condition = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeIdentifier ("stack_length"));
+		var cloop = new CCodeForStatement (cloop_condition, cloop_body);
+		cloop.add_initializer (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")));
+		cloop.add_iterator (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("i")));
+
+		block.add_statement (cloop);
+		block.add_statement (new CCodeReturnStatement (new CCodeConstant ("FALSE")));
+		source_declarations.add_type_member_declaration (function.copy ());
+		function.block = block;
+		source_type_member_definition.append (function);
+
+		return array_contains_func;
+	}
+
 	public override void visit_type_check (TypeCheck expr) {
 		generate_type_declaration (expr.type_reference, source_declarations);
 
diff --git a/tests/basic-types/arrays.vala b/tests/basic-types/arrays.vala
index ea11f54..ff32f2d 100644
--- a/tests/basic-types/arrays.vala
+++ b/tests/basic-types/arrays.vala
@@ -31,6 +31,10 @@ void test_integer_array () {
 	assert (c.length == 2);
 	assert (c[0] == 23);
 	assert (c[1] == 11);
+
+	// in expressions
+	assert (23 in a);
+	assert (!(-1 in a));
 }
 
 void test_string_array () {
diff --git a/vala/valabinaryexpression.vala b/vala/valabinaryexpression.vala
index 01cae0b..67ad50d 100644
--- a/vala/valabinaryexpression.vala
+++ b/vala/valabinaryexpression.vala
@@ -400,6 +400,10 @@ public class Vala.BinaryExpression : Expression {
 			if (left.value_type.compatible (analyzer.int_type)
 			    && right.value_type.compatible (analyzer.int_type)) {
 				// integers or enums
+			} else if (right.value_type is ArrayType) {
+				if (!left.value_type.compatible (((ArrayType) right.value_type).element_type)) {
+					Report.error (source_reference, "Cannot look for `%s' in `%s'".printf (left.value_type.to_string (), right.value_type.to_string ()));
+				}
 			} else {
 				// otherwise require a bool contains () method
 				var contains_method = right.value_type.get_member ("contains") as Method;



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