/**
* Represents an expression with two operands in the source code.
*
- * Supports +, -, *, /, %, <<, >>, <, >, <=, >=, ==, !=, &, |, ^, &&, ||.
+ * Supports +, -, *, /, %, <<, >>, <, >, <=, >=, ==, !=, &, |, ^, &&, ||, ??.
*/
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 ();
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;
BITWISE_XOR,
AND,
OR,
- IN
+ IN,
+ COALESCE
}
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);