[vala] Implement coalescing operator ??



commit b319ccfbfd263417ef0724bf3346eb3765cf75a9
Author: Jürg Billeter <j bitron ch>
Date:   Wed Jan 27 02:13:24 2010 +0100

    Implement coalescing operator ??
    
    Based on patch by Marc-André Lureau, fixes bug 580816.

 vala/valabinaryexpression.vala |   38 ++++++++++++++++++++++++++++++++++++--
 vala/valacodewriter.vala       |    3 +++
 vala/valaparser.vala           |   13 ++++++++++++-
 vala/valascanner.vala          |    4 ++++
 vala/valatokentype.vala        |    1 +
 5 files changed, 56 insertions(+), 3 deletions(-)
---
diff --git a/vala/valabinaryexpression.vala b/vala/valabinaryexpression.vala
index 4400f02..01cae0b 100644
--- a/vala/valabinaryexpression.vala
+++ b/vala/valabinaryexpression.vala
@@ -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
 }
diff --git a/vala/valacodewriter.vala b/vala/valacodewriter.vala
index b94f777..89fcab0 100644
--- a/vala/valacodewriter.vala
+++ b/vala/valacodewriter.vala
@@ -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 ();
 		}
diff --git a/vala/valaparser.vala b/vala/valaparser.vala
index 999976e..b3d3454 100644
--- a/vala/valaparser.vala
+++ b/vala/valaparser.vala
@@ -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);
diff --git a/vala/valascanner.vala b/vala/valascanner.vala
index 9a1d3ea..40e1975 100644
--- a/vala/valascanner.vala
+++ b/vala/valascanner.vala
@@ -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;
diff --git a/vala/valatokentype.vala b/vala/valatokentype.vala
index bfacde1..61b4859 100644
--- a/vala/valatokentype.vala
+++ b/vala/valatokentype.vala
@@ -93,6 +93,7 @@ public enum Vala.TokenType {
 	NULL,
 	OUT,
 	OP_AND,
+	OP_COALESCING,
 	OP_DEC,
 	OP_EQ,
 	OP_GE,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]