]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Implement coalescing operator ??
authorJürg Billeter <j@bitron.ch>
Wed, 27 Jan 2010 01:13:24 +0000 (02:13 +0100)
committerJürg Billeter <j@bitron.ch>
Fri, 29 Jan 2010 18:25:33 +0000 (19:25 +0100)
Based on patch by Marc-André Lureau, fixes bug 580816.

vala/valabinaryexpression.vala
vala/valacodewriter.vala
vala/valaparser.vala
vala/valascanner.vala
vala/valatokentype.vala

index 4400f025097bcc6f563ff00cc9dce7fbaa0d0366..01cae0b87d395d96aa5d209ae87c627783ac29a6 100644 (file)
@@ -24,7 +24,7 @@
 /**
  * Represents an expression with two operands in the source code.
  *
- * Supports +, -, *, /, %, <<, >>, <, >, <=, >=, ==, !=, &, |, ^, &&, ||.
+ * Supports +, -, *, /, %, <<, >>, <, >, <=, >=, ==, !=, &, |, ^, &&, ||, ??.
  */
 public class Vala.BinaryExpression : Expression {
        /**
@@ -118,6 +118,7 @@ public class Vala.BinaryExpression : Expression {
                case BinaryOperator.AND: return "&&";
                case BinaryOperator.OR: return "||";
                case BinaryOperator.IN: return "in";
+               case BinaryOperator.COALESCE: return "??";
                }
 
                assert_not_reached ();
@@ -206,6 +207,38 @@ public class Vala.BinaryExpression : Expression {
                        return true;
                }
 
+               if (operator == BinaryOperator.COALESCE) {
+                       var local = new LocalVariable (null, get_temp_name (), left, source_reference);
+                       var decl = new DeclarationStatement (local, source_reference);
+                       decl.check (analyzer);
+
+                       var right_stmt = new ExpressionStatement (new Assignment (new MemberAccess.simple (local.name, right.source_reference), right, AssignmentOperator.SIMPLE, right.source_reference), right.source_reference);
+
+                       var true_block = new Block (source_reference);
+
+                       true_block.add_statement (right_stmt);
+
+                       var cond = new BinaryExpression (BinaryOperator.EQUALITY, new MemberAccess.simple (local.name, left.source_reference), new NullLiteral (source_reference), source_reference);
+
+                       var if_stmt = new IfStatement (cond, true_block, null, source_reference);
+
+                       insert_statement (analyzer.insert_block, decl);
+                       insert_statement (analyzer.insert_block, if_stmt);
+
+                       if (!if_stmt.check (analyzer)) {
+                               error = true;
+                               return false;
+                       }
+
+                       var ma = new MemberAccess.simple (local.name, source_reference);
+                       ma.target_type = target_type;
+                       ma.check (analyzer);
+
+                       parent_node.replace_expression (this, ma);
+
+                       return true;
+               }
+
                if (!left.check (analyzer) || !right.check (analyzer)) {
                        /* if there were any errors in inner expressions, skip type check */
                        error = true;
@@ -432,5 +465,6 @@ public enum Vala.BinaryOperator {
        BITWISE_XOR,
        AND,
        OR,
-       IN
+       IN,
+       COALESCE
 }
index b94f777951dfa7acecd3a200df7d057fa820dd7e..89fcab079bf62245830324f68531b3e847c0baae 100644 (file)
@@ -1586,6 +1586,9 @@ public class Vala.CodeWriter : CodeVisitor {
                case BinaryOperator.IN:
                        write_string (" in ");
                        break;
+               case BinaryOperator.COALESCE:
+                       write_string (" ?? ");
+                       break;
                default:
                        assert_not_reached ();
                }
index 999976ebf3d723a817a81226d64085538004032e..b3d3454c57588eba6c91979424b65c410503cd6c 100644 (file)
@@ -1217,9 +1217,20 @@ public class Vala.Parser : CodeVisitor {
                return left;
        }
 
+       Expression parse_coalescing_expression () throws ParseError {
+               var begin = get_location ();
+               var left = parse_conditional_or_expression ();
+               if (accept (TokenType.OP_COALESCING)) {
+                       var right = parse_coalescing_expression ();
+                       return new BinaryExpression (BinaryOperator.COALESCE, left, right, get_src (begin));
+               } else {
+                       return left;
+               }
+       }
+
        Expression parse_conditional_expression () throws ParseError {
                var begin = get_location ();
-               var condition = parse_conditional_or_expression ();
+               var condition = parse_coalescing_expression ();
                if (accept (TokenType.INTERR)) {
                        var true_expr = parse_expression ();
                        expect (TokenType.COLON);
index 9a1d3eabcfe49a16ca3f226aed7e6eeec06385b5..40e19751c1f9c734b2164cd99de6ab50e74bd845 100644 (file)
@@ -688,6 +688,10 @@ public class Vala.Scanner {
                        case '?':
                                type = TokenType.INTERR;
                                current++;
+                               if (current < end && current[0] == '?') {
+                                       type = TokenType.OP_COALESCING;
+                                       current++;
+                               }
                                break;
                        case '|':
                                type = TokenType.BITWISE_OR;
index bfacde16dda1edf5ad5d13a50575e7ff51073e1a..61b485958f435275633e26212edaa9528ab7259b 100644 (file)
@@ -93,6 +93,7 @@ public enum Vala.TokenType {
        NULL,
        OUT,
        OP_AND,
+       OP_COALESCING,
        OP_DEC,
        OP_EQ,
        OP_GE,