]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Support equality checking on nullable boolean and numeric types
authorJürg Billeter <j@bitron.ch>
Fri, 29 Jan 2010 16:23:29 +0000 (17:23 +0100)
committerJürg Billeter <j@bitron.ch>
Fri, 29 Jan 2010 16:32:32 +0000 (17:32 +0100)
Fixes bug 608434.

codegen/valaccodebasemodule.vala
vala/valabinaryexpression.vala

index a3746798b8d544342bfffbe0d7ad12ab188ec228..af186bda6cfa6ea3f627ead72308cdcfcfe04cee 100644 (file)
@@ -2471,6 +2471,62 @@ internal class Vala.CCodeBaseModule : CCodeModule {
                return equal_func;
        }
 
+       private string generate_numeric_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);
+               }
+               // return (*s1 == *s2);
+               {
+                       var cexp = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("s1")), new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("s2")));
+                       cblock.add_statement (new CCodeReturnStatement (cexp));
+               }
+
+               // 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 ());
 
@@ -4335,8 +4391,8 @@ internal class Vala.CCodeBaseModule : CCodeModule {
                
                if (expr.operator == BinaryOperator.EQUALITY ||
                    expr.operator == BinaryOperator.INEQUALITY) {
-                       var left_type = expr.left.value_type;
-                       var right_type = expr.right.value_type;
+                       var left_type = expr.left.target_type;
+                       var right_type = expr.right.target_type;
                        make_comparable_cexpression (ref left_type, ref cleft, ref right_type, ref cright);
 
                        if (left_type is StructValueType && right_type is StructValueType) {
@@ -4346,6 +4402,14 @@ internal class Vala.CCodeBaseModule : CCodeModule {
                                ccall.add_argument (cright);
                                cleft = ccall;
                                cright = new CCodeConstant ("TRUE");
+                       } else if ((left_type is IntegerType || left_type is FloatingType || left_type is BooleanType) && left_type.nullable &&
+                                  (right_type is IntegerType || right_type is FloatingType || right_type is BooleanType) && right_type.nullable) {
+                               var equalfunc = generate_numeric_equal_function ((Struct) left_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");
                        }
                }
 
index 27477239e5f91885ad163c5a3ea2fe717d544b07..53dda1c82ee248a2e58bc871a00203e3b67a98de 100644 (file)
@@ -323,6 +323,20 @@ public class Vala.BinaryExpression : Expression {
                                return false;
                        }
 
+                       left.target_type = left.value_type.copy ();
+                       left.target_type.value_owned = false;
+                       right.target_type = right.value_type.copy ();
+                       right.target_type.value_owned = false;
+
+                       if (left.value_type.nullable != right.value_type.nullable) {
+                               // if only one operand is nullable, make sure the other operand is promoted to nullable as well
+                               if (!left.value_type.nullable) {
+                                       left.target_type.nullable = true;
+                               } else if (!right.value_type.nullable) {
+                                       right.target_type.nullable = true;
+                               }
+                       }
+
                        if (left.value_type.compatible (analyzer.string_type)
                            && right.value_type.compatible (analyzer.string_type)) {
                                // string comparison