allow string comparison with null, use strcmp instead of g_utf8_collate
authorJuerg Billeter <j@bitron.ch>
Wed, 23 Jan 2008 09:32:30 +0000 (09:32 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Wed, 23 Jan 2008 09:32:30 +0000 (09:32 +0000)
2008-01-23  Juerg Billeter  <j@bitron.ch>

* vala/valaenumvalue.vala, vala/valasemanticanalyzer.vala,
  gobject/valaccodegenerator.vala,
  gobject/valaccodegeneratorsourcefile.vala: allow string comparison
  with null, use strcmp instead of g_utf8_collate for string operators,
  fixes bug 506199

* tests/Makefile.am, tests/strings.vala, tests/strings.exp: test
  string operators

svn path=/trunk/; revision=891

ChangeLog
gobject/valaccodegenerator.vala
gobject/valaccodegeneratorsourcefile.vala
tests/Makefile.am
tests/strings.exp [moved from tests/test-021.exp with 100% similarity]
tests/strings.vala [moved from tests/test-021.vala with 50% similarity]
vala/valaenumvalue.vala
vala/valasemanticanalyzer.vala

index 63e7ddf..129a4ed 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2008-01-23  Jürg Billeter  <j@bitron.ch>
+
+       * vala/valaenumvalue.vala, vala/valasemanticanalyzer.vala,
+         gobject/valaccodegenerator.vala,
+         gobject/valaccodegeneratorsourcefile.vala: allow string comparison
+         with null, use strcmp instead of g_utf8_collate for string operators,
+         fixes bug 506199
+
+       * tests/Makefile.am, tests/strings.vala, tests/strings.exp: test
+         string operators
+
 2008-01-22  Jürg Billeter  <j@bitron.ch>
 
        * vapigen/valagidlparser.vala: support metadata attributes for signal
index 2fb255d..24941da 100644 (file)
@@ -117,6 +117,7 @@ public class Vala.CCodeGenerator : CodeGenerator {
        private bool requires_free_checked;
        private bool requires_array_free;
        private bool requires_array_move;
+       private bool requires_strcmp0;
 
        public CCodeGenerator () {
        }
@@ -2837,8 +2838,7 @@ public class Vala.CCodeGenerator : CodeGenerator {
                
                if (expr.operator == BinaryOperator.EQUALITY ||
                    expr.operator == BinaryOperator.INEQUALITY) {
-                       if (expr.left.static_type != null && expr.right.static_type != null &&
-                           expr.left.static_type.data_type is Class && ((Class) expr.left.static_type.data_type).is_subtype_of (gobject_type) &&
+                       if (expr.left.static_type.data_type is Class && ((Class) expr.left.static_type.data_type).is_subtype_of (gobject_type) &&
                            expr.right.static_type.data_type is Class && ((Class) expr.right.static_type.data_type).is_subtype_of (gobject_type)) {
                                var left_cl = (Class) expr.left.static_type.data_type;
                                var right_cl = (Class) expr.right.static_type.data_type;
@@ -2852,7 +2852,25 @@ public class Vala.CCodeGenerator : CodeGenerator {
                                }
                        }
                }
-               
+
+               if (!(expr.left.static_type is NullType)
+                   && expr.left.static_type.compatible (string_type)
+                   && !(expr.right.static_type is NullType)
+                   && expr.right.static_type.compatible (string_type)
+                   && (expr.operator == BinaryOperator.EQUALITY
+                       || expr.operator == BinaryOperator.INEQUALITY
+                       || expr.operator == BinaryOperator.LESS_THAN
+                       || expr.operator == BinaryOperator.GREATER_THAN
+                       || expr.operator == BinaryOperator.LESS_THAN_OR_EQUAL
+                       || expr.operator == BinaryOperator.GREATER_THAN_OR_EQUAL)) {
+                       requires_strcmp0 = true;
+                       var ccall = new CCodeFunctionCall (new CCodeIdentifier ("_vala_strcmp0"));
+                       ccall.add_argument (cleft);
+                       ccall.add_argument (cright);
+                       cleft = ccall;
+                       cright = new CCodeConstant ("0");
+               }
+
                expr.ccodenode = new CCodeBinaryExpression (op, cleft, cright);
                
                visit_expression (expr);
index e55152d..6d53fec 100644 (file)
@@ -1,6 +1,6 @@
 /* valaccodegeneratorsourcefile.vala
  *
- * Copyright (C) 2006-2007  Jürg Billeter, Raffaele Sandrini
+ * Copyright (C) 2006-2008  Jürg Billeter, Raffaele Sandrini
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -136,6 +136,42 @@ public class Vala.CCodeGenerator {
                source_type_member_definition.append (fun);
        }
 
+       private void append_vala_strcmp0 () {
+               var fun = new CCodeFunction ("_vala_strcmp0", "int");
+               fun.modifiers = CCodeModifiers.STATIC;
+               fun.add_parameter (new CCodeFormalParameter ("str1", "const char *"));
+               fun.add_parameter (new CCodeFormalParameter ("str2", "const char *"));
+               source_type_member_declaration.append (fun.copy ());
+
+               // (str1 != str2)
+               var cineq = new CCodeParenthesizedExpression (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("str1"), new CCodeIdentifier ("str2")));
+
+               fun.block = new CCodeBlock ();
+
+               var cblock = new CCodeBlock ();
+               // if (str1 == NULL)
+               var cif = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier ("str1"), new CCodeConstant ("NULL")), cblock);
+               // return -(str1 != str2);
+               cblock.add_statement (new CCodeReturnStatement (new CCodeUnaryExpression (CCodeUnaryOperator.MINUS, cineq)));
+               fun.block.add_statement (cif);
+
+               cblock = new CCodeBlock ();
+               // if (str2 == NULL)
+               cif = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier ("str2"), new CCodeConstant ("NULL")), cblock);
+               // return (str1 != str2);
+               cblock.add_statement (new CCodeReturnStatement (cineq));
+               fun.block.add_statement (cif);
+
+               // strcmp (str1, str2)
+               var ccall = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
+               ccall.add_argument (new CCodeIdentifier ("str1"));
+               ccall.add_argument (new CCodeIdentifier ("str2"));
+               // return strcmp (str1, str2);
+               fun.block.add_statement (new CCodeReturnStatement (ccall));
+
+               source_type_member_definition.append (fun);
+       }
+
        public override void visit_source_file (SourceFile! source_file) {
                header_begin = new CCodeFragment ();
                header_type_declaration = new CCodeFragment ();
@@ -156,6 +192,7 @@ public class Vala.CCodeGenerator {
                requires_free_checked = false;
                requires_array_free = false;
                requires_array_move = false;
+               requires_strcmp0 = false;
                
                header_begin.append (new CCodeIncludeDirective ("glib.h"));
                header_begin.append (new CCodeIncludeDirective ("glib-object.h"));
@@ -231,6 +268,9 @@ public class Vala.CCodeGenerator {
                if (requires_array_move) {
                        append_vala_array_move ();
                }
+               if (requires_strcmp0) {
+                       append_vala_strcmp0 ();
+               }
                
                if (string_h_needed) {
                        source_include_directives.append (new CCodeIncludeDirective ("string.h"));
index 3828f96..ff446e8 100644 (file)
@@ -16,6 +16,7 @@ TESTS_ENVIRONMENT = $(srcdir)/testrunner.sh
 
 TESTS = \
        hello.vala \
+       strings.vala \
        expressions-relational.vala \
        expressions-conditional.vala \
        expressions-assignments.vala \
@@ -36,7 +37,6 @@ TESTS = \
        exceptions.vala \
        \
        test-015.vala \
-       test-021.vala \
        test-023.vala \
        test-025.vala \
        test-026.vala \
@@ -54,6 +54,7 @@ EXTRA_DIST = \
        $(TESTS) \
        \
        hello.exp \
+       strings.exp \
        expressions-relational.exp \
        expressions-conditional.exp \
        expressions-assignments.exp \
@@ -74,7 +75,6 @@ EXTRA_DIST = \
        exceptions.exp \
        \
        test-015.exp \
-       test-021.exp \
        test-023.exp \
        test-025.exp \
        test-026.exp \
similarity index 100%
rename from tests/test-021.exp
rename to tests/strings.exp
similarity index 50%
rename from tests/test-021.vala
rename to tests/strings.vala
index 8a92082..0ec1570 100644 (file)
@@ -1,6 +1,20 @@
 using GLib;
 
 class Maman.Foo : Object {
+       static void test_string_operators () {
+               // string == operator compares content not reference
+               string s1 = "string";
+               string s2 = "string";
+               bool eq = (s1 == s2);
+               assert (eq);
+
+               // allow null string comparison
+               s1 = null;
+               s2 = null;
+               eq = (s1 == s2);
+               assert (eq);
+       }
+
        static int main (string[] args) {
                stdout.printf ("String Test: 1");
 
@@ -15,6 +29,8 @@ class Maman.Foo : Object {
 
                stdout.printf (" 8\n");
 
+               test_string_operators ();
+
                return 0;
        }
 }
index b6ba076..fde0561 100644 (file)
@@ -1,6 +1,6 @@
 /* valaenumvalue.vala
  *
- * Copyright (C) 2006  Jürg Billeter
+ * Copyright (C) 2006-2008  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -55,7 +55,13 @@ public class Vala.EnumValue : Symbol {
        public override void accept (CodeVisitor! visitor) {
                visitor.visit_enum_value (this);
        }
-       
+
+       public override void accept_children (CodeVisitor! visitor) {
+               if (value != null) {
+                       value.accept (visitor);
+               }
+       }
+
        /**
         * Returns the name of this enum value as it is used in C code.
         *
index 97bbd5b..4288c8c 100644 (file)
@@ -290,6 +290,14 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                current_symbol = current_symbol.parent_symbol;
        }
 
+       public override void visit_enum (Enum! en) {
+               en.accept_children (this);
+       }
+
+       public override void visit_enum_value (EnumValue! ev) {
+               ev.accept_children (this);
+       }
+
        public override void visit_delegate (Delegate! d) {
                d.accept_children (this);
        }
@@ -2375,17 +2383,9 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                           || expr.operator == BinaryOperator.GREATER_THAN
                           || expr.operator == BinaryOperator.LESS_THAN_OR_EQUAL
                           || expr.operator == BinaryOperator.GREATER_THAN_OR_EQUAL) {
-                       if (expr.left.static_type.data_type == string_type.data_type
-                           && expr.right.static_type.data_type == string_type.data_type) {
-                               /* string comparison: convert to a.collate (b) OP 0 */
-
-                               var cmp_call = new InvocationExpression (new MemberAccess (expr.left, "collate"));
-                               cmp_call.add_argument (expr.right);
-                               expr.left = cmp_call;
-
-                               expr.right = new LiteralExpression (new IntegerLiteral ("0"));
-
-                               expr.left.accept (this);
+                       if (expr.left.static_type.compatible (string_type)
+                           && expr.right.static_type.compatible (string_type)) {
+                               // string comparison
                        } else {
                                var resulting_type = get_arithmetic_result_type (expr.left.static_type, expr.right.static_type);
 
@@ -2408,17 +2408,9 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                                return;
                        }
 
-                       if (expr.left.static_type.data_type == string_type.data_type
-                           && expr.right.static_type.data_type == string_type.data_type) {
-                               /* string comparison: convert to a.collate (b) OP 0 */
-
-                               var cmp_call = new InvocationExpression (new MemberAccess (expr.left, "collate"));
-                               cmp_call.add_argument (expr.right);
-                               expr.left = cmp_call;
-
-                               expr.right = new LiteralExpression (new IntegerLiteral ("0"));
-
-                               expr.left.accept (this);
+                       if (expr.left.static_type.compatible (string_type)
+                           && expr.right.static_type.compatible (string_type)) {
+                               // string comparison
                        }
 
                        expr.static_type = bool_type;