Acknowledged
CIQQA-3581

Casting Float to Number does not yield Number

This code:

var myFloat = 5.0;
var myNumber = myFloat as Number;
var mod = myNumber % 1;

Compiles without warnings, but crashes at runtime with:

Error: Unhandled Exception
Exception: UnexpectedTypeException: Expected Number/Long, given Number/Float

As far as I can tell:

  • this behavior is undocumented
  • the types "Number/Long" and "Number/Float" are undocumented
  • the effects of casting numeric types are undocumented

Consequently I'm not sure how to characterize this bug. If it's expected, this is a documentation bug. If it's not expected, this is a runtime and/or compiler bug.

I read the relevant section on "type casting" in the SDK docs. I've reproduced the totality of the documentation on type casting here:

The as keyword can also be used in an expression to type cast a value to another type. This can be useful if the type is not clear to the type system.

This, unfortunately, does not help very much.

---

Tested on Descent G1 & G2 simulators

SDK 8.3.0

Parents
  • No worries! Like I said, Monkey Types very similar to TypeScript, which is a compile-time type-checking layer on top of JavaScript. Monkey Types is basically also a compile-time type-checking layer on top of the original Monkey C language.

    Like Monkey C, a cast in TypeScript only serves to change the type-checker's idea of what the type is, not to perform run-time type coercion. TypeScript is better in this aspect in the sense that it does give you a warning or error when you attempt to cast between unrelated types, and you have to type some additional code to tell TypeScript you *really* meant to do that. It's also better in the sense that the syntax for type declarations is completely different than the syntax for type casts.

    > It seems to be impossible to specify Double or Long literals. Instead you have to write "5.0.toDouble()" or "5.toLong()". Correct?

    Incorrect. There are examples of Long and Double literals here:

    https://developer.garmin.com/connect-iq/monkey-c/functions/ 

    var l = 5l;                 // 64-bit signed integers
    var d = 4.0d;               // 64-bit floating point

    Of course, without this syntax, it would be impossible to specify a Double literal that exceeds the precision of a Float, or a Long literal that exceeds the range of a Number. Indeed you would get a compile-time warning if you did so without the appropriate suffix

Comment
  • No worries! Like I said, Monkey Types very similar to TypeScript, which is a compile-time type-checking layer on top of JavaScript. Monkey Types is basically also a compile-time type-checking layer on top of the original Monkey C language.

    Like Monkey C, a cast in TypeScript only serves to change the type-checker's idea of what the type is, not to perform run-time type coercion. TypeScript is better in this aspect in the sense that it does give you a warning or error when you attempt to cast between unrelated types, and you have to type some additional code to tell TypeScript you *really* meant to do that. It's also better in the sense that the syntax for type declarations is completely different than the syntax for type casts.

    > It seems to be impossible to specify Double or Long literals. Instead you have to write "5.0.toDouble()" or "5.toLong()". Correct?

    Incorrect. There are examples of Long and Double literals here:

    https://developer.garmin.com/connect-iq/monkey-c/functions/ 

    var l = 5l;                 // 64-bit signed integers
    var d = 4.0d;               // 64-bit floating point

    Of course, without this syntax, it would be impossible to specify a Double literal that exceeds the precision of a Float, or a Long literal that exceeds the range of a Number. Indeed you would get a compile-time warning if you did so without the appropriate suffix

Children
No Data