[vala] Support struct comparison
- From: Jürg Billeter <juergbi src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [vala] Support struct comparison
- Date: Thu, 7 Jan 2010 20:05:07 +0000 (UTC)
commit a04d18379da5c4cd4f4e860f68cad6647e20b4a0
Author: Jürg Billeter <j bitron ch>
Date: Fri Oct 9 12:29:00 2009 +0200
Support struct comparison
Based on patch by Marc-André Lureau, fixes bug 530605.
codegen/valaccodebasemodule.vala | 161 +++++++++++++++++++++++++++++++------
tests/Makefile.am | 1 +
tests/structs/bug530605.vala | 23 ++++++
3 files changed, 159 insertions(+), 26 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 2266fb6..fe56e1d 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -2322,6 +2322,132 @@ internal class Vala.CCodeBaseModule : CCodeModule {
}
}
+ void make_comparable_cexpression (DataType left_type, ref CCodeExpression cleft, DataType right_type, ref CCodeExpression cright) {
+ var left_type_as_struct = left_type.data_type as Struct;
+ var right_type_as_struct = right_type.data_type as Struct;
+
+ if (left_type.data_type is Class && !((Class) left_type.data_type).is_compact &&
+ right_type.data_type is Class && !((Class) right_type.data_type).is_compact) {
+ var left_cl = (Class) left_type.data_type;
+ var right_cl = (Class) right_type.data_type;
+
+ if (left_cl != right_cl) {
+ if (left_cl.is_subtype_of (right_cl)) {
+ cleft = generate_instance_cast (cleft, right_cl);
+ } else if (right_cl.is_subtype_of (left_cl)) {
+ cright = generate_instance_cast (cright, left_cl);
+ }
+ }
+ } else if (left_type_as_struct != null && right_type_as_struct != null) {
+ if (left_type is StructValueType) {
+ // real structs (uses compare/equal function)
+ if (!left_type.nullable) {
+ cleft = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cleft);
+ }
+ if (!right_type.nullable) {
+ cright = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cright);
+ }
+ } else {
+ // integer or floating or boolean type
+ if (left_type.nullable && right_type.nullable) {
+ // FIXME also compare contents, not just address
+ } else if (left_type.nullable) {
+ // FIXME check left value is not null
+ cleft = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, cleft);
+ } else if (right_type.nullable) {
+ // FIXME check right value is not null
+ cright = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, cright);
+ }
+ }
+ }
+ }
+
+ private string generate_struct_equal_function (Struct st) {
+ string equal_func = "_%sequal".printf (st.get_lower_case_cprefix ());
+
+ if (!add_wrapper (equal_func)) {
+ // wrapper already defined
+ return equal_func;
+ }
+ // declaration
+
+ var function = new CCodeFunction (equal_func, "gboolean");
+ function.modifiers = CCodeModifiers.STATIC;
+
+ function.add_parameter (new CCodeFormalParameter ("s1", "const " + st.get_cname () + "*"));
+ function.add_parameter (new CCodeFormalParameter ("s2", "const " + st.get_cname () + "*"));
+
+ // definition
+ var cblock = new CCodeBlock ();
+
+ // if (s1 == s2) return TRUE;
+ {
+ var block = new CCodeBlock ();
+ block.add_statement (new CCodeReturnStatement (new CCodeConstant ("TRUE")));
+
+ var cexp = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier ("s1"), new CCodeIdentifier ("s2"));
+ var cif = new CCodeIfStatement (cexp, block);
+ cblock.add_statement (cif);
+ }
+ // if (s1 == NULL || s2 == NULL) return FALSE;
+ {
+ var block = new CCodeBlock ();
+ block.add_statement (new CCodeReturnStatement (new CCodeConstant ("FALSE")));
+
+ var cexp = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier ("s1"), new CCodeConstant ("NULL"));
+ var cif = new CCodeIfStatement (cexp, block);
+ cblock.add_statement (cif);
+
+ cexp = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier ("s2"), new CCodeConstant ("NULL"));
+ cif = new CCodeIfStatement (cexp, block);
+ cblock.add_statement (cif);
+ }
+
+ foreach (Field f in st.get_fields ()) {
+ if (f.binding != MemberBinding.INSTANCE) {
+ // we only compare instance fields
+ continue;
+ }
+
+ CCodeExpression cexp; // if (cexp) return FALSE;
+ var s1 = (CCodeExpression) new CCodeMemberAccess.pointer (new CCodeIdentifier ("s1"), f.name); // s1->f
+ var s2 = (CCodeExpression) new CCodeMemberAccess.pointer (new CCodeIdentifier ("s2"), f.name); // s2->f
+ make_comparable_cexpression (f.field_type, ref s1, f.field_type, ref s2);
+
+ if (!(f.field_type is NullType) && f.field_type.compatible (string_type)) {
+ requires_strcmp0 = true;
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier ("_vala_strcmp0"));
+ ccall.add_argument (s1);
+ ccall.add_argument (s2);
+ cexp = ccall;
+ } else if (f.field_type is StructValueType) {
+ var equalfunc = generate_struct_equal_function (f.field_type.data_type as Struct);
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier (equalfunc));
+ ccall.add_argument (s1);
+ ccall.add_argument (s2);
+ cexp = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, ccall);
+ } else {
+ cexp = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, s1, s2);
+ }
+
+ var block = new CCodeBlock ();
+ block.add_statement (new CCodeReturnStatement (new CCodeConstant ("FALSE")));
+ var cif = new CCodeIfStatement (cexp, block);
+ cblock.add_statement (cif);
+ }
+
+ cblock.add_statement (new CCodeReturnStatement (new CCodeConstant ("TRUE")));
+
+ // append to file
+
+ source_declarations.add_type_member_declaration (function.copy ());
+
+ function.block = cblock;
+ source_type_member_definition.append (function);
+
+ return equal_func;
+ }
+
private string generate_struct_dup_wrapper (ValueType value_type) {
string dup_func = "_%sdup".printf (value_type.type_symbol.get_lower_case_cprefix ());
@@ -4149,32 +4275,15 @@ internal class Vala.CCodeBaseModule : CCodeModule {
if (expr.operator == BinaryOperator.EQUALITY ||
expr.operator == BinaryOperator.INEQUALITY) {
- var left_type_as_struct = expr.left.value_type.data_type as Struct;
- var right_type_as_struct = expr.right.value_type.data_type as Struct;
+ make_comparable_cexpression (expr.left.value_type, ref cleft, expr.right.value_type, ref cright);
- if (expr.left.value_type.data_type is Class && !((Class) expr.left.value_type.data_type).is_compact &&
- expr.right.value_type.data_type is Class && !((Class) expr.right.value_type.data_type).is_compact) {
- var left_cl = (Class) expr.left.value_type.data_type;
- var right_cl = (Class) expr.right.value_type.data_type;
-
- if (left_cl != right_cl) {
- if (left_cl.is_subtype_of (right_cl)) {
- cleft = generate_instance_cast (cleft, right_cl);
- } else if (right_cl.is_subtype_of (left_cl)) {
- cright = generate_instance_cast (cright, left_cl);
- }
- }
- } else if (left_type_as_struct != null && right_type_as_struct != null) {
- // FIXME generate and use compare/equal function for real structs
- if (expr.left.value_type.nullable && expr.right.value_type.nullable) {
- // FIXME also compare contents, not just address
- } else if (expr.left.value_type.nullable) {
- // FIXME check left value is not null
- cleft = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, cleft);
- } else if (expr.right.value_type.nullable) {
- // FIXME check right value is not null
- cright = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, cright);
- }
+ if (expr.left.value_type is StructValueType && expr.right.value_type is StructValueType) {
+ var equalfunc = generate_struct_equal_function ((Struct) expr.left.value_type.data_type as Struct);
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier (equalfunc));
+ ccall.add_argument (cleft);
+ ccall.add_argument (cright);
+ cleft = ccall;
+ cright = new CCodeConstant ("TRUE");
}
}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 09d0640..9698cfa 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -40,6 +40,7 @@ TESTS = \
enums/enums.vala \
structs/structs.vala \
structs/gvalue.vala \
+ structs/bug530605.vala \
structs/bug583603.vala \
structs/bug595587.vala \
delegates/delegates.vala \
diff --git a/tests/structs/bug530605.vala b/tests/structs/bug530605.vala
new file mode 100644
index 0000000..030564f
--- /dev/null
+++ b/tests/structs/bug530605.vala
@@ -0,0 +1,23 @@
+struct Foo {
+ int bar;
+ string baz;
+
+ public Foo (int bar, string baz) {
+ this.bar = bar;
+ this.baz = baz;
+ }
+}
+
+void main () {
+ Foo a = Foo (42, "hello");
+ Foo b = Foo (42, "hello");
+ Foo? c = Foo (42, "hello");
+ Foo d = Foo (42, "world");
+ Foo e = Foo (23, "hello");
+
+ assert (a == b);
+ assert (a == c);
+ assert (a != d);
+ assert (a != e);
+}
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]