Description
This issue describes the current status of the runtime representation of ReScript constructs in JS.
Most constructs map cleanly to JS with some exceptions:
- variants e.g.
D(1,2)
are represented as{TAG: /* D */1, _0: 1, _1: 2}
. - curried functions e.g. a type
(int, int)=>int
could be a function with 2 args, or a function with 1 arg returning a function with 1 arg.
One implication is that these representations can be cumbersome to use from JS.
Another implication is the type correspondence with genType, where in order to get a clean mapping, a runtime conversion needs to be performed. Sometimes that conversion is simply missing even with genType, e.g. in recursive types with variants where an appropriate recursive function would need to be generated. (See issues about genType and linked lists).
If one could have clean representations, then FFI would be simpler, and typed FFI with genType would require no runtime whatsoever #6099. A further implication is that one could try to move towards just generating .d.ts
files, which fit much more naturally in a TS project.
The obstacles to cleaning up the remaining cases are the following:
- For curried functions, the existence of curried functions is itself an issue. Uncurried mode gets around those issues. It means every function is uncurried. Explicit partial application is also supported. Cleanup uncurried #6080
- For variants, two aspects are involved. First of course, one would need to change the code emitter. Second, pattern matching would need to be adapted. Make variant pattern matching not rely on tags being int #6085 Introduce untagged variants. #6103
For example:
switch x {
| A => 10
| B | C | D => 0
| E => 10
}
generates
if (x > 3 || x < 1) {
return 10;
} else {
return 0;
}
as it relies on the fact that tags are numeric values (and is not obvious to the user how it maps to the source program).