rescript-lang.org
rescript-lang.org copied to clipboard
Cheat sheet for annotations
Present a compact cheat sheet for decorators relevant for code generation. Here's a list of all decorators. Irrelevant ones to be removed:
- ~@@deprecated~
- ~@@warning~
- [x] @as only used for runtime representation, except for default arguments
@as("someString") _
- [email protected]~
- ~@dead~
- ~@deprecated~
- ~@deriving~ About runtime representation
- ~@doesNotRaise~
- ~@genType~
- [x] @get
- [x] @get_index
- [x] @ignore
- ~@inline~
- ~@int~ not relevant: about runtime representation
- ~@live~
- ~@meth~ About runtime representation
- [x] @module
- [x] @new
- [x] @obj
- ~@raises~
- [email protected]~
- [ ] @return This mixes runtime representation and externals: a post-processing for results
- [x] @scope
- [x] @send
- [x] @set
- [x] @set_index
- ~@string~ not relevant: about runtime representation
- [ ] @this Requires annotations on both external and uses
- ~@unboxed~ About runtime representation
- [ ] @uncurry This guarantees that the curried function is treated as if it were uncurried
- [ ] @unwrap Unwraps one level of unary polymorphci variants (e.g.
[#Int(int) | #Str(string)]
). Should probably be a language-level featureeither<(int, string)>
. - [x] @val
- [?] @variadic Should this be a language-level feature?
A few examples covered:
// @val
// external setTimeout: (unit => unit, int) => timeoutID = "setTimeout"
external setTimeout: (unit => unit, int) => timeoutID = "setTimeout($1, $2)"
// @get external getName: window => string = "name"
external getName: window => string = "$1.name"
// @set external setName: (window, string) => unit = "name"
external setName: (window, string) => unit = "$1.name = $2"
// @get_index external get: (t, string) => int = ""
external get: (t, string) => int = "$1[$2]"
// @set_index external set: (t, string, int) => unit = ""
external set: (t, string, int) => unit = "$1[$2] = $3"
// @module("path")
// external dirname: string => string = "dirname"
external dirname: string => string = "import(path).dirname($1)"
// @new external create: unit => t = "Date"
external create: unit => t = "new Date()"
// @send external getElementById: (document, string) => Dom.element = "getElementById"
external getElementById: (document, string) => Dom.element = "$1.getElementById($2)"
// @module("library-x")
// @val external doStuff: (@as(json`{format:"utf8", includeStuff: false}`) _, string) => string = "doStuff"
external doStuff: string => string = "import(library-x).doStuff({format: 'utf8', includeStuff: false}, $1)"
// @val external doSomething: (@ignore 'a, 'a) => unit = "doSomething"
external doSomething: ('a, 'a) => unit = "doSomething($2)"
// @obj
// external action: (~name: string, unit) => _ = ""
external action: (~name: string, unit) => _ = "{name:$1}"
// @scope("Math") @val
// external floor: float => int = "floor"
external floor: float => int = "Math.floor($1)"
How to describe the difference between @scope
and @module
?
I didn't know, but are the $1, $2 placeholder a thing?
Just a compact notation to describe what the examples do. But once all the uses of attributes are lined out, it might suggest a decent universal representation.
Looks like @variadic
can be moved to the language in principle e.g. little prototype: https://github.com/rescript-lang/rescript-compiler/issues/5727
So it becomes about runtime representation and not about FFI.
Just used import(-)
to mark @module
things. Just as a notation to differentiate from @scope
.
And removed @variadic
.
This gives a pretty small, self-contained set of things that can be expressed.
Since import wasn't well received, a couple of ideas for importing values from javascript:
external "path" {
dirname: string => string,
renameSync as rename: (string, string) => string,
"weird identifier" as ident: unit => unit
}
// entire module contents
external "leftPad" {
* as leftPad: (string, int) => string
}
// import default export
external "./modules/school.js" {
default as schoolName: string,
}
// or simply: (this could be too much)
external "./modules/school.js" as schoolName: string
@cristianoc is this issue about having a separate page that lists all possible constructs in one example? Or are you talking about extending our syntax lookup, that lists all the decorators already?
![image](https://user-images.githubusercontent.com/1121889/216561564-51d8f247-dec2-4dbf-b050-dc9a78a4d987.png)
@cristianoc is this issue about having a separate page that lists all possible constructs in one example? Or are you talking about extending our syntax lookup, that lists all the decorators already?
![]()
This is not necessarily about description only. It could be a different way to express FFI in future. Perhaps not super relevant for the doc site right now.
A few additional comments from discussions with folks
@val
standalone binds to globals. But in any recent JS version you wouldn’t need that anymore. There’s a global object now
I’m not sure how useful
@this
is. Binding to modern libraries that use OOP is a challenge. A mere@this
might not be enough anyway
I’m not sure
@scope
is needed because we can just special-case a few built-ins like Math and others in@module