// expressions.h -- Go frontend expression handling.     -*- C++ -*-

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#ifndef GO_EXPRESSIONS_H
#define GO_EXPRESSIONS_H

#include <mpfr.h>
#include <mpc.h>

#include "operator.h"
#include "runtime.h"

class Gogo;
class Translate_context;
class Traverse;
class Statement_inserter;
class Type;
class Method;
struct Type_context;
class Integer_type;
class Float_type;
class Complex_type;
class Function_type;
class Map_type;
class Struct_type;
class Struct_field;
class Expression_list;
class Var_expression;
class Enclosed_var_expression;
class Temporary_reference_expression;
class Set_and_use_temporary_expression;
class String_expression;
class Type_conversion_expression;
class Unsafe_type_conversion_expression;
class Unary_expression;
class Binary_expression;
class String_concat_expression;
class Call_expression;
class Builtin_call_expression;
class Call_result_expression;
class Func_expression;
class Func_descriptor_expression;
class Unknown_expression;
class Index_expression;
class Array_index_expression;
class String_index_expression;
class Map_index_expression;
class Bound_method_expression;
class Field_reference_expression;
class Interface_field_reference_expression;
class Allocation_expression;
class Composite_literal_expression;
class Struct_construction_expression;
class Array_construction_expression;
class Fixed_array_construction_expression;
class Slice_construction_expression;
class Map_construction_expression;
class Type_guard_expression;
class Heap_expression;
class Receive_expression;
class Slice_value_expression;
class Conditional_expression;
class Compound_expression;
class Numeric_constant;
class Named_object;
class Export_function_body;
class Import_expression;
class Temporary_statement;
class Label;
class Ast_dump_context;
class String_dump;

// The precision to use for complex values represented as an mpc_t.
const int mpc_precision = 256;

// The base class for all expressions.

class Expression
{
 public:
  // The types of expressions.
  enum Expression_classification
  {
    EXPRESSION_ERROR,
    EXPRESSION_TYPE,
    EXPRESSION_UNARY,
    EXPRESSION_BINARY,
    EXPRESSION_STRING_CONCAT,
    EXPRESSION_CONST_REFERENCE,
    EXPRESSION_VAR_REFERENCE,
    EXPRESSION_ENCLOSED_VAR_REFERENCE,
    EXPRESSION_TEMPORARY_REFERENCE,
    EXPRESSION_SET_AND_USE_TEMPORARY,
    EXPRESSION_SINK,
    EXPRESSION_FUNC_REFERENCE,
    EXPRESSION_FUNC_DESCRIPTOR,
    EXPRESSION_FUNC_CODE_REFERENCE,
    EXPRESSION_UNKNOWN_REFERENCE,
    EXPRESSION_BOOLEAN,
    EXPRESSION_STRING,
    EXPRESSION_STRING_INFO,
    EXPRESSION_INTEGER,
    EXPRESSION_FLOAT,
    EXPRESSION_COMPLEX,
    EXPRESSION_NIL,
    EXPRESSION_IOTA,
    EXPRESSION_CALL,
    EXPRESSION_CALL_RESULT,
    EXPRESSION_BOUND_METHOD,
    EXPRESSION_INDEX,
    EXPRESSION_ARRAY_INDEX,
    EXPRESSION_STRING_INDEX,
    EXPRESSION_MAP_INDEX,
    EXPRESSION_SELECTOR,
    EXPRESSION_FIELD_REFERENCE,
    EXPRESSION_INTERFACE_FIELD_REFERENCE,
    EXPRESSION_ALLOCATION,
    EXPRESSION_TYPE_GUARD,
    EXPRESSION_CONVERSION,
    EXPRESSION_UNSAFE_CONVERSION,
    EXPRESSION_STRUCT_CONSTRUCTION,
    EXPRESSION_FIXED_ARRAY_CONSTRUCTION,
    EXPRESSION_SLICE_CONSTRUCTION,
    EXPRESSION_MAP_CONSTRUCTION,
    EXPRESSION_COMPOSITE_LITERAL,
    EXPRESSION_HEAP,
    EXPRESSION_RECEIVE,
    EXPRESSION_TYPE_DESCRIPTOR,
    EXPRESSION_GC_SYMBOL,
    EXPRESSION_PTRMASK_SYMBOL,
    EXPRESSION_TYPE_INFO,
    EXPRESSION_SLICE_INFO,
    EXPRESSION_SLICE_VALUE,
    EXPRESSION_INTERFACE_INFO,
    EXPRESSION_INTERFACE_VALUE,
    EXPRESSION_INTERFACE_MTABLE,
    EXPRESSION_STRUCT_FIELD_OFFSET,
    EXPRESSION_LABEL_ADDR,
    EXPRESSION_CONDITIONAL,
    EXPRESSION_COMPOUND,
    EXPRESSION_BACKEND
  };

  Expression(Expression_classification, Location);

  virtual ~Expression();

  // Make an error expression.  This is used when a parse error occurs
  // to prevent cascading errors.
  static Expression*
  make_error(Location);

  // Make an expression which is really a type.  This is used during
  // parsing.
  static Expression*
  make_type(Type*, Location);

  // Make a unary expression.
  static Expression*
  make_unary(Operator, Expression*, Location);

  // Make a binary expression.
  static Expression*
  make_binary(Operator, Expression*, Expression*, Location);

  // Make a string concatenation expression.
  static Expression*
  make_string_concat(Expression_list*);

  // Make a reference to a constant in an expression.
  static Expression*
  make_const_reference(Named_object*, Location);

  // Make a reference to a variable in an expression.
  static Expression*
  make_var_reference(Named_object*, Location);

  // Make a reference to a variable within an enclosing function.
  static Expression*
  make_enclosing_var_reference(Expression*, Named_object*, Location);

  // Make a reference to a temporary variable.  Temporary variables
  // are always created by a single statement, which is what we use to
  // refer to them.
  static Temporary_reference_expression*
  make_temporary_reference(Temporary_statement*, Location);

  // Make an expressions which sets a temporary variable and then
  // evaluates to a reference to that temporary variable.  This is
  // used to set a temporary variable while retaining the order of
  // evaluation.
  static Set_and_use_temporary_expression*
  make_set_and_use_temporary(Temporary_statement*, Expression*, Location);

  // Make a sink expression--a reference to the blank identifier _.
  static Expression*
  make_sink(Location);

  // Make a reference to a function in an expression.  This returns a
  // pointer to the struct holding the address of the function
  // followed by any closed-over variables.
  static Expression*
  make_func_reference(Named_object*, Expression* closure, Location);

  // Make a function descriptor, an immutable struct with a single
  // field that points to the function code.  This may only be used
  // with functions that do not have closures.  FN is the function for
  // which we are making the descriptor.
  static Func_descriptor_expression*
  make_func_descriptor(Named_object* fn);

  // Make a reference to the code of a function.  This is used to set
  // descriptor and closure fields.
  static Expression*
  make_func_code_reference(Named_object*, Location);

  // Make a reference to an unknown name.  In a correct program this
  // will always be lowered to a real const/var/func reference.
  static Unknown_expression*
  make_unknown_reference(Named_object*, Location);

  // Make a constant bool expression.
  static Expression*
  make_boolean(bool val, Location);

  // Make a constant string expression.
  static Expression*
  make_string(const std::string&, Location);

  // Make an expression that evaluates to some characteristic of an string.
  // For simplicity, the enum values must match the field indexes in the
  // underlying struct.
  enum String_info
    {
      // The underlying data in the string.
      STRING_INFO_DATA,
      // The length of the string.
      STRING_INFO_LENGTH
    };

  static Expression*
  make_string_info(Expression* string, String_info, Location);

  // Make a character constant expression.  TYPE should be NULL for an
  // abstract type.
  static Expression*
  make_character(const mpz_t*, Type*, Location);

  // Make a constant integer expression from a multi-precision
  // integer.  TYPE should be NULL for an abstract type.
  static Expression*
  make_integer_z(const mpz_t*, Type*, Location);

  // Make a constant integer expression from an unsigned long.  TYPE
  // should be NULL for an abstract type.
  static Expression*
  make_integer_ul(unsigned long, Type*, Location);

  // Make a constant integer expression from a signed long.  TYPE
  // should be NULL for an abstract type.
  static Expression*
  make_integer_sl(long, Type*, Location);

  // Make a constant integer expression from an int64_t.  TYPE should
  // be NULL for an abstract type.
  static Expression*
  make_integer_int64(int64_t, Type*, Location);

  // Make a constant float expression.  TYPE should be NULL for an
  // abstract type.
  static Expression*
  make_float(const mpfr_t*, Type*, Location);

  // Make a constant complex expression.  TYPE should be NULL for an
  // abstract type.
  static Expression*
  make_complex(const mpc_t*, Type*, Location);

  // Make a nil expression.
  static Expression*
  make_nil(Location);

  // Make an iota expression.  This is used for the predeclared
  // constant iota.
  static Expression*
  make_iota();

  // Make a call expression.
  static Call_expression*
  make_call(Expression* func, Expression_list* args, bool is_varargs,
	    Location);

  // Make a reference to a specific result of a call expression which
  // returns a tuple.
  static Expression*
  make_call_result(Call_expression*, unsigned int index);

  // Make an expression which is a method bound to its first
  // parameter.  METHOD is the method being called, FUNCTION is the
  // function to call.
  static Bound_method_expression*
  make_bound_method(Expression* object, const Method* method,
		    Named_object* function, Location);

  // Make an index or slice expression.  This is a parser expression
  // which represents LEFT[START:END:CAP].  END may be NULL, meaning an
  // index rather than a slice.  CAP may be NULL, meaning we use the default
  // capacity of LEFT. At parse time we may not know the type of LEFT.
  // After parsing this is lowered to an array index, a string index,
  // or a map index.
  static Expression*
  make_index(Expression* left, Expression* start, Expression* end,
             Expression* cap, Location);

  // Make an array index expression.  END may be NULL, in which case
  // this is an lvalue.  CAP may be NULL, in which case it defaults
  // to cap(ARRAY).
  static Expression*
  make_array_index(Expression* array, Expression* start, Expression* end,
                   Expression* cap, Location);

  // Make a string index expression.  END may be NULL.  This is never
  // an lvalue.
  static Expression*
  make_string_index(Expression* string, Expression* start, Expression* end,
		    Location);

  // Make a map index expression.  This is an lvalue.
  static Map_index_expression*
  make_map_index(Expression* map, Expression* val, Location);

  // Make a selector.  This is a parser expression which represents
  // LEFT.NAME.  At parse time we may not know the type of the left
  // hand side.
  static Expression*
  make_selector(Expression* left, const std::string& name, Location);

  // Make a reference to a field in a struct.
  static Field_reference_expression*
  make_field_reference(Expression*, unsigned int field_index, Location);

  // Make a reference to a field of an interface, with an associated
  // object.
  static Expression*
  make_interface_field_reference(Expression*, const std::string&,
				 Location);

  // Make an allocation expression.
  static Expression*
  make_allocation(Type*, Location);

  // Make a type guard expression.
  static Expression*
  make_type_guard(Expression*, Type*, Location);

  // Make a type cast expression.
  static Expression*
  make_cast(Type*, Expression*, Location);

  // Make an unsafe type cast expression.  This is only used when
  // passing parameter to builtin functions that are part of the Go
  // runtime.
  static Expression*
  make_unsafe_cast(Type*, Expression*, Location);

  // Make a composite literal.  The DEPTH parameter is how far down we
  // are in a list of composite literals with omitted types.  HAS_KEYS
  // is true if the expression list has keys alternating with values.
  // ALL_ARE_NAMES is true if all the keys could be struct field
  // names.
  static Expression*
  make_composite_literal(Type*, int depth, bool has_keys, Expression_list*,
			 bool all_are_names, Location);

  // Make a struct composite literal.
  static Expression*
  make_struct_composite_literal(Type*, Expression_list*, Location);

  // Make an array composite literal.
  static Expression*
  make_array_composite_literal(Type*, Expression_list*, Location);

  // Make a slice composite literal.
  static Slice_construction_expression*
  make_slice_composite_literal(Type*, Expression_list*, Location);

  // Take an expression and allocate it on the heap.
  static Expression*
  make_heap_expression(Expression*, Location);

  // Make a receive expression.  VAL is NULL for a unary receive.
  static Receive_expression*
  make_receive(Expression* channel, Location);

  // Make an expression which evaluates to the address of the type
  // descriptor for TYPE.
  static Expression*
  make_type_descriptor(Type* type, Location);

  // Make an expression which evaluates to the address of the gc
  // symbol for TYPE.
  static Expression*
  make_gc_symbol(Type* type);

  // Make an expression that evaluates to the address of a ptrmask
  // symbol for TYPE.  For most types this will be the same as
  // make_gc_symbol, but for larger types make_gc_symbol will return a
  // gcprog while this will return a ptrmask.
  static Expression*
  make_ptrmask_symbol(Type* type);

  // Make an expression which evaluates to some characteristic of a
  // type.  These are only used for type descriptors, so there is no
  // location parameter.
  enum Type_info
    {
      // The size of a value of the type.
      TYPE_INFO_SIZE,
      // The required alignment of a value of the type.
      TYPE_INFO_ALIGNMENT,
      // The required alignment of a value of the type when used as a
      // field in a struct.
      TYPE_INFO_FIELD_ALIGNMENT,
      // The size of the prefix of a value of the type that contains
      // all the pointers.  This is 0 for a type that contains no
      // pointers.  It is always <= TYPE_INFO_SIZE.
      TYPE_INFO_BACKEND_PTRDATA,
      // Like TYPE_INFO_BACKEND_PTRDATA, but the ptrdata value that we
      // want to store in a type descriptor.  They are the same for
      // most types, but can differ for a type that uses a gcprog.
      TYPE_INFO_DESCRIPTOR_PTRDATA
    };

  static Expression*
  make_type_info(Type* type, Type_info);

  // Make an expression that evaluates to some characteristic of a
  // slice.  For simplicity, the enum values must match the field indexes
  // in the underlying struct.
  enum Slice_info
    {
      // The underlying data of the slice.
      SLICE_INFO_VALUE_POINTER,
      // The length of the slice.
      SLICE_INFO_LENGTH,
      // The capacity of the slice.
      SLICE_INFO_CAPACITY
    };

  static Expression*
  make_slice_info(Expression* slice, Slice_info, Location);

  // Make an expression for a slice value.
  static Expression*
  make_slice_value(Type*, Expression* valptr, Expression* len, Expression* cap,
                   Location);

  // Make an expression that evaluates to some characteristic of an
  // interface.  For simplicity, the enum values must match the field indexes
  // in the underlying struct.
  enum Interface_info
    {
      // The type descriptor of an empty interface.
      INTERFACE_INFO_TYPE_DESCRIPTOR = 0,
      // The methods of an interface.
      INTERFACE_INFO_METHODS = 0,
      // The first argument to pass to an interface method.
      INTERFACE_INFO_OBJECT
    };

  static Expression*
  make_interface_info(Expression* iface, Interface_info, Location);

  // Make an expression for an interface value.
  static Expression*
  make_interface_value(Type*, Expression*, Expression*, Location);

  // Make an expression that builds a reference to the interface method table
  // for TYPE that satisfies interface ITYPE. IS_POINTER is true if this is a
  // reference to the interface method table for the pointer receiver type.
  static Expression*
  make_interface_mtable_ref(Interface_type* itype, Type* type,
                            bool is_pointer, Location);

  // Make an expression which evaluates to the offset of a field in a
  // struct.  This is only used for type descriptors, so there is no
  // location parameter.
  static Expression*
  make_struct_field_offset(Struct_type*, const Struct_field*);

  // Make an expression which evaluates to the address of an unnamed
  // label.
  static Expression*
  make_label_addr(Label*, Location);

  // Make a conditional expression.
  static Expression*
  make_conditional(Expression*, Expression*, Expression*, Location);

  // Make a compound expression.
  static Expression*
  make_compound(Expression*, Expression*, Location);

  // Make a backend expression.
  static Expression*
  make_backend(Bexpression*, Type*, Location);

  enum Nil_check_classification
    {
      // Use the default policy for deciding if this deref needs a check.
      NIL_CHECK_DEFAULT,
      // An explicit check is required for this dereference operation.
      NIL_CHECK_NEEDED,
      // No check needed for this dereference operation.
      NIL_CHECK_NOT_NEEDED,
      // A type error or error construct was encountered when determining
      // whether this deref needs an explicit check.
      NIL_CHECK_ERROR_ENCOUNTERED
    };

  // Make a dereference expression.
  static Expression*
  make_dereference(Expression*, Nil_check_classification, Location);

  // Return the expression classification.
  Expression_classification
  classification() const
  { return this->classification_; }

  // Return the location of the expression.
  Location
  location() const
  { return this->location_; }

  // Return whether this is a constant expression.
  bool
  is_constant() const
  { return this->do_is_constant(); }

  // Return whether this expression can be used as a static
  // initializer.  This is true for an expression that has only
  // numbers and pointers to global variables or composite literals
  // that do not require runtime initialization.  It is false if we
  // must generate code to compute this expression when it is used to
  // initialize a global variable.  This is not a language-level
  // concept, but an implementation-level one.  If this expression is
  // used to initialize a global variable, this is true if we can pass
  // an initializer to the backend, false if we must generate code to
  // initialize the variable.  It is always safe for this method to
  // return false, but the resulting code may be less efficient.
  bool
  is_static_initializer() const
  { return this->do_is_static_initializer(); }

  // If this is not a numeric constant, return false.  If it is one,
  // return true, and set VAL to hold the value.
  bool
  numeric_constant_value(Numeric_constant* val) const
  { return this->do_numeric_constant_value(val); }

  // If this is not a constant expression with string type, return
  // false.  If it is one, return true, and set VAL to the value.
  bool
  string_constant_value(std::string* val) const
  { return this->do_string_constant_value(val); }

  // This is called if the value of this expression is being
  // discarded.  This issues warnings about computed values being
  // unused.  This returns true if all is well, false if it issued an
  // error message.
  bool
  discarding_value()
  { return this->do_discarding_value(); }

  // Return whether this is an error expression.
  bool
  is_error_expression() const
  { return this->classification_ == EXPRESSION_ERROR; }

  // Return whether this expression really represents a type.
  bool
  is_type_expression() const
  { return this->classification_ == EXPRESSION_TYPE; }

  // If this is a variable reference, return the Var_expression
  // structure.  Otherwise, return NULL.  This is a controlled dynamic
  // cast.
  Var_expression*
  var_expression()
  { return this->convert<Var_expression, EXPRESSION_VAR_REFERENCE>(); }

  const Var_expression*
  var_expression() const
  { return this->convert<const Var_expression, EXPRESSION_VAR_REFERENCE>(); }

  // If this is a enclosed_variable reference, return the
  // Enclosed_var_expression structure.  Otherwise, return NULL.
  // This is a controlled dynamic cast.
  Enclosed_var_expression*
  enclosed_var_expression()
  { return this->convert<Enclosed_var_expression,
			 EXPRESSION_ENCLOSED_VAR_REFERENCE>(); }

  const Enclosed_var_expression*
  enclosed_var_expression() const
  { return this->convert<const Enclosed_var_expression,
			 EXPRESSION_ENCLOSED_VAR_REFERENCE>(); }


  // If this is a reference to a temporary variable, return the
  // Temporary_reference_expression.  Otherwise, return NULL.
  Temporary_reference_expression*
  temporary_reference_expression()
  {
    return this->convert<Temporary_reference_expression,
			 EXPRESSION_TEMPORARY_REFERENCE>();
  }

  // If this is a set-and-use-temporary, return the
  // Set_and_use_temporary_expression.  Otherwise, return NULL.
  Set_and_use_temporary_expression*
  set_and_use_temporary_expression()
  {
    return this->convert<Set_and_use_temporary_expression,
			 EXPRESSION_SET_AND_USE_TEMPORARY>();
  }

  // Return whether this is a sink expression.
  bool
  is_sink_expression() const
  { return this->classification_ == EXPRESSION_SINK; }

  // If this is a string expression, return the String_expression
  // structure.  Otherwise, return NULL.
  String_expression*
  string_expression()
  { return this->convert<String_expression, EXPRESSION_STRING>(); }

  // If this is a conversion expression, return the Type_conversion_expression
  // structure.  Otherwise, return NULL.
  Type_conversion_expression*
  conversion_expression()
  { return this->convert<Type_conversion_expression, EXPRESSION_CONVERSION>(); }

  // If this is an unsafe conversion expression, return the
  // Unsafe_type_conversion_expression structure.  Otherwise, return NULL.
  Unsafe_type_conversion_expression*
  unsafe_conversion_expression()
  {
    return this->convert<Unsafe_type_conversion_expression,
			 EXPRESSION_UNSAFE_CONVERSION>();
  }

  // Return whether this is the expression nil.
  bool
  is_nil_expression() const
  { return this->classification_ == EXPRESSION_NIL; }

  // If this is an indirection through a pointer, return the
  // expression being pointed through.  Otherwise return this.
  Expression*
  deref();

  // If this is a unary expression, return the Unary_expression
  // structure.  Otherwise return NULL.
  Unary_expression*
  unary_expression()
  { return this->convert<Unary_expression, EXPRESSION_UNARY>(); }

  // If this is a binary expression, return the Binary_expression
  // structure.  Otherwise return NULL.
  Binary_expression*
  binary_expression()
  { return this->convert<Binary_expression, EXPRESSION_BINARY>(); }

  // If this is a string concatenation expression, return the
  // String_concat_expression structure.  Otherwise, return NULL.
  String_concat_expression*
  string_concat_expression()
  {
    return this->convert<String_concat_expression, EXPRESSION_STRING_CONCAT>();
  }

  // If this is a call expression, return the Call_expression
  // structure.  Otherwise, return NULL.  This is a controlled dynamic
  // cast.
  Call_expression*
  call_expression()
  { return this->convert<Call_expression, EXPRESSION_CALL>(); }

  // If this is a call_result expression, return the Call_result_expression
  // structure.  Otherwise, return NULL.  This is a controlled dynamic
  // cast.
  Call_result_expression*
  call_result_expression()
  { return this->convert<Call_result_expression, EXPRESSION_CALL_RESULT>(); }

  // If this is an expression which refers to a function, return the
  // Func_expression structure.  Otherwise, return NULL.
  Func_expression*
  func_expression()
  { return this->convert<Func_expression, EXPRESSION_FUNC_REFERENCE>(); }

  const Func_expression*
  func_expression() const
  { return this->convert<const Func_expression, EXPRESSION_FUNC_REFERENCE>(); }

  // If this is an expression which refers to an unknown name, return
  // the Unknown_expression structure.  Otherwise, return NULL.
  Unknown_expression*
  unknown_expression()
  { return this->convert<Unknown_expression, EXPRESSION_UNKNOWN_REFERENCE>(); }

  const Unknown_expression*
  unknown_expression() const
  {
    return this->convert<const Unknown_expression,
			 EXPRESSION_UNKNOWN_REFERENCE>();
  }

  // If this is an index expression, return the Index_expression
  // structure.  Otherwise, return NULL.
  Index_expression*
  index_expression()
  { return this->convert<Index_expression, EXPRESSION_INDEX>(); }

  // If this is an expression which refers to indexing in a array,
  // return the Array_index_expression structure.  Otherwise, return
  // NULL.
  Array_index_expression*
  array_index_expression()
  { return this->convert<Array_index_expression, EXPRESSION_ARRAY_INDEX>(); }

  // If this is an expression which refers to indexing in a string,
  // return the String_index_expression structure.  Otherwise, return
  // NULL.
  String_index_expression*
  string_index_expression()
  { return this->convert<String_index_expression, EXPRESSION_STRING_INDEX>(); }

  // If this is an expression which refers to indexing in a map,
  // return the Map_index_expression structure.  Otherwise, return
  // NULL.
  Map_index_expression*
  map_index_expression()
  { return this->convert<Map_index_expression, EXPRESSION_MAP_INDEX>(); }

  // If this is a bound method expression, return the
  // Bound_method_expression structure.  Otherwise, return NULL.
  Bound_method_expression*
  bound_method_expression()
  { return this->convert<Bound_method_expression, EXPRESSION_BOUND_METHOD>(); }

  // If this is a reference to a field in a struct, return the
  // Field_reference_expression structure.  Otherwise, return NULL.
  Field_reference_expression*
  field_reference_expression()
  {
    return this->convert<Field_reference_expression,
			 EXPRESSION_FIELD_REFERENCE>();
  }

  // If this is a reference to a field in an interface, return the
  // Interface_field_reference_expression structure.  Otherwise,
  // return NULL.
  Interface_field_reference_expression*
  interface_field_reference_expression()
  {
    return this->convert<Interface_field_reference_expression,
			 EXPRESSION_INTERFACE_FIELD_REFERENCE>();
  }

  // If this is an allocation expression, return the Allocation_expression
  // structure.  Otherwise, return NULL.
  Allocation_expression*
  allocation_expression()
  { return this->convert<Allocation_expression, EXPRESSION_ALLOCATION>(); }

  // If this is a general composite literal, return the
  // Composite_literal_expression structure.  Otherwise, return NULL.
  Composite_literal_expression*
  complit()
  {
    return this->convert<Composite_literal_expression,
			 EXPRESSION_COMPOSITE_LITERAL>();
  }

  // If this is a struct composite literal, return the
  // Struct_construction_expression structure.  Otherwise, return NULL.
  Struct_construction_expression*
  struct_literal()
  {
    return this->convert<Struct_construction_expression,
			 EXPRESSION_STRUCT_CONSTRUCTION>();
  }

  // If this is a array composite literal, return the
  // Array_construction_expression structure.  Otherwise, return NULL.
  Fixed_array_construction_expression*
  array_literal()
  {
    return this->convert<Fixed_array_construction_expression,
			 EXPRESSION_FIXED_ARRAY_CONSTRUCTION>();
  }

  // If this is a slice composite literal, return the
  // Slice_construction_expression structure.  Otherwise, return NULL.
  Slice_construction_expression*
  slice_literal()
  {
    return this->convert<Slice_construction_expression,
			 EXPRESSION_SLICE_CONSTRUCTION>();
  }

  // If this is a map composite literal, return the
  // Map_construction_expression structure.  Otherwise, return NULL.
  Map_construction_expression*
  map_literal()
  {
    return this->convert<Map_construction_expression,
			 EXPRESSION_MAP_CONSTRUCTION>();
  }

  // If this is a type guard expression, return the
  // Type_guard_expression structure.  Otherwise, return NULL.
  Type_guard_expression*
  type_guard_expression()
  { return this->convert<Type_guard_expression, EXPRESSION_TYPE_GUARD>(); }

  // If this is a heap expression, returhn the Heap_expression structure.
  // Otherwise, return NULL.
  Heap_expression*
  heap_expression()
  { return this->convert<Heap_expression, EXPRESSION_HEAP>(); }

  // If this is a receive expression, return the Receive_expression
  // structure.  Otherwise, return NULL.
  Receive_expression*
  receive_expression()
  { return this->convert<Receive_expression, EXPRESSION_RECEIVE>(); }

  // If this is a slice value expression, return the Slice_valiue_expression
  // structure.  Otherwise, return NULL.
  Slice_value_expression*
  slice_value_expression()
  { return this->convert<Slice_value_expression, EXPRESSION_SLICE_VALUE>(); }

  // If this is a conditional expression, return the Conditional_expression
  // structure.  Otherwise, return NULL.
  Conditional_expression*
  conditional_expression()
  { return this->convert<Conditional_expression, EXPRESSION_CONDITIONAL>(); }

  // If this is a compound expression, return the Compound_expression structure.
  // Otherwise, return NULL.
  Compound_expression*
  compound_expression()
  { return this->convert<Compound_expression, EXPRESSION_COMPOUND>(); }

  // Return true if this is a composite literal.
  bool
  is_composite_literal() const;

  // Return true if this is a composite literal which is not constant.
  bool
  is_nonconstant_composite_literal() const;

  // Return true if this is a variable or temporary variable.
  bool
  is_variable() const;

  // Return true if this is a reference to a local variable.
  bool
  is_local_variable() const;

  // Return true if two expressions refer to the same variable or
  // struct field.
  static bool
  is_same_variable(Expression*, Expression*);

  // Make the builtin function descriptor type, so that it can be
  // converted.
  static void
  make_func_descriptor_type();

  // Traverse an expression.
  static int
  traverse(Expression**, Traverse*);

  // Traverse subexpressions of this expression.
  int
  traverse_subexpressions(Traverse*);

  // Lower an expression.  This is called immediately after parsing.
  // FUNCTION is the function we are in; it will be NULL for an
  // expression initializing a global variable.  INSERTER may be used
  // to insert statements before the statement or initializer
  // containing this expression; it is normally used to create
  // temporary variables.  IOTA_VALUE is the value that we should give
  // to any iota expressions.  This function must resolve expressions
  // which could not be fully parsed into their final form.  It
  // returns the same Expression or a new one.
  Expression*
  lower(Gogo* gogo, Named_object* function, Statement_inserter* inserter,
	int iota_value)
  { return this->do_lower(gogo, function, inserter, iota_value); }

  // Flatten an expression. This is called after order_evaluation.
  // FUNCTION is the function we are in; it will be NULL for an
  // expression initializing a global variable.  INSERTER may be used
  // to insert statements before the statement or initializer
  // containing this expression; it is normally used to create
  // temporary variables. This function must resolve expressions
  // which could not be fully parsed into their final form.  It
  // returns the same Expression or a new one.
  Expression*
  flatten(Gogo* gogo, Named_object* function, Statement_inserter* inserter)
  { return this->do_flatten(gogo, function, inserter); }

  // Determine the real type of an expression with abstract integer,
  // floating point, or complex type.  TYPE_CONTEXT describes the
  // expected type.
  void
  determine_type(const Type_context*);

  // Check types in an expression.
  void
  check_types(Gogo* gogo)
  { this->do_check_types(gogo); }

  // Determine the type when there is no context.
  void
  determine_type_no_context();

  // Return the current type of the expression.  This may be changed
  // by determine_type.
  Type*
  type()
  { return this->do_type(); }

  // Return a copy of an expression.
  Expression*
  copy()
  { return this->do_copy(); }

  // Return the cost of this statement for inlining purposes.
  int
  inlining_cost() const
  { return this->do_inlining_cost(); }

  // Return whether the expression is addressable--something which may
  // be used as the operand of the unary & operator.
  bool
  is_addressable() const
  { return this->do_is_addressable(); }

  // Note that we are taking the address of this expression.  ESCAPES
  // is true if this address escapes the current function.
  void
  address_taken(bool escapes)
  { this->do_address_taken(escapes); }

  // Note that a nil check must be issued for this expression.
  void
  issue_nil_check()
  { this->do_issue_nil_check(); }

  // Return whether this expression must be evaluated in order
  // according to the order of evaluation rules.  This is basically
  // true of all expressions with side-effects.
  bool
  must_eval_in_order() const
  { return this->do_must_eval_in_order(); }

  // Return whether subexpressions of this expression must be
  // evaluated in order.  This is true of index expressions and
  // pointer indirections.  This sets *SKIP to the number of
  // subexpressions to skip during traversing, as index expressions
  // only requiring moving the index, not the array.
  bool
  must_eval_subexpressions_in_order(int* skip) const
  {
    *skip = 0;
    return this->do_must_eval_subexpressions_in_order(skip);
  }

  // Return the backend representation for this expression.
  Bexpression*
  get_backend(Translate_context*);

  // Return an expression handling any conversions which must be done during
  // assignment.
  static Expression*
  convert_for_assignment(Gogo*, Type* lhs_type, Expression* rhs,
                         Location location);

  // Return an expression converting a value of one interface type to another
  // interface type.  If FOR_TYPE_GUARD is true this is for a type
  // assertion.
  static Expression*
  convert_interface_to_interface(Type* lhs_type,
                                 Expression* rhs, bool for_type_guard,
                                 Location);

  // Return a backend expression implementing the comparison LEFT OP RIGHT.
  // TYPE is the type of both sides.
  static Bexpression*
  comparison(Translate_context*, Type* result_type, Operator op,
	     Expression* left, Expression* right, Location);

  // Return the backend expression for the numeric constant VAL.
  static Bexpression*
  backend_numeric_constant_expression(Translate_context*,
                                      Numeric_constant* val);

  // Export the expression.
  void
  export_expression(Export_function_body* efb) const
  { this->do_export(efb); }

  // Import an expression.  The location should be used for the
  // returned expression.  Errors should be reported using the
  // Import's location method.
  static Expression*
  import_expression(Import_expression*, Location);

  // Return an expression which checks that VAL, of arbitrary integer type,
  // is non-negative and is not more than the maximum integer value.
  static Expression*
  check_bounds(Expression* val, Location);

  // Dump an expression to a dump constext.
  void
  dump_expression(Ast_dump_context*) const;

 protected:
  // May be implemented by child class: traverse the expressions.
  virtual int
  do_traverse(Traverse*);

  // Return a lowered expression.
  virtual Expression*
  do_lower(Gogo*, Named_object*, Statement_inserter*, int)
  { return this; }

  // Return a flattened expression.
  virtual Expression*
  do_flatten(Gogo*, Named_object*, Statement_inserter*)
  { return this; }


  // Return whether this is a constant expression.
  virtual bool
  do_is_constant() const
  { return false; }

  // Return whether this expression can be used as a constant
  // initializer.
  virtual bool
  do_is_static_initializer() const
  { return false; }

  // Return whether this is a constant expression of numeric type, and
  // set the Numeric_constant to the value.
  virtual bool
  do_numeric_constant_value(Numeric_constant*) const
  { return false; }

  // Return whether this is a constant expression of string type, and
  // set VAL to the value.
  virtual bool
  do_string_constant_value(std::string*) const
  { return false; }

  // Called by the parser if the value is being discarded.
  virtual bool
  do_discarding_value();

  // Child class holds type.
  virtual Type*
  do_type() = 0;

  // Child class implements determining type information.
  virtual void
  do_determine_type(const Type_context*) = 0;

  // Child class implements type checking if needed.
  virtual void
  do_check_types(Gogo*)
  { }

  // Child class implements copying.
  virtual Expression*
  do_copy() = 0;

  // Child class implements determining the cost of this statement for
  // inlining.  The default cost is high, so we only need to define
  // this method for expressions that can be inlined.
  virtual int
  do_inlining_cost() const
  { return 0x100000; }

  // Child class implements whether the expression is addressable.
  virtual bool
  do_is_addressable() const
  { return false; }

  // Child class implements taking the address of an expression.
  virtual void
  do_address_taken(bool)
  { }

  // Child class implements issuing a nil check if the address is taken.
  virtual void
  do_issue_nil_check()
  { }

  // Child class implements whether this expression must be evaluated
  // in order.
  virtual bool
  do_must_eval_in_order() const
  { return false; }

  // Child class implements whether this expressions requires that
  // subexpressions be evaluated in order.  The child implementation
  // may set *SKIP if it should be non-zero.
  virtual bool
  do_must_eval_subexpressions_in_order(int* /* skip */) const
  { return false; }

  // Child class implements conversion to backend representation.
  virtual Bexpression*
  do_get_backend(Translate_context*) = 0;

  // Child class implements export.
  virtual void
  do_export(Export_function_body*) const;

  // For children to call to give an error for an unused value.
  void
  unused_value_error();

  // For children to call when they detect that they are in error.
  void
  set_is_error();

  // For children to call to report an error conveniently.
  void
  report_error(const char*);

  // Child class implements dumping to a dump context.
  virtual void
  do_dump_expression(Ast_dump_context*) const = 0;

  // Varargs lowering creates a slice object (unnamed compiler temp)
  // to contain the variable length collection of values. The enum
  // below tells the lowering routine whether it can mark that temp
  // as non-escaping or not. For general varargs calls it is not always
  // safe to stack-allocated the storage, but for specific cases (ex:
  // call to append()) it is legal.
  enum Slice_storage_escape_disp
  {
    SLICE_STORAGE_MAY_ESCAPE,
    SLICE_STORAGE_DOES_NOT_ESCAPE
  };

 private:
  // Convert to the desired statement classification, or return NULL.
  // This is a controlled dynamic cast.
  template<typename Expression_class,
	   Expression_classification expr_classification>
  Expression_class*
  convert()
  {
    return (this->classification_ == expr_classification
	    ? static_cast<Expression_class*>(this)
	    : NULL);
  }

  template<typename Expression_class,
	   Expression_classification expr_classification>
  const Expression_class*
  convert() const
  {
    return (this->classification_ == expr_classification
	    ? static_cast<const Expression_class*>(this)
	    : NULL);
  }

  static Expression*
  convert_type_to_interface(Type*, Expression*, Location);

  static Expression*
  get_interface_type_descriptor(Expression*);

  static Expression*
  convert_interface_to_type(Type*, Expression*, Location);

  // The expression classification.
  Expression_classification classification_;
  // The location in the input file.
  Location location_;
};

// A list of Expressions.

class Expression_list
{
 public:
  Expression_list()
    : entries_()
  { }

  // Return whether the list is empty.
  bool
  empty() const
  { return this->entries_.empty(); }

  // Return the number of entries in the list.
  size_t
  size() const
  { return this->entries_.size(); }

  // Add an entry to the end of the list.
  void
  push_back(Expression* expr)
  { this->entries_.push_back(expr); }

  void
  append(Expression_list* add)
  { this->entries_.insert(this->entries_.end(), add->begin(), add->end()); }

  // Reserve space in the list.
  void
  reserve(size_t size)
  { this->entries_.reserve(size); }

  // Traverse the expressions in the list.
  int
  traverse(Traverse*);

  // Copy the list.
  Expression_list*
  copy();

  // Return true if the list contains an error expression.
  bool
  contains_error() const;

  // Retrieve an element by index.
  Expression*&
  at(size_t i)
  { return this->entries_.at(i); }

  // Return the first and last elements.
  Expression*&
  front()
  { return this->entries_.front(); }

  Expression*
  front() const
  { return this->entries_.front(); }

  Expression*&
  back()
  { return this->entries_.back(); }

  Expression*
  back() const
  { return this->entries_.back(); }

  // Iterators.

  typedef std::vector<Expression*>::iterator iterator;
  typedef std::vector<Expression*>::const_iterator const_iterator;

  iterator
  begin()
  { return this->entries_.begin(); }

  const_iterator
  begin() const
  { return this->entries_.begin(); }

  iterator
  end()
  { return this->entries_.end(); }

  const_iterator
  end() const
  { return this->entries_.end(); }

  // Erase an entry.
  void
  erase(iterator p)
  { this->entries_.erase(p); }

 private:
  std::vector<Expression*> entries_;
};

// An abstract base class for an expression which is only used by the
// parser, and is lowered in the lowering pass.

class Parser_expression : public Expression
{
 public:
  Parser_expression(Expression_classification classification,
		    Location location)
    : Expression(classification, location)
  { }

 protected:
  virtual Expression*
  do_lower(Gogo*, Named_object*, Statement_inserter*, int) = 0;

  Type*
  do_type();

  void
  do_determine_type(const Type_context*)
  { go_unreachable(); }

  void
  do_check_types(Gogo*)
  { go_unreachable(); }

  Bexpression*
  do_get_backend(Translate_context*)
  { go_unreachable(); }
};

// An expression which is simply a variable.

class Var_expression : public Expression
{
 public:
  Var_expression(Named_object* variable, Location location)
    : Expression(EXPRESSION_VAR_REFERENCE, location),
      variable_(variable)
  { }

  // Return the variable.
  Named_object*
  named_object() const
  { return this->variable_; }

 protected:
  Expression*
  do_lower(Gogo*, Named_object*, Statement_inserter*, int);

  Type*
  do_type();

  void
  do_determine_type(const Type_context*);

  Expression*
  do_copy()
  { return this; }

  int
  do_inlining_cost() const;

  void
  do_export(Export_function_body*) const;

  bool
  do_is_addressable() const
  { return true; }

  void
  do_address_taken(bool);

  Bexpression*
  do_get_backend(Translate_context*);

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The variable we are referencing.
  Named_object* variable_;
};

// A reference to a variable within an enclosing function.

class Enclosed_var_expression : public Expression
{
 public:
  Enclosed_var_expression(Expression* reference, Named_object* variable,
			  Location location)
    : Expression(EXPRESSION_ENCLOSED_VAR_REFERENCE, location),
      reference_(reference), variable_(variable)
  { }

  // The reference to the enclosed variable.  This will be an indirection of the
  // the field stored within closure variable.
  Expression*
  reference() const
  { return this->reference_; }

  // The variable being enclosed and referenced.
  Named_object*
  variable() const
  { return this->variable_; }

 protected:
  int
  do_traverse(Traverse*);

  Expression*
  do_lower(Gogo*, Named_object*, Statement_inserter*, int);

  Expression*
  do_flatten(Gogo*, Named_object*, Statement_inserter*);

  Type*
  do_type()
  { return this->reference_->type(); }

  void
  do_determine_type(const Type_context* context)
  { return this->reference_->determine_type(context); }

  Expression*
  do_copy()
  { return this; }

  bool
  do_is_addressable() const
  { return this->reference_->is_addressable(); }

  void
  do_address_taken(bool escapes);

  Bexpression*
  do_get_backend(Translate_context* context)
  { return this->reference_->get_backend(context); }

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The reference to the enclosed variable.
  Expression* reference_;
  // The variable being enclosed.
  Named_object* variable_;
};

// A reference to a temporary variable.

class Temporary_reference_expression : public Expression
{
 public:
  Temporary_reference_expression(Temporary_statement* statement,
				 Location location)
    : Expression(EXPRESSION_TEMPORARY_REFERENCE, location),
      statement_(statement), is_lvalue_(false)
  { }

  // The temporary that this expression refers to.
  Temporary_statement*
  statement() const
  { return this->statement_; }

  // Indicate that this reference appears on the left hand side of an
  // assignment statement.
  void
  set_is_lvalue()
  { this->is_lvalue_ = true; }

 protected:
  Type*
  do_type();

  void
  do_determine_type(const Type_context*)
  { }

  Expression*
  do_copy()
  { return make_temporary_reference(this->statement_, this->location()); }

  bool
  do_is_addressable() const
  { return true; }

  void
  do_address_taken(bool);

  Bexpression*
  do_get_backend(Translate_context*);

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The statement where the temporary variable is defined.
  Temporary_statement* statement_;
  // Whether this reference appears on the left hand side of an
  // assignment statement.
  bool is_lvalue_;
};

// Set and use a temporary variable.

class Set_and_use_temporary_expression : public Expression
{
 public:
  Set_and_use_temporary_expression(Temporary_statement* statement,
				   Expression* expr, Location location)
    : Expression(EXPRESSION_SET_AND_USE_TEMPORARY, location),
      statement_(statement), expr_(expr)
  { }

  // Return the temporary.
  Temporary_statement*
  temporary() const
  { return this->statement_; }

  // Return the expression.
  Expression*
  expression() const
  { return this->expr_; }

 protected:
  int
  do_traverse(Traverse* traverse)
  { return Expression::traverse(&this->expr_, traverse); }

  Type*
  do_type();

  void
  do_determine_type(const Type_context*);

  Expression*
  do_copy()
  {
    return make_set_and_use_temporary(this->statement_, this->expr_,
				      this->location());
  }

  bool
  do_is_addressable() const
  { return true; }

  void
  do_address_taken(bool);

  Bexpression*
  do_get_backend(Translate_context*);

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The statement where the temporary variable is defined.
  Temporary_statement* statement_;
  // The expression to assign to the temporary.
  Expression* expr_;
};

// A string expression.

class String_expression : public Expression
{
 public:
  String_expression(const std::string& val, Location location)
    : Expression(EXPRESSION_STRING, location),
      val_(val), type_(NULL)
  { }

  const std::string&
  val() const
  { return this->val_; }

  static Expression*
  do_import(Import_expression*, Location);

 protected:
  bool
  do_is_constant() const
  { return true; }

  bool
  do_is_static_initializer() const
  { return true; }

  bool
  do_string_constant_value(std::string* val) const
  {
    *val = this->val_;
    return true;
  }

  Type*
  do_type();

  void
  do_determine_type(const Type_context*);

  Expression*
  do_copy()
  { return this; }

  Bexpression*
  do_get_backend(Translate_context*);

  // Write string literal to a string dump.
  static void
  export_string(String_dump* exp, const String_expression* str);

  // Set the inlining cost a bit high since inlining may cause
  // duplicated string literals.
  int
  do_inlining_cost() const
  { return 5; }

  void
  do_export(Export_function_body*) const;

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The string value.  This is immutable.
  const std::string val_;
  // The type as determined by context.
  Type* type_;
};

// A type conversion expression.

class Type_conversion_expression : public Expression
{
 public:
  Type_conversion_expression(Type* type, Expression* expr,
			     Location location)
    : Expression(EXPRESSION_CONVERSION, location),
      type_(type), expr_(expr), may_convert_function_types_(false)
  { }

  // Return the type to which we are converting.
  Type*
  type() const
  { return this->type_; }

  // Return the expression which we are converting.
  Expression*
  expr() const
  { return this->expr_; }

  // Permit converting from one function type to another.  This is
  // used internally for method expressions.
  void
  set_may_convert_function_types()
  {
    this->may_convert_function_types_ = true;
  }

  // Import a type conversion expression.
  static Expression*
  do_import(Import_expression*, Location);

 protected:
  int
  do_traverse(Traverse* traverse);

  Expression*
  do_lower(Gogo*, Named_object*, Statement_inserter*, int);

  Expression*
  do_flatten(Gogo*, Named_object*, Statement_inserter*);

  bool
  do_is_constant() const;

  bool
  do_is_static_initializer() const;

  bool
  do_numeric_constant_value(Numeric_constant*) const;

  bool
  do_string_constant_value(std::string*) const;

  Type*
  do_type()
  { return this->type_; }

  void
  do_determine_type(const Type_context*);

  void
  do_check_types(Gogo*);

  Expression*
  do_copy();

  Bexpression*
  do_get_backend(Translate_context* context);

  int
  do_inlining_cost() const;

  void
  do_export(Export_function_body*) const;

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The type to convert to.
  Type* type_;
  // The expression to convert.
  Expression* expr_;
  // True if this is permitted to convert function types.  This is
  // used internally for method expressions.
  bool may_convert_function_types_;
};

// An unsafe type conversion, used to pass values to builtin functions.

class Unsafe_type_conversion_expression : public Expression
{
 public:
  Unsafe_type_conversion_expression(Type* type, Expression* expr,
				    Location location)
    : Expression(EXPRESSION_UNSAFE_CONVERSION, location),
      type_(type), expr_(expr)
  { }

  Expression*
  expr() const
  { return this->expr_; }

 protected:
  int
  do_traverse(Traverse* traverse);

  bool
  do_is_static_initializer() const;

  Type*
  do_type()
  { return this->type_; }

  void
  do_determine_type(const Type_context*)
  { this->expr_->determine_type_no_context(); }

  Expression*
  do_copy();

  Bexpression*
  do_get_backend(Translate_context*);

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The type to convert to.
  Type* type_;
  // The expression to convert.
  Expression* expr_;
};

// A Unary expression.

class Unary_expression : public Expression
{
 public:
  Unary_expression(Operator op, Expression* expr, Location location)
    : Expression(EXPRESSION_UNARY, location),
      op_(op), escapes_(true), create_temp_(false), is_gc_root_(false),
      is_slice_init_(false), expr_(expr),
      issue_nil_check_(NIL_CHECK_DEFAULT)
  { }

  // Return the operator.
  Operator
  op() const
  { return this->op_; }

  // Return the operand.
  Expression*
  operand() const
  { return this->expr_; }

  // Record that an address expression does not escape.
  void
  set_does_not_escape()
  {
    go_assert(this->op_ == OPERATOR_AND);
    this->escapes_ = false;
  }

  // Record that this is an address expression which should create a
  // temporary variable if necessary.  This is used for method calls.
  void
  set_create_temp()
  {
    go_assert(this->op_ == OPERATOR_AND);
    this->create_temp_ = true;
  }

  // Record that this is an address expression of a GC root, which is a
  // mutable composite literal.  This used for registering GC variables.
  void
  set_is_gc_root()
  {
    go_assert(this->op_ == OPERATOR_AND);
    this->is_gc_root_ = true;
  }

  // Record that this is an address expression of a slice value initializer,
  // which is mutable if the values are not copied to the heap.
  void
  set_is_slice_init()
  {
    go_assert(this->op_ == OPERATOR_AND);
    this->is_slice_init_ = true;
  }

  // Call the address_taken method on the operand if necessary.
  void
  check_operand_address_taken(Gogo*);

  // Apply unary opcode OP to UNC, setting NC.  Return true if this
  // could be done, false if not.  On overflow, issues an error and
  // sets *ISSUED_ERROR.
  static bool
  eval_constant(Operator op, const Numeric_constant* unc,
		Location, Numeric_constant* nc, bool *issued_error);

  static Expression*
  do_import(Import_expression*, Location);

  // Declare that this deref does or does not require an explicit nil check.
  void
  set_requires_nil_check(bool needed)
  {
    go_assert(this->op_ == OPERATOR_MULT);
    if (needed)
      this->issue_nil_check_ = NIL_CHECK_NEEDED;
    else
      this->issue_nil_check_ = NIL_CHECK_NOT_NEEDED;
  }

 protected:
  int
  do_traverse(Traverse* traverse)
  { return Expression::traverse(&this->expr_, traverse); }

  Expression*
  do_lower(Gogo*, Named_object*, Statement_inserter*, int);

  Expression*
  do_flatten(Gogo*, Named_object*, Statement_inserter*);

  bool
  do_is_constant() const;

  bool
  do_is_static_initializer() const;

  bool
  do_numeric_constant_value(Numeric_constant*) const;

  Type*
  do_type();

  void
  do_determine_type(const Type_context*);

  void
  do_check_types(Gogo*);

  Expression*
  do_copy()
  {
    return Expression::make_unary(this->op_, this->expr_->copy(),
				  this->location());
  }

  bool
  do_must_eval_subexpressions_in_order(int*) const
  { return this->op_ == OPERATOR_MULT; }

  bool
  do_is_addressable() const
  { return this->op_ == OPERATOR_MULT; }

  Bexpression*
  do_get_backend(Translate_context*);

  int
  do_inlining_cost() const
  { return 1; }

  void
  do_export(Export_function_body*) const;

  void
  do_dump_expression(Ast_dump_context*) const;

  void
  do_issue_nil_check()
  {
    if (this->op_ == OPERATOR_MULT)
      this->set_requires_nil_check(true);
  }

 private:
  static bool
  base_is_static_initializer(Expression*);

  // Return a determination as to whether this dereference expression
  // requires a nil check.
  Nil_check_classification
  requires_nil_check(Gogo*);

  // The unary operator to apply.
  Operator op_;
  // Normally true.  False if this is an address expression which does
  // not escape the current function.
  bool escapes_;
  // True if this is an address expression which should create a
  // temporary variable if necessary.
  bool create_temp_;
  // True if this is an address expression for a GC root.  A GC root is a
  // special struct composite literal that is mutable when addressed, meaning
  // it cannot be represented as an immutable_struct in the backend.
  bool is_gc_root_;
  // True if this is an address expression for a slice value with an immutable
  // initializer.  The initializer for a slice's value pointer has an array
  // type, meaning it cannot be represented as an immutable_struct in the
  // backend.
  bool is_slice_init_;
  // The operand.
  Expression* expr_;
  // Whether or not to issue a nil check for this expression if its address
  // is being taken.
  Nil_check_classification issue_nil_check_;
};

// A binary expression.

class Binary_expression : public Expression
{
 public:
  Binary_expression(Operator op, Expression* left, Expression* right,
		    Location location)
    : Expression(EXPRESSION_BINARY, location),
      op_(op), left_(left), right_(right), type_(NULL)
  { }

  // Return the operator.
  Operator
  op()
  { return this->op_; }

  // Return the left hand expression.
  Expression*
  left()
  { return this->left_; }

  // Return the right hand expression.
  Expression*
  right()
  { return this->right_; }

  // Apply binary opcode OP to LEFT_NC and RIGHT_NC, setting NC.
  // Return true if this could be done, false if not.  Issue errors at
  // LOCATION as appropriate, and sets *ISSUED_ERROR if it did.
  static bool
  eval_constant(Operator op, Numeric_constant* left_nc,
		Numeric_constant* right_nc, Location location,
		Numeric_constant* nc, bool* issued_error);

  // Compare constants LEFT_NC and RIGHT_NC according to OP, setting
  // *RESULT.  Return true if this could be done, false if not.  Issue
  // errors at LOCATION as appropriate.
  static bool
  compare_constant(Operator op, Numeric_constant* left_nc,
		   Numeric_constant* right_nc, Location location,
		   bool* result);

  static Expression*
  do_import(Import_expression*, Location);

  // Report an error if OP can not be applied to TYPE.  Return whether
  // it can.  OTYPE is the type of the other operand.
  static bool
  check_operator_type(Operator op, Type* type, Type* otype, Location);

  // Set *RESULT_TYPE to the resulting type when OP is applied to
  // operands of type LEFT_TYPE and RIGHT_TYPE.  Return true on
  // success, false on failure.
  static bool
  operation_type(Operator op, Type* left_type, Type* right_type,
		 Type** result_type);

 protected:
  int
  do_traverse(Traverse* traverse);

  Expression*
  do_lower(Gogo*, Named_object*, Statement_inserter*, int);

  Expression*
  do_flatten(Gogo*, Named_object*, Statement_inserter*);

  bool
  do_is_constant() const
  { return this->left_->is_constant() && this->right_->is_constant(); }

  bool
  do_is_static_initializer() const;

  bool
  do_numeric_constant_value(Numeric_constant*) const;

  bool
  do_discarding_value();

  Type*
  do_type();

  void
  do_determine_type(const Type_context*);

  void
  do_check_types(Gogo*);

  Expression*
  do_copy()
  {
    return Expression::make_binary(this->op_, this->left_->copy(),
				   this->right_->copy(), this->location());
  }

  Bexpression*
  do_get_backend(Translate_context*);

  int
  do_inlining_cost() const
  { return 1; }

  void
  do_export(Export_function_body*) const;

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  static bool
  cmp_to_bool(Operator op, int cmp);

  static bool
  eval_integer(Operator op, const Numeric_constant*, const Numeric_constant*,
	       Location, Numeric_constant*);

  static bool
  eval_float(Operator op, const Numeric_constant*, const Numeric_constant*,
	     Location, Numeric_constant*);

  static bool
  eval_complex(Operator op, const Numeric_constant*, const Numeric_constant*,
	       Location, Numeric_constant*);

  static bool
  compare_integer(const Numeric_constant*, const Numeric_constant*, int*);

  static bool
  compare_float(const Numeric_constant*, const Numeric_constant *, int*);

  static bool
  compare_complex(const Numeric_constant*, const Numeric_constant*, int*);

  Expression*
  lower_struct_comparison(Gogo*, Statement_inserter*);

  Expression*
  lower_array_comparison(Gogo*, Statement_inserter*);

  Expression*
  lower_interface_value_comparison(Gogo*, Statement_inserter*);

  Expression*
  lower_compare_to_memcmp(Gogo*, Statement_inserter*);

  Expression*
  operand_address(Statement_inserter*, Expression*);

  // The binary operator to apply.
  Operator op_;
  // The left hand side operand.
  Expression* left_;
  // The right hand side operand.
  Expression* right_;
  // The type of a comparison operation.
  Type* type_;
};

// A string concatenation expression.  This is a sequence of strings
// added together.  It is created when lowering Binary_expression.

class String_concat_expression : public Expression
{
 public:
  String_concat_expression(Expression_list* exprs)
    : Expression(EXPRESSION_STRING_CONCAT, exprs->front()->location()),
      exprs_(exprs)
  { }

  // Return the list of string expressions to be concatenated.
  Expression_list*
  exprs()
  { return this->exprs_; }

 protected:
  int
  do_traverse(Traverse* traverse)
  { return this->exprs_->traverse(traverse); }

  Expression*
  do_lower(Gogo*, Named_object*, Statement_inserter*, int)
  { return this; }

  Expression*
  do_flatten(Gogo*, Named_object*, Statement_inserter*);

  bool
  do_is_constant() const;

  bool
  do_is_static_initializer() const;

  Type*
  do_type();

  void
  do_determine_type(const Type_context*);

  void
  do_check_types(Gogo*);

  Expression*
  do_copy()
  { return Expression::make_string_concat(this->exprs_->copy()); }

  Bexpression*
  do_get_backend(Translate_context*)
  { go_unreachable(); }

  void
  do_export(Export_function_body*) const
  { go_unreachable(); }

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The string expressions to concatenate.
  Expression_list* exprs_;
};

// A call expression.  The go statement needs to dig inside this.

class Call_expression : public Expression
{
 public:
  Call_expression(Expression* fn, Expression_list* args, bool is_varargs,
		  Location location)
    : Expression(EXPRESSION_CALL, location),
      fn_(fn), args_(args), type_(NULL), call_(NULL), call_temp_(NULL)
    , expected_result_count_(0), is_varargs_(is_varargs),
      varargs_are_lowered_(false), types_are_determined_(false),
      is_deferred_(false), is_concurrent_(false), issued_error_(false),
      is_multi_value_arg_(false), is_flattened_(false)
  { }

  // The function to call.
  Expression*
  fn() const
  { return this->fn_; }

  // The arguments.
  Expression_list*
  args()
  { return this->args_; }

  const Expression_list*
  args() const
  { return this->args_; }

  // Get the function type.
  Function_type*
  get_function_type() const;

  // Return the number of values this call will return.
  size_t
  result_count() const;

  // Return the temporary variable that holds the results.  This is
  // only valid after the expression has been lowered, and is only
  // valid for calls which return multiple results.
  Temporary_statement*
  results() const;

  // Set the number of results expected from this call.  This is used
  // when the call appears in a context that expects multiple results,
  // such as a, b = f().
  void
  set_expected_result_count(size_t);

  // Return whether this is a call to the predeclared function
  // recover.
  bool
  is_recover_call() const;

  // Set the argument for a call to recover.
  void
  set_recover_arg(Expression*);

  // Whether the last argument is a varargs argument (f(a...)).
  bool
  is_varargs() const
  { return this->is_varargs_; }

  // Return whether varargs have already been lowered.
  bool
  varargs_are_lowered() const
  { return this->varargs_are_lowered_; }

  // Note that varargs have already been lowered.
  void
  set_varargs_are_lowered()
  { this->varargs_are_lowered_ = true; }

  // Whether this call is being deferred.
  bool
  is_deferred() const
  { return this->is_deferred_; }

  // Note that the call is being deferred.
  void
  set_is_deferred()
  { this->is_deferred_ = true; }

  // Whether this call is concurrently executed.
  bool
  is_concurrent() const
  { return this->is_concurrent_; }

  // Note that the call is concurrently executed.
  void
  set_is_concurrent()
  { this->is_concurrent_ = true; }

  // We have found an error with this call expression; return true if
  // we should report it.
  bool
  issue_error();

  // Whether or not this call contains errors, either in the call or the
  // arguments to the call.
  bool
  is_erroneous_call();

  // Whether this call returns multiple results that are used as an
  // multi-valued argument.
  bool
  is_multi_value_arg() const
  { return this->is_multi_value_arg_; }

  // Note this call is used as a multi-valued argument.
  void
  set_is_multi_value_arg()
  { this->is_multi_value_arg_ = true; }

  // Whether this is a call to builtin function.
  virtual bool
  is_builtin()
  { return false; }

  // Convert to a Builtin_call_expression, or return NULL.
  inline Builtin_call_expression*
  builtin_call_expression();

 protected:
  int
  do_traverse(Traverse*);

  virtual Expression*
  do_lower(Gogo*, Named_object*, Statement_inserter*, int);

  virtual Expression*
  do_flatten(Gogo*, Named_object*, Statement_inserter*);

  bool
  do_discarding_value()
  { return true; }

  virtual Type*
  do_type();

  virtual void
  do_determine_type(const Type_context*);

  virtual void
  do_check_types(Gogo*);

  Expression*
  do_copy();

  bool
  do_must_eval_in_order() const;

  virtual Bexpression*
  do_get_backend(Translate_context*);

  virtual bool
  do_is_recover_call() const;

  virtual void
  do_set_recover_arg(Expression*);

  // Let a builtin expression change the argument list.
  void
  set_args(Expression_list* args)
  { this->args_ = args; }

  // Let a builtin expression lower varargs.
  void
  lower_varargs(Gogo*, Named_object* function, Statement_inserter* inserter,
		Type* varargs_type, size_t param_count,
		Slice_storage_escape_disp escape_disp);

  // Let a builtin expression check whether types have been
  // determined.
  bool
  determining_types();

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  bool
  check_argument_type(int, const Type*, const Type*, Location, bool);

  Expression*
  lower_to_builtin(Named_object**, const char*, int);

  Expression*
  interface_method_function(Interface_field_reference_expression*,
			    Expression**, Location);

  Bexpression*
  set_results(Translate_context*);

  // The function to call.
  Expression* fn_;
  // The arguments to pass.  This may be NULL if there are no
  // arguments.
  Expression_list* args_;
  // The type of the expression, to avoid recomputing it.
  Type* type_;
  // The backend expression for the call, used for a call which returns a tuple.
  Bexpression* call_;
  // A temporary variable to store this call if the function returns a tuple.
  Temporary_statement* call_temp_;
  // If not 0, the number of results expected from this call, when
  // used in a context that expects multiple values.
  size_t expected_result_count_;
  // True if the last argument is a varargs argument (f(a...)).
  bool is_varargs_;
  // True if varargs have already been lowered.
  bool varargs_are_lowered_;
  // True if types have been determined.
  bool types_are_determined_;
  // True if the call is an argument to a defer statement.
  bool is_deferred_;
  // True if the call is an argument to a go statement.
  bool is_concurrent_;
  // True if we reported an error about a mismatch between call
  // results and uses.  This is to avoid producing multiple errors
  // when there are multiple Call_result_expressions.
  bool issued_error_;
  // True if this call is used as an argument that returns multiple results.
  bool is_multi_value_arg_;
  // True if this expression has already been flattened.
  bool is_flattened_;
};

// A call expression to a builtin function.

class Builtin_call_expression : public Call_expression
{
 public:
  Builtin_call_expression(Gogo* gogo, Expression* fn, Expression_list* args,
			  bool is_varargs, Location location);

  // The builtin functions.
  enum Builtin_function_code
    {
      BUILTIN_INVALID,

      // Predeclared builtin functions.
      BUILTIN_APPEND,
      BUILTIN_CAP,
      BUILTIN_CLOSE,
      BUILTIN_COMPLEX,
      BUILTIN_COPY,
      BUILTIN_DELETE,
      BUILTIN_IMAG,
      BUILTIN_LEN,
      BUILTIN_MAKE,
      BUILTIN_NEW,
      BUILTIN_PANIC,
      BUILTIN_PRINT,
      BUILTIN_PRINTLN,
      BUILTIN_REAL,
      BUILTIN_RECOVER,

      // Builtin functions from the unsafe package.
      BUILTIN_ALIGNOF,
      BUILTIN_OFFSETOF,
      BUILTIN_SIZEOF
    };

  Builtin_function_code
  code()
  { return this->code_; }

  // This overrides Call_expression::is_builtin.
  bool
  is_builtin()
  { return true; }

  // Return whether EXPR, of array type, is a constant if passed to
  // len or cap.
  static bool
  array_len_is_constant(Expression* expr);

  Expression*
  flatten_append(Gogo*, Named_object*, Statement_inserter*, Expression*,
		 Block*);

 protected:
  // This overrides Call_expression::do_lower.
  Expression*
  do_lower(Gogo*, Named_object*, Statement_inserter*, int);

  Expression*
  do_flatten(Gogo*, Named_object*, Statement_inserter*);

  bool
  do_is_constant() const;

  bool
  do_numeric_constant_value(Numeric_constant*) const;

  bool
  do_discarding_value();

  Type*
  do_type();

  void
  do_determine_type(const Type_context*);

  void
  do_check_types(Gogo*);

  Expression*
  do_copy();

  Bexpression*
  do_get_backend(Translate_context*);

  void
  do_export(Export_function_body*) const;

  virtual bool
  do_is_recover_call() const;

  virtual void
  do_set_recover_arg(Expression*);

 private:
  Expression*
  one_arg() const;

  bool
  check_one_arg();

  static Type*
  real_imag_type(Type*);

  static Type*
  complex_type(Type*);

  Expression*
  lower_make(Statement_inserter*);

  bool
  check_int_value(Expression*, bool is_length, bool* small);

  // A pointer back to the general IR structure.  This avoids a global
  // variable, or passing it around everywhere.
  Gogo* gogo_;
  // The builtin function being called.
  Builtin_function_code code_;
  // Used to stop endless loops when the length of an array uses len
  // or cap of the array itself.
  mutable bool seen_;
  // Whether the argument is set for calls to BUILTIN_RECOVER.
  bool recover_arg_is_set_;
};

inline Builtin_call_expression*
Call_expression::builtin_call_expression()
{
  return (this->is_builtin()
          ? static_cast<Builtin_call_expression*>(this)
          : NULL);
}

// A single result from a call which returns multiple results.

class Call_result_expression : public Expression
{
 public:
  Call_result_expression(Call_expression* call, unsigned int index)
    : Expression(EXPRESSION_CALL_RESULT, call->location()),
      call_(call), index_(index)
  { }

  Expression*
  call() const
  { return this->call_; }

  unsigned int
  index() const
  { return this->index_; }

 protected:
  int
  do_traverse(Traverse*);

  Type*
  do_type();

  void
  do_determine_type(const Type_context*);

  void
  do_check_types(Gogo*);

  Expression*
  do_copy()
  {
    return new Call_result_expression(this->call_->call_expression(),
				      this->index_);
  }

  bool
  do_must_eval_in_order() const
  { return true; }

  Bexpression*
  do_get_backend(Translate_context*);

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The underlying call expression.
  Expression* call_;
  // Which result we want.
  unsigned int index_;
};

// An expression which represents a pointer to a function.

class Func_expression : public Expression
{
 public:
  Func_expression(Named_object* function, Expression* closure,
		  Location location)
    : Expression(EXPRESSION_FUNC_REFERENCE, location),
      function_(function), closure_(closure),
      runtime_code_(Runtime::NUMBER_OF_FUNCTIONS)
  { }

  // Return the object associated with the function.
  Named_object*
  named_object() const
  { return this->function_; }

  // Return the closure for this function.  This will return NULL if
  // the function has no closure, which is the normal case.
  Expression*
  closure()
  { return this->closure_; }

  // Return whether this is a reference to a runtime function.
  bool
  is_runtime_function() const
  { return this->runtime_code_ != Runtime::NUMBER_OF_FUNCTIONS; }

  // Return the runtime code for this function expression.
  // Returns Runtime::NUMBER_OF_FUNCTIONS if this is not a reference to a
  // runtime function.
  Runtime::Function
  runtime_code() const
  { return this->runtime_code_; }

  // Set the runtime code for this function expression.
  void
  set_runtime_code(Runtime::Function code)
  { this->runtime_code_ = code; }

  // Return a backend expression for the code of a function.
  static Bexpression*
  get_code_pointer(Gogo*, Named_object* function, Location loc);

 protected:
  int
  do_traverse(Traverse*);

  Type*
  do_type();

  void
  do_determine_type(const Type_context*)
  {
    if (this->closure_ != NULL)
      this->closure_->determine_type_no_context();
  }

  Expression*
  do_copy()
  {
    return Expression::make_func_reference(this->function_,
					   (this->closure_ == NULL
					    ? NULL
					    : this->closure_->copy()),
					   this->location());
  }

  Bexpression*
  do_get_backend(Translate_context*);

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The function itself.
  Named_object* function_;
  // A closure.  This is normally NULL.  For a nested function, it may
  // be a struct holding pointers to all the variables referenced by
  // this function and defined in enclosing functions.
  Expression* closure_;
  // The runtime code for the referenced function.
  Runtime::Function runtime_code_;
};

// A function descriptor.  A function descriptor is a struct with a
// single field pointing to the function code.  This is used for
// functions without closures.

class Func_descriptor_expression : public Expression
{
 public:
  Func_descriptor_expression(Named_object* fn);

  // Make the function descriptor type, so that it can be converted.
  static void
  make_func_descriptor_type();

 protected:
  int
  do_traverse(Traverse*);

  Type*
  do_type();

  void
  do_determine_type(const Type_context*)
  { }

  Expression*
  do_copy()
  { return Expression::make_func_descriptor(this->fn_); }

  bool
  do_is_addressable() const
  { return true; }

  Bexpression*
  do_get_backend(Translate_context*);

  void
  do_dump_expression(Ast_dump_context* context) const;

 private:
  // The type of all function descriptors.
  static Type* descriptor_type;

  // The function for which this is the descriptor.
  Named_object* fn_;
  // The descriptor variable.
  Bvariable* dvar_;
};

// A reference to an unknown name.

class Unknown_expression : public Parser_expression
{
 public:
  Unknown_expression(Named_object* named_object, Location location)
    : Parser_expression(EXPRESSION_UNKNOWN_REFERENCE, location),
      named_object_(named_object), no_error_message_(false),
      is_composite_literal_key_(false)
  { }

  // The associated named object.
  Named_object*
  named_object() const
  { return this->named_object_; }

  // The name of the identifier which was unknown.
  const std::string&
  name() const;

  // Call this to indicate that we should not give an error if this
  // name is never defined.  This is used to avoid knock-on errors
  // during an erroneous parse.
  void
  set_no_error_message()
  { this->no_error_message_ = true; }

  // Note that this expression is being used as the key in a composite
  // literal, so it may be OK if it is not resolved.
  void
  set_is_composite_literal_key()
  { this->is_composite_literal_key_ = true; }

  // Note that this expression should no longer be treated as a
  // composite literal key.
  void
  clear_is_composite_literal_key()
  { this->is_composite_literal_key_ = false; }

 protected:
  Expression*
  do_lower(Gogo*, Named_object*, Statement_inserter*, int);

  Expression*
  do_copy()
  { return new Unknown_expression(this->named_object_, this->location()); }

  void
  do_dump_expression(Ast_dump_context*) const;
  
 private:
  // The unknown name.
  Named_object* named_object_;
  // True if we should not give errors if this is undefined.  This is
  // used if there was a parse failure.
  bool no_error_message_;
  // True if this is the key in a composite literal.
  bool is_composite_literal_key_;
};

// An index expression.  This is lowered to an array index, a string
// index, or a map index.

class Index_expression : public Parser_expression
{
 public:
  Index_expression(Expression* left, Expression* start, Expression* end,
                   Expression* cap, Location location)
    : Parser_expression(EXPRESSION_INDEX, location),
      left_(left), start_(start), end_(end), cap_(cap)
  { }

  // Dump an index expression, i.e. an expression of the form
  // expr[expr], expr[expr:expr], or expr[expr:expr:expr] to a dump context.
  static void
  dump_index_expression(Ast_dump_context*, const Expression* expr, 
                        const Expression* start, const Expression* end,
                        const Expression* cap);

 protected:
  int
  do_traverse(Traverse*);

  Expression*
  do_lower(Gogo*, Named_object*, Statement_inserter*, int);

  Expression*
  do_copy()
  {
    return new Index_expression(this->left_->copy(), this->start_->copy(),
				(this->end_ == NULL
				 ? NULL
				 : this->end_->copy()),
				(this->cap_ == NULL
				 ? NULL
				 : this->cap_->copy()),
				this->location());
  }

  // This shouldn't be called--we don't know yet.
  bool
  do_must_eval_subexpressions_in_order(int*) const
  { go_unreachable(); }

  void
  do_dump_expression(Ast_dump_context*) const;

  void
  do_issue_nil_check()
  { this->left_->issue_nil_check(); }
 private:
  // The expression being indexed.
  Expression* left_;
  // The first index.
  Expression* start_;
  // The second index.  This is NULL for an index, non-NULL for a
  // slice.
  Expression* end_;
  // The capacity argument.  This is NULL for indices and slices that use the
  // default capacity, non-NULL for indices and slices that specify the
  // capacity.
  Expression* cap_;
};

// An array index.  This is used for both indexing and slicing.

class Array_index_expression : public Expression
{
 public:
  Array_index_expression(Expression* array, Expression* start,
			 Expression* end, Expression* cap, Location location)
    : Expression(EXPRESSION_ARRAY_INDEX, location),
      array_(array), start_(start), end_(end), cap_(cap), type_(NULL),
      is_lvalue_(false)
  { }

  // Return the array.
  Expression*
  array()
  { return this->array_; }

  const Expression*
  array() const
  { return this->array_; }

  // Return the index of a simple index expression, or the start index
  // of a slice expression.
  Expression*
  start()
  { return this->start_; }

  const Expression*
  start() const
  { return this->start_; }

  // Return the end index of a slice expression.  This is NULL for a
  // simple index expression.
  Expression*
  end()
  { return this->end_; }

  const Expression*
  end() const
  { return this->end_; }

  // Return whether this array index expression appears in an lvalue
  // (left hand side of assignment) context.
  bool
  is_lvalue() const
  { return this->is_lvalue_; }

  // Update this array index expression to indicate that it appears
  // in a left-hand-side or lvalue context.
  void
  set_is_lvalue()
  { this->is_lvalue_ = true; }

 protected:
  int
  do_traverse(Traverse*);

  Expression*
  do_flatten(Gogo*, Named_object*, Statement_inserter*);

  Type*
  do_type();

  void
  do_determine_type(const Type_context*);

  void
  do_check_types(Gogo*);

  Expression*
  do_copy()
  {
    return Expression::make_array_index(this->array_->copy(),
					this->start_->copy(),
					(this->end_ == NULL
					 ? NULL
					 : this->end_->copy()),
					(this->cap_ == NULL
					 ? NULL
					 : this->cap_->copy()),
					this->location());
  }

  bool
  do_must_eval_subexpressions_in_order(int* skip) const;

  bool
  do_is_addressable() const;

  void
  do_address_taken(bool escapes);

  void
  do_issue_nil_check()
  { this->array_->issue_nil_check(); }

  Bexpression*
  do_get_backend(Translate_context*);

  void
  do_dump_expression(Ast_dump_context*) const;
  
 private:
  // The array we are getting a value from.
  Expression* array_;
  // The start or only index.
  Expression* start_;
  // The end index of a slice.  This may be NULL for a simple array
  // index, or it may be a nil expression for the length of the array.
  Expression* end_;
  // The capacity argument of a slice.  This may be NULL for an array index or
  // slice.
  Expression* cap_;
  // The type of the expression.
  Type* type_;
  // Whether expr appears in an lvalue context.
  bool is_lvalue_;
};

// A string index.  This is used for both indexing and slicing.

class String_index_expression : public Expression
{
 public:
  String_index_expression(Expression* string, Expression* start,
			  Expression* end, Location location)
    : Expression(EXPRESSION_STRING_INDEX, location),
      string_(string), start_(start), end_(end)
  { }

  // Return the string being indexed.
  Expression*
  string() const
  { return this->string_; }

 protected:
  int
  do_traverse(Traverse*);

  Expression*
  do_flatten(Gogo*, Named_object*, Statement_inserter*);

  Type*
  do_type();

  void
  do_determine_type(const Type_context*);

  void
  do_check_types(Gogo*);

  Expression*
  do_copy()
  {
    return Expression::make_string_index(this->string_->copy(),
					 this->start_->copy(),
					 (this->end_ == NULL
					  ? NULL
					  : this->end_->copy()),
					 this->location());
  }

  bool
  do_must_eval_subexpressions_in_order(int*) const
  { return true; }

  Bexpression*
  do_get_backend(Translate_context*);

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The string we are getting a value from.
  Expression* string_;
  // The start or only index.
  Expression* start_;
  // The end index of a slice.  This may be NULL for a single index,
  // or it may be a nil expression for the length of the string.
  Expression* end_;
};

// An index into a map.

class Map_index_expression : public Expression
{
 public:
  Map_index_expression(Expression* map, Expression* index,
		       Location location)
    : Expression(EXPRESSION_MAP_INDEX, location),
      map_(map), index_(index), value_pointer_(NULL)
  { }

  // Return the map.
  Expression*
  map()
  { return this->map_; }

  const Expression*
  map() const
  { return this->map_; }

  // Return the index.
  Expression*
  index()
  { return this->index_; }

  const Expression*
  index() const
  { return this->index_; }

  // Get the type of the map being indexed.
  Map_type*
  get_map_type() const;

  // Return an expression for the map index.  This returns an
  // expression that evaluates to a pointer to a value in the map.  If
  // the key is not present in the map, this will return a pointer to
  // the zero value.
  Expression*
  get_value_pointer(Gogo*);

 protected:
  int
  do_traverse(Traverse*);

  Expression*
  do_flatten(Gogo*, Named_object*, Statement_inserter*);

  Type*
  do_type();

  void
  do_determine_type(const Type_context*);

  void
  do_check_types(Gogo*);

  Expression*
  do_copy()
  {
    return Expression::make_map_index(this->map_->copy(),
				      this->index_->copy(),
				      this->location());
  }

  bool
  do_must_eval_subexpressions_in_order(int*) const
  { return true; }

  // A map index expression is an lvalue but it is not addressable.

  Bexpression*
  do_get_backend(Translate_context*);

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The map we are looking into.
  Expression* map_;
  // The index.
  Expression* index_;
  // A pointer to the value at this index.
  Expression* value_pointer_;
};

// An expression which represents a method bound to its first
// argument.

class Bound_method_expression : public Expression
{
 public:
  Bound_method_expression(Expression* expr, const Method *method,
			  Named_object* function, Location location)
    : Expression(EXPRESSION_BOUND_METHOD, location),
      expr_(expr), expr_type_(NULL), method_(method), function_(function)
  { }

  // Return the object which is the first argument.
  Expression*
  first_argument()
  { return this->expr_; }

  // Return the implicit type of the first argument.  This will be
  // non-NULL when using a method from an anonymous field without
  // using an explicit stub.
  Type*
  first_argument_type() const
  { return this->expr_type_; }

  // Return the method.
  const Method*
  method() const
  { return this->method_; }

  // Return the function to call.
  Named_object*
  function() const
  { return this->function_; }

  // Set the implicit type of the expression.
  void
  set_first_argument_type(Type* type)
  { this->expr_type_ = type; }

  // Create a thunk to call FUNCTION, for METHOD, when it is used as
  // part of a method value.
  static Named_object*
  create_thunk(Gogo*, const Method* method, Named_object* function);

 protected:
  int
  do_traverse(Traverse*);

  Expression*
  do_flatten(Gogo*, Named_object*, Statement_inserter*);

  Type*
  do_type();

  void
  do_determine_type(const Type_context*);

  void
  do_check_types(Gogo*);

  Expression*
  do_copy()
  {
    return new Bound_method_expression(this->expr_->copy(), this->method_,
				       this->function_, this->location());
  }

  Bexpression*
  do_get_backend(Translate_context*)
  { go_unreachable(); }

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // A mapping from method functions to the thunks we have created for
  // them.
  typedef Unordered_map(Named_object*, Named_object*) Method_value_thunks;
  static Method_value_thunks method_value_thunks;

  // The object used to find the method.  This is passed to the method
  // as the first argument.
  Expression* expr_;
  // The implicit type of the object to pass to the method.  This is
  // NULL in the normal case, non-NULL when using a method from an
  // anonymous field which does not require a stub.
  Type* expr_type_;
  // The method.
  const Method* method_;
  // The function to call.  This is not the same as
  // method_->named_object() when the method has a stub.  This will be
  // the real function rather than the stub.
  Named_object* function_;
};

// A reference to a field in a struct.

class Field_reference_expression : public Expression
{
 public:
  Field_reference_expression(Expression* expr, unsigned int field_index,
			     Location location)
    : Expression(EXPRESSION_FIELD_REFERENCE, location),
      expr_(expr), field_index_(field_index), implicit_(false), called_fieldtrack_(false)
  { }

  // Return the struct expression.
  Expression*
  expr() const
  { return this->expr_; }

  // Return the field index.
  unsigned int
  field_index() const
  { return this->field_index_; }

  // Return whether this node was implied by an anonymous field.
  bool
  implicit() const
  { return this->implicit_; }

  void
  set_implicit(bool implicit)
  { this->implicit_ = implicit; }

  // Set the struct expression.  This is used when parsing.
  void
  set_struct_expression(Expression* expr)
  {
    go_assert(this->expr_ == NULL);
    this->expr_ = expr;
  }

 protected:
  int
  do_traverse(Traverse* traverse)
  { return Expression::traverse(&this->expr_, traverse); }

  Expression*
  do_lower(Gogo*, Named_object*, Statement_inserter*, int);

  Type*
  do_type();

  void
  do_determine_type(const Type_context*)
  { this->expr_->determine_type_no_context(); }

  void
  do_check_types(Gogo*);

  Expression*
  do_copy()
  {
    return Expression::make_field_reference(this->expr_->copy(),
					    this->field_index_,
					    this->location());
  }

  bool
  do_is_addressable() const
  { return this->expr_->is_addressable(); }

  void
  do_address_taken(bool escapes)
  { this->expr_->address_taken(escapes); }

  void
  do_issue_nil_check()
  { this->expr_->issue_nil_check(); }

  Bexpression*
  do_get_backend(Translate_context*);

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The expression we are looking into.  This should have a type of
  // struct.
  Expression* expr_;
  // The zero-based index of the field we are retrieving.
  unsigned int field_index_;
  // Whether this node was emitted implicitly for an embedded field,
  // that is, expr_ is not the expr_ of the original user node.
  bool implicit_;
  // Whether we have already emitted a fieldtrack call.
  bool called_fieldtrack_;
};

// A reference to a field of an interface.

class Interface_field_reference_expression : public Expression
{
 public:
  Interface_field_reference_expression(Expression* expr,
				       const std::string& name,
				       Location location)
    : Expression(EXPRESSION_INTERFACE_FIELD_REFERENCE, location),
      expr_(expr), name_(name)
  { }

  // Return the expression for the interface object.
  Expression*
  expr()
  { return this->expr_; }

  // Return the name of the method to call.
  const std::string&
  name() const
  { return this->name_; }

  // Create a thunk to call the method NAME in TYPE when it is used as
  // part of a method value.
  static Named_object*
  create_thunk(Gogo*, Interface_type* type, const std::string& name);

  // Return an expression for the pointer to the function to call.
  Expression*
  get_function();

  // Return an expression for the first argument to pass to the interface
  // function.  This is the real object associated with the interface object.
  Expression*
  get_underlying_object();

 protected:
  int
  do_traverse(Traverse* traverse);

  Expression*
  do_flatten(Gogo*, Named_object*, Statement_inserter*);

  Type*
  do_type();

  void
  do_determine_type(const Type_context*);

  void
  do_check_types(Gogo*);

  Expression*
  do_copy()
  {
    return Expression::make_interface_field_reference(this->expr_->copy(),
						      this->name_,
						      this->location());
  }

  Bexpression*
  do_get_backend(Translate_context*);

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // A mapping from interface types to a list of thunks we have
  // created for methods.
  typedef std::vector<std::pair<std::string, Named_object*> > Method_thunks;
  typedef Unordered_map(Interface_type*, Method_thunks*)
    Interface_method_thunks;
  static Interface_method_thunks interface_method_thunks;

  // The expression for the interface object.  This should have a type
  // of interface or pointer to interface.
  Expression* expr_;
  // The field we are retrieving--the name of the method.
  std::string name_;
};

// Implement the builtin function new.

class Allocation_expression : public Expression
{
 public:
  Allocation_expression(Type* type, Location location)
    : Expression(EXPRESSION_ALLOCATION, location),
      type_(type), allocate_on_stack_(false)
  { }

  void
  set_allocate_on_stack()
  { this->allocate_on_stack_ = true; }

 protected:
  int
  do_traverse(Traverse*);

  Type*
  do_type();

  void
  do_determine_type(const Type_context*)
  { }

  void
  do_check_types(Gogo*);

  Expression*
  do_copy();

  Bexpression*
  do_get_backend(Translate_context*);

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The type we are allocating.
  Type* type_;
  // Whether or not this is a stack allocation.
  bool allocate_on_stack_;
};

// A general composite literal.  This is lowered to a type specific
// version.

class Composite_literal_expression : public Parser_expression
{
 public:
  Composite_literal_expression(Type* type, int depth, bool has_keys,
			       Expression_list* vals, bool all_are_names,
			       Location location)
    : Parser_expression(EXPRESSION_COMPOSITE_LITERAL, location),
      type_(type), depth_(depth), vals_(vals), has_keys_(has_keys),
      all_are_names_(all_are_names), key_path_(std::vector<bool>(depth))
  {}


  // Mark the DEPTH entry of KEY_PATH as containing a key.
  void
  update_key_path(size_t depth)
  {
    go_assert(depth < this->key_path_.size());
    this->key_path_[depth] = true;
  }

 protected:
  int
  do_traverse(Traverse* traverse);

  Expression*
  do_lower(Gogo*, Named_object*, Statement_inserter*, int);

  Expression*
  do_copy();

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  Expression*
  lower_struct(Gogo*, Type*);

  Expression*
  lower_array(Type*);

  Expression*
  make_array(Type*, const std::vector<unsigned long>*, Expression_list*);

  Expression*
  lower_map(Gogo*, Named_object*, Statement_inserter*, Type*);

  // The type of the composite literal.
  Type* type_;
  // The depth within a list of composite literals within a composite
  // literal, when the type is omitted.
  int depth_;
  // The values to put in the composite literal.
  Expression_list* vals_;
  // If this is true, then VALS_ is a list of pairs: a key and a
  // value.  In an array initializer, a missing key will be NULL.
  bool has_keys_;
  // If this is true, then HAS_KEYS_ is true, and every key is a
  // simple identifier.
  bool all_are_names_;
  // A complement to DEPTH that indicates for each level starting from 0 to
  // DEPTH-1 whether or not this composite literal is nested inside of key or
  // a value.  This is used to decide which type to use when given a map literal
  // with omitted key types.
  std::vector<bool> key_path_;
};

// Helper/mixin class for struct and array construction expressions;
// encapsulates a list of values plus an optional traversal order
// recording the order in which the values should be visited.

class Ordered_value_list
{
 public:
  Ordered_value_list(Expression_list* vals)
      : vals_(vals), traverse_order_(NULL)
  { }

  Expression_list*
  vals() const
  { return this->vals_; }

  int
  traverse_vals(Traverse* traverse);

  // Get the traversal order (may be NULL)
  std::vector<unsigned long>*
  traverse_order()
  { return traverse_order_; }

  // Set the traversal order, used to ensure that we implement the
  // order of evaluation rules.  Takes ownership of the argument.
  void
  set_traverse_order(std::vector<unsigned long>* traverse_order)
  { this->traverse_order_ = traverse_order; }

 private:
  // The list of values, in order of the fields in the struct or in
  // order of indices in an array. A NULL value of vals_ means that
  // all fields/slots should be zero-initialized; a single NULL entry
  // in the list means that the corresponding field or array slot
  // should be zero-initialized.
  Expression_list* vals_;
  // If not NULL, the order in which to traverse vals_.  This is used
  // so that we implement the order of evaluation rules correctly.
  std::vector<unsigned long>* traverse_order_;
};

// Construct a struct.

class Struct_construction_expression : public Expression,
				       public Ordered_value_list
{
 public:
  Struct_construction_expression(Type* type, Expression_list* vals,
				 Location location)
      : Expression(EXPRESSION_STRUCT_CONSTRUCTION, location),
	Ordered_value_list(vals),
	type_(type)
  { }

 // Return whether this is a constant initializer.
  bool
  is_constant_struct() const;

 protected:
  int
  do_traverse(Traverse* traverse);

  bool
  do_is_static_initializer() const;

  Type*
  do_type()
  { return this->type_; }

  void
  do_determine_type(const Type_context*);

  void
  do_check_types(Gogo*);

  Expression*
  do_copy();

  Expression*
  do_flatten(Gogo*, Named_object*, Statement_inserter*);

  Bexpression*
  do_get_backend(Translate_context*);

  void
  do_export(Export_function_body*) const;

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The type of the struct to construct.
  Type* type_;
};

// Construct an array.  This class is not used directly; instead we
// use the child classes, Fixed_array_construction_expression and
// Slice_construction_expression.

class Array_construction_expression : public Expression,
				      public Ordered_value_list
{
 protected:
  Array_construction_expression(Expression_classification classification,
				Type* type,
				const std::vector<unsigned long>* indexes,
				Expression_list* vals, Location location)
    : Expression(classification, location),
      Ordered_value_list(vals),
      type_(type), indexes_(indexes)
  { go_assert(indexes == NULL || indexes->size() == vals->size()); }

 public:
  // Return whether this is a constant initializer.
  bool
  is_constant_array() const;

  // Return the number of elements.
  size_t
  element_count() const
  { return this->vals() == NULL ? 0 : this->vals()->size(); }

protected:
  virtual int
  do_traverse(Traverse* traverse);

  bool
  do_is_static_initializer() const;

  Type*
  do_type()
  { return this->type_; }

  void
  do_determine_type(const Type_context*);

  void
  do_check_types(Gogo*);

  void
  do_export(Export_function_body*) const;

  // The indexes.
  const std::vector<unsigned long>*
  indexes()
  { return this->indexes_; }

  Expression*
  do_flatten(Gogo*, Named_object*, Statement_inserter*);

  // Get the backend constructor for the array values.
  Bexpression*
  get_constructor(Translate_context* context, Btype* btype);

  void
  do_dump_expression(Ast_dump_context*) const;

  virtual void
  dump_slice_storage_expression(Ast_dump_context*) const { }

 private:
  // The type of the array to construct.
  Type* type_;
  // The list of indexes into the array, one for each value.  This may
  // be NULL, in which case the indexes start at zero and increment.
  const std::vector<unsigned long>* indexes_;
};

// Construct a fixed array.

class Fixed_array_construction_expression :
  public Array_construction_expression
{
 public:
  Fixed_array_construction_expression(Type* type,
				      const std::vector<unsigned long>* indexes,
				      Expression_list* vals, Location location);

 protected:
  Expression*
  do_copy();

  Bexpression*
  do_get_backend(Translate_context*);
};

// Construct a slice.

class Slice_construction_expression : public Array_construction_expression
{
 public:
  Slice_construction_expression(Type* type,
				const std::vector<unsigned long>* indexes,
				Expression_list* vals, Location location);

  Expression*
  do_flatten(Gogo*, Named_object*, Statement_inserter*);

  // Record that the storage for this slice (e.g. vals) cannot escape,
  // hence it can be stack-allocated.
  void
  set_storage_does_not_escape()
  {
    this->storage_escapes_ = false;
  }

 protected:
  // Note that taking the address of a slice literal is invalid.

  int
  do_traverse(Traverse* traverse);

  Expression*
  do_copy();

  Bexpression*
  do_get_backend(Translate_context*);

  void
  dump_slice_storage_expression(Ast_dump_context* ast_dump_context) const;

  // Create an array value for the constructed slice. Invoked during
  // flattening if slice storage does not escape, otherwise invoked
  // later on during do_get_backend().
  Expression*
  create_array_val();

 private:
  // The type of the values in this slice.
  Type* valtype_;
  // Array value expression, optionally filled in during flattening.
  Expression* array_val_;
  // Slice storage expression, optionally filled in during flattening.
  Expression* slice_storage_;
  // Normally true. Can be set to false if we know that the resulting
  // storage for the slice cannot escape.
  bool storage_escapes_;
};

// Construct a map.

class Map_construction_expression : public Expression
{
 public:
  Map_construction_expression(Type* type, Expression_list* vals,
			      Location location)
    : Expression(EXPRESSION_MAP_CONSTRUCTION, location),
      type_(type), vals_(vals), element_type_(NULL), constructor_temp_(NULL)
  { go_assert(vals == NULL || vals->size() % 2 == 0); }

  Expression_list*
  vals() const
  { return this->vals_; }

 protected:
  int
  do_traverse(Traverse* traverse);

  Expression*
  do_flatten(Gogo*, Named_object*, Statement_inserter*);

  Type*
  do_type()
  { return this->type_; }

  void
  do_determine_type(const Type_context*);

  void
  do_check_types(Gogo*);

  Expression*
  do_copy();

  Bexpression*
  do_get_backend(Translate_context*);

  void
  do_export(Export_function_body*) const;

  void
  do_dump_expression(Ast_dump_context*) const;
  
 private:
  // The type of the map to construct.
  Type* type_;
  // The list of values.
  Expression_list* vals_;
  // The type of the key-value pair struct for each map element.
  Struct_type* element_type_;
  // A temporary reference to the variable storing the constructor initializer.
  Temporary_statement* constructor_temp_;
};

// A type guard expression.

class Type_guard_expression : public Expression
{
 public:
  Type_guard_expression(Expression* expr, Type* type, Location location)
    : Expression(EXPRESSION_TYPE_GUARD, location),
      expr_(expr), type_(type)
  { }

  // Return the expression to convert.
  Expression*
  expr()
  { return this->expr_; }

  // Return the type to which to convert.
  Type*
  type()
  { return this->type_; }

 protected:
  int
  do_traverse(Traverse* traverse);

  Expression*
  do_flatten(Gogo*, Named_object*, Statement_inserter*);

  Type*
  do_type()
  { return this->type_; }

  void
  do_determine_type(const Type_context*)
  { this->expr_->determine_type_no_context(); }

  void
  do_check_types(Gogo*);

  Expression*
  do_copy();

  Bexpression*
  do_get_backend(Translate_context*);

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The expression to convert.
  Expression* expr_;
  // The type to which to convert.
  Type* type_;
};

// Class Heap_expression.

// When you take the address of an escaping expression, it is allocated
// on the heap.  This class implements that.

class Heap_expression : public Expression
{
 public:
  Heap_expression(Expression* expr, Location location)
    : Expression(EXPRESSION_HEAP, location),
      expr_(expr), allocate_on_stack_(false)
  { }

  Expression*
  expr() const
  { return this->expr_; }

  void
  set_allocate_on_stack()
  { this->allocate_on_stack_ = true; }

 protected:
  int
  do_traverse(Traverse* traverse)
  { return Expression::traverse(&this->expr_, traverse); }

  Type*
  do_type();
  void
  do_determine_type(const Type_context*)
  { this->expr_->determine_type_no_context(); }

  Expression*
  do_copy()
  {
    return Expression::make_heap_expression(this->expr_->copy(),
                                            this->location());
  }

  Bexpression*
  do_get_backend(Translate_context*);

  // We only export global objects, and the parser does not generate
  // this in global scope.
  void
  do_export(Export_function_body*) const
  { go_unreachable(); }

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The expression which is being put on the heap.
  Expression* expr_;
  // Whether or not this is a stack allocation.
  bool allocate_on_stack_;
};

// A receive expression.

class Receive_expression : public Expression
{
 public:
  Receive_expression(Expression* channel, Location location)
    : Expression(EXPRESSION_RECEIVE, location),
      channel_(channel), temp_receiver_(NULL)
  { }

  // Return the channel.
  Expression*
  channel()
  { return this->channel_; }

 protected:
  int
  do_traverse(Traverse* traverse)
  { return Expression::traverse(&this->channel_, traverse); }

  bool
  do_discarding_value()
  { return true; }

  Type*
  do_type();

  Expression*
  do_flatten(Gogo*, Named_object*, Statement_inserter*);

  void
  do_determine_type(const Type_context*)
  { this->channel_->determine_type_no_context(); }

  void
  do_check_types(Gogo*);

  Expression*
  do_copy()
  {
    return Expression::make_receive(this->channel_->copy(), this->location());
  }

  bool
  do_must_eval_in_order() const
  { return true; }

  Bexpression*
  do_get_backend(Translate_context*);

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The channel from which we are receiving.
  Expression* channel_;
  // A temporary reference to the variable storing the received data.
  Temporary_statement* temp_receiver_;
};

// An expression that represents a slice value: a struct with value pointer,
// length, and capacity fields.

class Slice_value_expression : public Expression
{
 public:
  Slice_value_expression(Type* type, Expression* valmem, Expression* len,
                         Expression* cap, Location location)
    : Expression(EXPRESSION_SLICE_VALUE, location),
      type_(type), valmem_(valmem), len_(len), cap_(cap)
  { }

  // The memory holding the values in the slice.  The type should be a
  // pointer to the element value of the slice.
  Expression*
  valmem() const
  { return this->valmem_; }

 protected:
  int
  do_traverse(Traverse*);

  Type*
  do_type()
  { return this->type_; }

  void
  do_determine_type(const Type_context*)
  { }

  Expression*
  do_copy();

  Bexpression*
  do_get_backend(Translate_context* context);

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The type of the slice value.
  Type* type_;
  // The memory holding the values in the slice.
  Expression* valmem_;
  // The length of the slice.
  Expression* len_;
  // The capacity of the slice.
  Expression* cap_;
};

// 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)
  {}

  Expression*
  condition() const
  { return this->cond_; }

 protected:
  int
  do_traverse(Traverse*);

  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());
  }

  Bexpression*
  do_get_backend(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_;
};

// Compound expressions.

class Compound_expression : public Expression
{
 public:
  Compound_expression(Expression* init, Expression* expr, Location location)
      : Expression(EXPRESSION_COMPOUND, location), init_(init), expr_(expr)
  {}

  Expression*
  init() const
  { return this->init_; }

 protected:
  int
  do_traverse(Traverse*);

  Type*
  do_type();

  void
  do_determine_type(const Type_context*);

  Expression*
  do_copy()
  {
    return new Compound_expression(this->init_->copy(), this->expr_->copy(),
                                   this->location());
  }

  Bexpression*
  do_get_backend(Translate_context* context);

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The expression that is evaluated first and discarded.
  Expression* init_;
  // The expression that is evaluated and returned.
  Expression* expr_;
};

// A backend expression.  This is a backend expression wrapped in an
// Expression, for convenience during backend generation.

class Backend_expression : public Expression
{
 public:
  Backend_expression(Bexpression* bexpr, Type* type, Location location)
    : Expression(EXPRESSION_BACKEND, location), bexpr_(bexpr), type_(type)
  {}

 protected:
  int
  do_traverse(Traverse*);

  // For now these are always valid static initializers.  If that
  // changes we can change this.
  bool
  do_is_static_initializer() const
  { return true; }

  Type*
  do_type()
  { return this->type_; }

  void
  do_determine_type(const Type_context*)
  { }

  Expression*
  do_copy();

  Bexpression*
  do_get_backend(Translate_context*)
  { return this->bexpr_; }

  void
  do_dump_expression(Ast_dump_context*) const;

 private:
  // The backend expression we are wrapping.
  Bexpression* bexpr_;
  // The type of the expression;
  Type* type_;
};

// A numeric constant.  This is used both for untyped constants and
// for constants that have a type.

class Numeric_constant
{
 public:
  Numeric_constant()
    : classification_(NC_INVALID), type_(NULL)
  { }

  ~Numeric_constant();

  Numeric_constant(const Numeric_constant&);

  Numeric_constant& operator=(const Numeric_constant&);

  // Set to an unsigned long value.
  void
  set_unsigned_long(Type*, unsigned long);

  // Set to an integer value.
  void
  set_int(Type*, const mpz_t);

  // Set to a rune value.
  void
  set_rune(Type*, const mpz_t);

  // Set to a floating point value.
  void
  set_float(Type*, const mpfr_t);

  // Set to a complex value.
  void
  set_complex(Type*, const mpc_t);

  // Mark numeric constant as invalid.
  void
  set_invalid()
  { this->classification_ = NC_INVALID; }

  // Classifiers.
  bool
  is_int() const
  { return this->classification_ == Numeric_constant::NC_INT; }

  bool
  is_rune() const
  { return this->classification_ == Numeric_constant::NC_RUNE; }

  bool
  is_float() const
  { return this->classification_ == Numeric_constant::NC_FLOAT; }

  bool
  is_complex() const
  { return this->classification_ == Numeric_constant::NC_COMPLEX; }

  bool
  is_invalid() const
  { return this->classification_ == Numeric_constant::NC_INVALID; }

  // Value retrievers.  These will initialize the values as well as
  // set them.  GET_INT is only valid if IS_INT returns true, and
  // likewise respectively.
  void
  get_int(mpz_t*) const;

  void
  get_rune(mpz_t*) const;

  void
  get_float(mpfr_t*) const;

  void
  get_complex(mpc_t*) const;

  // Codes returned by to_unsigned_long.
  enum To_unsigned_long
  {
    // Value is integer and fits in unsigned long.
    NC_UL_VALID,
    // Value is not integer.
    NC_UL_NOTINT,
    // Value is integer but is negative.
    NC_UL_NEGATIVE,
    // Value is non-negative integer but does not fit in unsigned
    // long.
    NC_UL_BIG
  };

  // If the value can be expressed as an integer that fits in an
  // unsigned long, set *VAL and return NC_UL_VALID.  Otherwise return
  // one of the other To_unsigned_long codes.
  To_unsigned_long
  to_unsigned_long(unsigned long* val) const;

  // If the value can be expressed as an integer that describes the
  // size of an object in memory, set *VAL and return true.
  // Otherwise, return false.  Currently we use int64_t to represent a
  // memory size, as in Type::backend_type_size.
  bool
  to_memory_size(int64_t* val) const;

  // If the value can be expressed as an int, return true and
  // initialize and set VAL.  This will return false for a value with
  // an explicit float or complex type, even if the value is integral.
  bool
  to_int(mpz_t* val) const;

  // If the value can be expressed as a float, return true and
  // initialize and set VAL.
  bool
  to_float(mpfr_t* val) const;

  // If the value can be expressed as a complex, return true and
  // initialize and set VR and VI.
  bool
  to_complex(mpc_t* val) const;

  // Get the type.
  Type*
  type() const;

  // If the constant can be expressed in TYPE, then set the type of
  // the constant to TYPE and return true.  Otherwise return false,
  // and, if ISSUE_ERROR is true, issue an error message.  LOCATION is
  // the location to use for the error.
  bool
  set_type(Type* type, bool issue_error, Location location);

  // Return an Expression for this value.
  Expression*
  expression(Location) const;

 private:
  void
  clear();

  To_unsigned_long
  mpz_to_unsigned_long(const mpz_t ival, unsigned long *val) const;

  To_unsigned_long
  mpfr_to_unsigned_long(const mpfr_t fval, unsigned long *val) const;

  bool
  mpz_to_memory_size(const mpz_t ival, int64_t* val) const;

  bool
  mpfr_to_memory_size(const mpfr_t fval, int64_t* val) const;

  bool
  check_int_type(Integer_type*, bool, Location);

  bool
  check_float_type(Float_type*, bool, Location);

  bool
  check_complex_type(Complex_type*, bool, Location);

  static bool
  is_float_neg_zero(const mpfr_t, int bits);

  // The kinds of constants.
  enum Classification
  {
    NC_INVALID,
    NC_RUNE,
    NC_INT,
    NC_FLOAT,
    NC_COMPLEX
  };

  // The kind of constant.
  Classification classification_;
  // The value.
  union
  {
    // If NC_INT or NC_RUNE.
    mpz_t int_val;
    // If NC_FLOAT.
    mpfr_t float_val;
    // If NC_COMPLEX.
    mpc_t complex_val;
  } u_;
  // The type if there is one.  This will be NULL for an untyped
  // constant.
  Type* type_;
};

#endif // !defined(GO_EXPRESSIONS_H)
