}
}
- bool is_string_comparison = !(expr.left.value_type is NullType) && expr.left.value_type.compatible (string_type)
- && !(expr.right.value_type is NullType) && expr.right.value_type.compatible (string_type);
+ bool is_string_comparison = false;
+ if (!(expr.right.value_type is NullType) && expr.right.value_type.compatible (string_type)) {
+ if (!(expr.left.value_type is NullType) && expr.left.value_type.compatible (string_type)) {
+ is_string_comparison = true;
+ } else if (expr.is_chained) {
+ unowned BinaryExpression lbe = (BinaryExpression) expr.left;
+ if (!(lbe.right.value_type is NullType) && lbe.right.value_type.compatible (string_type)) {
+ is_string_comparison = true;
+ }
+ }
+ }
bool has_string_literal = (expr.left is StringLiteral || expr.right is StringLiteral);
if (is_string_comparison || (has_string_literal && expr.operator != BinaryOperator.PLUS)) {
parser/attribute-missing-literal.test \
parser/attribute-wrong-number.test \
parser/block-delimiter-missing.test \
+ parser/chained-equality-type-invalid.test \
+ parser/chained-equality.vala \
parser/constant-owned.test \
parser/constant-local-owned.test \
parser/constructor-class-exists.test \
--- /dev/null
+Invalid Code
+
+void main () {
+ var foo = "world";
+ var bar = 0;
+ if (foo == "world" != 0) {
+ }
+}
--- /dev/null
+/* parser_chained_equality.c generated by valac, the Vala compiler
+ * generated from parser_chained_equality.vala, do not modify */
+
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define _g_free0(var) (var = (g_free (var), NULL))
+#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
+#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
+#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+
+static void _vala_main (void);
+
+static void
+_vala_main (void)
+{
+ {
+ gint foo = 0;
+ gint bar = 0;
+ gint _tmp0_;
+ foo = 123;
+ bar = 123;
+ _tmp0_ = bar;
+ _vala_assert ((foo == _tmp0_) && (_tmp0_ == 123), "foo == bar == 123");
+ }
+ {
+ gint foo = 0;
+ gint bar = 0;
+ gint _tmp1_;
+ foo = 111;
+ bar = 222;
+ _tmp1_ = bar;
+ _vala_assert ((foo != _tmp1_) && (_tmp1_ == 222), "foo != bar == 222");
+ }
+ {
+ gint foo = 0;
+ gint bar = 0;
+ gint _tmp2_;
+ foo = 111;
+ bar = 111;
+ _tmp2_ = bar;
+ _vala_assert ((foo == _tmp2_) && (_tmp2_ != 222), "foo == bar != 222");
+ }
+ {
+ gint foo = 0;
+ gint bar = 0;
+ gint _tmp3_;
+ gint _tmp4_;
+ foo = 111;
+ bar = 111;
+ _tmp3_ = foo;
+ _tmp4_ = bar;
+ _vala_assert (((0 < _tmp3_) && (_tmp3_ == _tmp4_)) && (_tmp4_ < 222), "0 < foo == bar < 222");
+ }
+ {
+ gint a = 0;
+ gint b = 0;
+ gint c = 0;
+ gint _tmp5_;
+ gint _tmp6_;
+ a = 111;
+ b = 111;
+ c = 111;
+ _tmp5_ = b;
+ _tmp6_ = c;
+ _vala_assert (((a == _tmp5_) && (_tmp5_ == _tmp6_)) && (_tmp6_ == 111), "a == b == c == 111");
+ }
+ {
+ gint a = 0;
+ gint b = 0;
+ gint c = 0;
+ gint _tmp7_;
+ gint _tmp8_;
+ a = 111;
+ b = 222;
+ c = 333;
+ _tmp7_ = b;
+ _tmp8_ = c;
+ _vala_assert (((a != _tmp7_) && (_tmp7_ != _tmp8_)) && (_tmp8_ != 123), "a != b != c != 123");
+ }
+ {
+ gchar* foo = NULL;
+ gchar* _tmp9_;
+ gchar* bar = NULL;
+ gchar* _tmp10_;
+ gchar* _tmp11_;
+ _tmp9_ = g_strdup ("world");
+ foo = _tmp9_;
+ _tmp10_ = g_strdup ("hello");
+ bar = _tmp10_;
+ _tmp11_ = bar;
+ _vala_assert ((g_strcmp0 (foo, _tmp11_) > 0) && (g_strcmp0 (_tmp11_, "hello") == 0), "foo > bar == \"hello\"");
+ _g_free0 (bar);
+ _g_free0 (foo);
+ }
+ {
+ gchar* a = NULL;
+ gchar* _tmp12_;
+ gchar* b = NULL;
+ gchar* _tmp13_;
+ gchar* c = NULL;
+ gchar* _tmp14_;
+ gchar* _tmp15_;
+ gchar* _tmp16_;
+ gchar* _tmp17_;
+ gchar* _tmp18_;
+ _tmp12_ = g_strdup ("hello");
+ a = _tmp12_;
+ _tmp13_ = g_strdup ("hello");
+ b = _tmp13_;
+ _tmp14_ = g_strdup ("hello");
+ c = _tmp14_;
+ _tmp15_ = a;
+ _tmp16_ = b;
+ _tmp17_ = c;
+ _tmp18_ = "hello";
+ _vala_assert (((((g_strcmp0 ("hello", _tmp15_) == 0) && (g_strcmp0 (_tmp15_, _tmp16_) <= 0)) && (g_strcmp0 (_tmp16_, _tmp17_) == 0)) && (g_strcmp0 (_tmp17_, _tmp18_) == 0)) && (g_strcmp0 (_tmp18_, "hello") <= 0), "\"hello\" == a <= b == c == \"hello\" <= \"hello\"");
+ _g_free0 (c);
+ _g_free0 (b);
+ _g_free0 (a);
+ }
+ {
+ gchar* foo = NULL;
+ gchar* _tmp19_;
+ gchar* bar = NULL;
+ gchar* _tmp20_;
+ gchar* _tmp21_;
+ _tmp19_ = g_strdup ("h");
+ foo = _tmp19_;
+ _tmp20_ = g_strdup ("h");
+ bar = _tmp20_;
+ _tmp21_ = bar;
+ _vala_assert ((g_strcmp0 (foo, _tmp21_) == 0) && (g_strcmp0 (_tmp21_, "hello") < 0), "foo == bar < \"hello\"");
+ _g_free0 (bar);
+ _g_free0 (foo);
+ }
+ {
+ gchar* foo = NULL;
+ gchar* _tmp22_;
+ gchar* bar = NULL;
+ gchar* _tmp23_;
+ gchar* _tmp24_;
+ _tmp22_ = g_strdup ("hello");
+ foo = _tmp22_;
+ _tmp23_ = g_strdup ("world");
+ bar = _tmp23_;
+ _tmp24_ = bar;
+ _vala_assert ((g_strcmp0 (foo, _tmp24_) != 0) && (g_strcmp0 (_tmp24_, "world") == 0), "foo != bar == \"world\"");
+ _g_free0 (bar);
+ _g_free0 (foo);
+ }
+ {
+ gchar* foo = NULL;
+ gchar* _tmp25_;
+ gchar* bar = NULL;
+ gchar* _tmp26_;
+ gchar* _tmp27_;
+ _tmp25_ = g_strdup ("world");
+ foo = _tmp25_;
+ _tmp26_ = g_strdup ("world");
+ bar = _tmp26_;
+ _tmp27_ = bar;
+ _vala_assert ((g_strcmp0 (foo, _tmp27_) == 0) && (g_strcmp0 (_tmp27_, "hello") != 0), "foo == bar != \"hello\"");
+ _g_free0 (bar);
+ _g_free0 (foo);
+ }
+ {
+ gchar* foo = NULL;
+ gchar* _tmp28_;
+ gchar* bar = NULL;
+ gchar* _tmp29_;
+ gchar* _tmp30_;
+ gint _tmp31_;
+ _tmp28_ = g_strdup ("world");
+ foo = _tmp28_;
+ _tmp29_ = g_strdup ("world");
+ bar = _tmp29_;
+ _tmp30_ = bar;
+ _tmp31_ = 0;
+ _vala_assert (((g_strcmp0 (foo, _tmp30_) == 0) && (g_strcmp0 (_tmp30_, "hello") != 0)) == ((0 == _tmp31_) && (_tmp31_ <= 1)), "(foo == bar != \"hello\") == (0 == 0 <= 1)");
+ _g_free0 (bar);
+ _g_free0 (foo);
+ }
+ {
+ gchar* foo = NULL;
+ gchar* _tmp32_;
+ gchar* bar = NULL;
+ gchar* _tmp33_;
+ gchar* _tmp34_;
+ gint _tmp35_;
+ _tmp32_ = g_strdup ("world");
+ foo = _tmp32_;
+ _tmp33_ = g_strdup ("world");
+ bar = _tmp33_;
+ _tmp34_ = bar;
+ _tmp35_ = 1;
+ _vala_assert (((g_strcmp0 (foo, _tmp34_) == 0) && (g_strcmp0 (_tmp34_, "hello") == 0)) == ((1 == _tmp35_) && (_tmp35_ <= 0)), "(foo == bar == \"hello\") == (1 == 1 <= 0)");
+ _g_free0 (bar);
+ _g_free0 (foo);
+ }
+}
+
+int
+main (int argc,
+ char ** argv)
+{
+ _vala_main ();
+ return 0;
+}
+
--- /dev/null
+void main () {
+ {
+ var foo = 123;
+ var bar = 123;
+ assert (foo == bar == 123);
+ }
+ {
+ var foo = 111;
+ var bar = 222;
+ assert (foo != bar == 222);
+ }
+ {
+ var foo = 111;
+ var bar = 111;
+ assert (foo == bar != 222);
+ }
+ {
+ var foo = 111;
+ var bar = 111;
+ assert (0 < foo == bar < 222);
+ }
+ {
+ var a = 111;
+ var b = 111;
+ var c = 111;
+ assert (a == b == c == 111);
+ }
+ {
+ var a = 111;
+ var b = 222;
+ var c = 333;
+ assert (a != b != c != 123);
+ }
+ {
+ var foo = "world";
+ var bar = "hello";
+ assert (foo > bar == "hello");
+ }
+ {
+ var a = "hello";
+ var b = "hello";
+ var c = "hello";
+ assert ("hello" == a <= b == c == "hello" <= "hello");
+ }
+ {
+ var foo = "h";
+ var bar = "h";
+ assert (foo == bar < "hello");
+ }
+ {
+ var foo = "hello";
+ var bar = "world";
+ assert (foo != bar == "world");
+ }
+ {
+ var foo = "world";
+ var bar = "world";
+ assert (foo == bar != "hello");
+ }
+ {
+ var foo = "world";
+ var bar = "world";
+ assert ((foo == bar != "hello") == (0 == 0 <= 1)); // true == true
+ }
+ {
+ var foo = "world";
+ var bar = "world";
+ assert ((foo == bar == "hello") == (1 == 1 <= 0)); // false == false
+ }
+}
DataType resulting_type;
if (is_chained) {
- var lbe = (BinaryExpression) left;
+ unowned BinaryExpression lbe = (BinaryExpression) left;
+ if (lbe.right.value_type.compatible (context.analyzer.string_type)
+ && right.value_type.compatible (context.analyzer.string_type)) {
+ value_type = context.analyzer.bool_type;
+ break;
+ }
resulting_type = context.analyzer.get_arithmetic_result_type (lbe.right.target_type, right.target_type);
} else {
resulting_type = context.analyzer.get_arithmetic_result_type (left.target_type, right.target_type);
if (resulting_type == null) {
error = true;
- Report.error (source_reference, "Relational operation not supported for types `%s' and `%s'", left.value_type.to_string (), right.value_type.to_string ());
+ unowned DataType left_type;
+ if (is_chained) {
+ unowned BinaryExpression lbe = (BinaryExpression) left;
+ left_type = lbe.right.value_type;
+ } else {
+ left_type = left.value_type;
+ }
+ Report.error (source_reference, "Relational operation not supported for types `%s' and `%s'", left_type.to_string (), right.value_type.to_string ());
return false;
}
}
}
- if (!right.value_type.compatible (left.value_type)
- && !left.value_type.compatible (right.value_type)) {
- Report.error (source_reference, "Equality operation: `%s' and `%s' are incompatible", right.value_type.to_string (), left.value_type.to_string ());
- error = true;
- return false;
+ DataType resulting_type;
+ if (is_chained) {
+ unowned BinaryExpression lbe = (BinaryExpression) left;
+ resulting_type = context.analyzer.get_arithmetic_result_type (lbe.right.target_type, right.target_type);
+ if (!right.value_type.compatible (lbe.right.value_type)
+ && !lbe.right.value_type.compatible (right.value_type)) {
+ Report.error (source_reference, "Equality operation: `%s' and `%s' are incompatible", right.value_type.to_string (), lbe.right.value_type.to_string ());
+ error = true;
+ return false;
+ }
+ } else {
+ resulting_type = context.analyzer.get_arithmetic_result_type (left.target_type, right.target_type);
+ if (!right.value_type.compatible (left.value_type)
+ && !left.value_type.compatible (right.value_type)) {
+ Report.error (source_reference, "Equality operation: `%s' and `%s' are incompatible", right.value_type.to_string (), left.value_type.to_string ());
+ error = true;
+ return false;
+ }
}
- var resulting_type = context.analyzer.get_arithmetic_result_type (left.target_type, right.target_type);
if (resulting_type != null) {
// numeric operation
- left.target_type = resulting_type.copy ();
+ if (!is_chained) {
+ left.target_type = resulting_type.copy ();
+ }
right.target_type = resulting_type.copy ();
}
case BinaryOperator.LESS_THAN:
case BinaryOperator.LESS_THAN_OR_EQUAL:
case BinaryOperator.GREATER_THAN_OR_EQUAL:
+ case BinaryOperator.EQUALITY:
+ case BinaryOperator.INEQUALITY:
next ();
var right = parse_type_check_expression ();
if (first) {
return left;
}
- Expression parse_equality_expression () throws ParseError {
- var begin = get_location ();
- var left = parse_relational_expression ();
- bool found = true;
- while (found) {
- var operator = get_binary_operator (current ());
- switch (operator) {
- case BinaryOperator.EQUALITY:
- case BinaryOperator.INEQUALITY:
- next ();
- var right = parse_relational_expression ();
- left = new BinaryExpression (operator, left, right, get_src (begin));
- break;
- default:
- found = false;
- break;
- }
- }
- return left;
- }
-
Expression parse_and_expression () throws ParseError {
var begin = get_location ();
- var left = parse_equality_expression ();
+ var left = parse_relational_expression ();
while (accept (TokenType.BITWISE_AND)) {
- var right = parse_equality_expression ();
+ var right = parse_relational_expression ();
left = new BinaryExpression (BinaryOperator.BITWISE_AND, left, right, get_src (begin));
}
return left;