unisonweb / unison

A friendly programming language from the future
https://unison-lang.org
Other
5.77k stars 268 forks source link

Char.toNat & Char.fromNat aren't casts in the chez or racket runtime, but are codegenning as such #3805

Open jaredly opened 1 year ago

jaredly commented 1 year ago

Unison considers conversion between char and nat to be a simple cast

https://github.com/unisonweb/unison/blob/bba24cd2425ef15ca6c43d656c4eea2a78a26e32/parser-typechecker/src/Unison/Runtime/Builtin.hs#L1998-L1999

Because of this, the generated chez code for Char.toNat and Char.fromNat is identity.

  (define-unison
    (builtin-Char.fromNat x0)
    (identity x0))
  (define-unison
    (builtin-Char.toNat x0)
    (identity x0))

But in the chez & racket runtimes, they are considered distinct, so performing fx+ on chars results in a runtime error. (in racket, preforming unsafe-fx+ on chars results in a special #garbage value, which is also a problem).

Solutions I can see: 1) special-case these builtins in SchemeDefn.toIndentedText as I do in this draft PR 2) modify builtin.hs to indicate that, while they are treated the same by the unison / haskell runtime, they need to be explicitly converted under scheme

dolio commented 1 year ago

Here's a third option.

Right now various constructors that wrap unboxed types are designated as 'newtypes' in the scheme code emitter. This causes there to be no data wrapper around them. The point being that they're already first-class scheme objects, so they don't need to be wrapped to behave appropriately like they do in Haskell. Also, matching on the data part of a 'newtype' is a no-op. We just turn match x with N y -> ... into essentially let x = id y in ....

Char could be slightly different, where the constructor applies the Nat -> Char transformation, and unpacking applies the Char -> Nat transformation. Then these implementations work, because they are composites of an identity (un)pack and a coercing (un)pack. And also any other builtins that (un)pack a Char expecting it to contain the same unboxed stuff as a Nat will also work, although I don't know if there are any other examples.