[vala] Support `in' operator for arrays
- From: Jürg Billeter <juergbi src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [vala] Support `in' operator for arrays
- Date: Thu, 11 Feb 2010 20:41:05 +0000 (UTC)
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]