intended semantics of Scalar

While trying to use Scalar in my code, I've found some oddities.

In particular, binary promotion does a bitwise reinterpretation of an
integer when promoting to a floating point type.

This was easy enough to fix, for most cases, but it caused more

* What are the intended semantics of operations like Float and Double?
  For example, I tried to write a unit test for this but I am not sure
  if it is correct:

      int a2 = 23;
      Scalar a2_scalar(a2);
      ASSERT_EQ((float)a2, a2_scalar.Float());
      ASSERT_EQ((double)a2, a2_scalar.Double());

  The current code here also does bitwise reinterpretation.

  This comment appears in Scalar.h but I did not find it much clearer:

  // Returns a casted value of the current contained data without
  // modifying the current value. FAIL_VALUE will be returned if the type
  // of the value is void or invalid.

* What is the intended difference between the Cast and Promote methods?
  These don't have comments.

* Are the 128- and 256-bit integers expected to participate in binary
  promotion the same way that other ints do? If so then it seems to me
  that other parts of the code are also incorrect, for example in

      if (lhs_type > rhs_type) { [...]

  This will cause Scalar to attempt to promote floating point types to
  these wide integer types; but that doesn't seem correct to me. There
  may be more such problems, I did not check exhaustively.


It was initially intended to mimic the C promotion rules when doing expressions. The scalar values are used in a lot of place, but most importantly in the DWARF expression parser. Can't remember if the AST expression parser uses them as well when expressions are simple enough.

Basically we want the class to behave like C/C++ expressions, when to do something like:

auto result = 22 + 3.2

we want "result" to match if we used Scalar objects.

Promote is used to promote a type during an expression. In the above example "22" should be promoted to a matching float type as "22.0". If your expression was:

int result = 22 + 3.2

I would think we would use "Cast" to chase the "22.0" to 22. There don't seem to be any callers (at least that is what Xcode says) to the Scalar::Cast(...) function, so it could be removed.

It used to be that Scalar just contained integers up to uint64_t, but later this code was converted to use llvm::APIInt and llvm::APFloat classes. Not sure if that is when bugs crept it. But that should give us the ability to use any size integers IIRC.

Basically, I would be happy if the Scalar class can automatically do what C/C++ expression would do with similar types. That should make it easy to find errors and to unit test as the test can be:

auto result = 22 + 3.2;
Scalar a(22);
Scalar b(3.2);
c = a + b;
verify(c == result);