Пример #1
0
// Perform the usual arithmetic conversions on `e1` and `e2`. This
// tries to find a common type for `e1` and `e2` and convert both
// expressions to that type.
//
// NOTE: In C++ lvalue-to-rvalue conversions are required on a
// per-expression basis, independently of converting to a common
// type. Also, non-user-defined types are unqualified prior to
// analysis. It would be easier if we found an absolute common
// type and then instantiated a declaration suitable for overload
// resolution. Maybe.
//
// TODO: Handle conversions for character types (or promote to a
// corresponding integer type?).
//
// TODO: How does bool work with this set of conversions? Promote
// bool to int?
//
// TODO: Can we unify this with the common type required by the
// conditional expression? Note that the arithmetic version converts
// to values, and the conditional expression can retain references.
Expr_pair
arithmetic_conversions(Context& cxt, Expr& e1, Expr& e2)
{
  // If the types are the same, no conversions are applied.
  if (is_equivalent(e1.type(), e2.type()))
    return {e1, e2};

  // If either operand has floating point type, convert to the type
  // with the greatest precision.
  //
  // TODO: Why isn't convert_to_common_float symmetric? This seems like
  // an issue.
  if (has_floating_point_type(e1))
    return convert_to_common_float(cxt, e2, e1);
  if (has_floating_point_type(e2))
    return convert_to_common_float(cxt, e1, e2);

  // If both operands have integer type, the following rules apply.
  if (has_integer_type(e1) && has_integer_type(e2))
    return convert_to_common_int(cxt, e1, e2);

  // TODO: No conversion from e1 to e2.
  error(cxt, "no usual arithmetic conversion of '{}' and '{}'", e1, e2);
  throw Type_error();
}
Пример #2
0
// Assuming the type of e1 is untested and e2 has floating point
// type, convert to the most precise floating point type.
Expr_pair
convert_to_common_float(Context& cxt, Expr& e1, Expr& e2)
{
  Float_type& f2 = cast<Float_type>(e2.type());

  // If e1 has float type, convert to the most precise type.
  if (has_floating_point_type(e1)) {
    Float_type& f1 = cast<Float_type>(e1.type());
    if (f1.precision() < f2.precision()) {
      Expr& c = convert_to_wider_float(cxt, e1, f2);
      return {c, e2};
    }
    if (f2.precision() < f1.precision()) {
      Expr& c = convert_to_wider_float(cxt, e2, f1);
      return {e1, c};
    }
    lingo_unreachable();
  }

  // If e1 has integer type, convert to e2.
  if (has_integer_type(e1)) {
    Expr& c = convert_integer_to_float(cxt, e1, f2);
    return {c, e2};
  }

  error(cxt, "no floating point conversions for '{}' and '{}'", e1, e2);
  throw Type_error();
}
Пример #3
0
// Perform the usual arithmetic conversions on `e1` and `e2`. This
// tries to find a common type for `e1` and `e2` and convert both
// expressions to that type.
//
// NOTE: In C++ lvalue-to-rvalue conversions are required on a
// per-expression basis, independently of converting to a common
// type. Also, non-user-defined types are unqualified prior to
// analysis. It would be easier if we found an absolute common
// type and then instantiated a declaration suitable for overload
// resolution. Maybe.
//
// TODO: Handle conversions for character types (or promote to a
// corresponding integer type?).
//
// TODO: How does bool work with this set of conversions? Promote
// bool to int?
//
// TODO: Can we unify this with the common type required by the
// conditional expression? Note that the arithmetic version converts
// to values, and the conditional expression can retain references.
Expr_pair
arithmetic_conversion(Expr& e1, Expr& e2)
{
  // If the types are the same, no conversions are applied.
  if (is_equivalent(e1.type(), e2.type()))
    return {e1, e2};

  // If either operand has floating point type, convert to the type
  // with the greatest precision.
  if (has_floating_point_type(e1))
    return convert_to_common_float(e2, e1);
  if (has_floating_point_type(e2))
    return convert_to_common_float(e1, e2);

  // If both oerands have integer type, the following rules apply.
  if (has_integer_type(e1) && has_integer_type(e2))
    return convert_to_common_int(e1, e2);

  // TODO: No conversion from e1 to e2.
  throw std::runtime_error("incompatible types");
}
Пример #4
0
// Assuming the type of e1 is untested and e2 has floating point
// type, convert to the most precise floating point type.
Expr_pair
convert_to_common_float(Expr& e1, Expr& e2)
{
  Float_type& f2 = cast<Float_type>(e2.type());

  // If e1 has float type, convert to the most precise.
  if (has_floating_point_type(e1)) {
    Float_type& f1 = cast<Float_type>(e1.type());
    if (f1.precision() < f2.precision())
      return {convert_to_wider_float(e1, f2), e2};
    if (f2.precision() < f1.precision())
      return {e1, convert_to_wider_float(e2, f1)};
  }

  // If e1 has integer type, convert to e2.
  if (has_integer_type(e1)) {
    return {convert_integer_to_float(e1, f2), e2};
  }

  throw std::runtime_error("incompatible types");
}