This patch from Chris Manghane adds a conditional expression construct to the Go frontend IR, for use in future conversion to the backend interface. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline.
Ian
diff -r cc4de9df6d88 go/expressions.cc --- a/go/expressions.cc Tue Jan 28 13:43:27 2014 -0800 +++ b/go/expressions.cc Thu Jan 30 17:55:18 2014 -0800 @@ -15040,6 +15040,103 @@ return new Label_addr_expression(label, location); } +// Conditional expressions. + +class Conditional_expression : public Expression +{ + public: + Conditional_expression(Expression* cond, Expression* then_expr, + Expression* else_expr, Location location) + : Expression(EXPRESSION_CONDITIONAL, location), + cond_(cond), then_(then_expr), else_(else_expr) + {} + + protected: + Type* + do_type(); + + void + do_determine_type(const Type_context*) + { } + + Expression* + do_copy() + { + return new Conditional_expression(this->cond_->copy(), this->then_->copy(), + this->else_->copy(), this->location()); + } + + tree + do_get_tree(Translate_context* context); + + void + do_dump_expression(Ast_dump_context*) const; + + private: + // The condition to be checked. + Expression* cond_; + // The expression to execute if the condition is true. + Expression* then_; + // The expression to execute if the condition is false. + Expression* else_; +}; + +// Return the type of the conditional expression. + +Type* +Conditional_expression::do_type() +{ + Type* result_type = Type::make_void_type(); + if (this->then_->type() == this->else_->type()) + result_type = this->then_->type(); + else if (this->then_->is_nil_expression() + || this->else_->is_nil_expression()) + result_type = (!this->then_->is_nil_expression() + ? this->then_->type() + : this->else_->type()); + return result_type; +} + +// Get the backend representation of a conditional expression. + +tree +Conditional_expression::do_get_tree(Translate_context* context) +{ + Gogo* gogo = context->gogo(); + Btype* result_btype = this->type()->get_backend(gogo); + Bexpression* cond = tree_to_expr(this->cond_->get_tree(context)); + Bexpression* then = tree_to_expr(this->then_->get_tree(context)); + Bexpression* belse = tree_to_expr(this->else_->get_tree(context)); + Bexpression* ret = + gogo->backend()->conditional_expression(result_btype, cond, then, belse, + this->location()); + return expr_to_tree(ret); +} + +// Dump ast representation of a conditional expression. + +void +Conditional_expression::do_dump_expression( + Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->ostream() << "("; + ast_dump_context->dump_expression(this->cond_); + ast_dump_context->ostream() << " ? "; + ast_dump_context->dump_expression(this->then_); + ast_dump_context->ostream() << " : "; + ast_dump_context->dump_expression(this->else_); + ast_dump_context->ostream() << ") "; +} + +// Make a conditional expression. + +Expression* +Expression::make_conditional(Expression* cond, Expression* then, + Expression* else_expr, Location location) +{ + return new Conditional_expression(cond, then, else_expr, location); +} + // Import an expression. This comes at the end in order to see the // various class definitions. diff -r cc4de9df6d88 go/expressions.h --- a/go/expressions.h Tue Jan 28 13:43:27 2014 -0800 +++ b/go/expressions.h Thu Jan 30 17:55:18 2014 -0800 @@ -106,7 +106,8 @@ EXPRESSION_INTERFACE_INFO, EXPRESSION_STRUCT_FIELD_OFFSET, EXPRESSION_MAP_DESCRIPTOR, - EXPRESSION_LABEL_ADDR + EXPRESSION_LABEL_ADDR, + EXPRESSION_CONDITIONAL }; Expression(Expression_classification, Location); @@ -388,6 +389,10 @@ static Expression* make_label_addr(Label*, Location); + // Make a conditional expression. + static Expression* + make_conditional(Expression*, Expression*, Expression*, Location); + // Return the expression classification. Expression_classification classification() const