+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
private bool requires_free_checked;
private bool requires_array_free;
private bool requires_array_move;
+ private bool requires_strcmp0;
public CCodeGenerator () {
}
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;
}
}
}
-
+
+ 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);
/* 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
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 ();
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"));
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"));
TESTS = \
hello.vala \
+ strings.vala \
expressions-relational.vala \
expressions-conditional.vala \
expressions-assignments.vala \
exceptions.vala \
\
test-015.vala \
- test-021.vala \
test-023.vala \
test-025.vala \
test-026.vala \
$(TESTS) \
\
hello.exp \
+ strings.exp \
expressions-relational.exp \
expressions-conditional.exp \
expressions-assignments.exp \
exceptions.exp \
\
test-015.exp \
- test-021.exp \
test-023.exp \
test-025.exp \
test-026.exp \
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");
stdout.printf (" 8\n");
+ test_string_operators ();
+
return 0;
}
}
/* 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
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.
*
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);
}
|| 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);
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;