You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/OCaml-call-JS.md
+192-5Lines changed: 192 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,3 +1,143 @@
1
+
To make OCaml work smoothly with Javascript, we introduced several
2
+
extensions to OCaml language. Those BuckleScript extensions
3
+
facilitates the integration of native JavaScript code as well as
4
+
improve the generated code.
5
+
6
+
> Note that all those extension will be correctly ignored by the native OCaml compiler.
7
+
8
+
9
+
## Embedding raw Javascript code
10
+
11
+
- extension `bs.raw`
12
+
13
+
It can be either `[%bs.raw{| this_is_arbitrary_js_expression |}]` or `[%%bs.raw{| this is arbitrary_js_statement |}`
14
+
15
+
Use cases:
16
+
for example if you want to use a JavaScript string, you can write code like this
17
+
18
+
```OCaml
19
+
let x : string = [%bs.raw{|"\x01\x02"|}]
20
+
```
21
+
22
+
which will be compiled into
23
+
24
+
```js
25
+
var x ="\x01\x02"
26
+
```
27
+
28
+
```OCaml
29
+
[%%bs.raw{|
30
+
// Math.imul polyfill
31
+
if (!Math.imul){
32
+
Math.imul = function (..) {..}
33
+
}
34
+
|}]
35
+
```
36
+
In the expression level, i.e, `[%bs.raw ...]` user can add a type annotation, the compiler would use such type annotation to deduce its arities. for example, the next three versions:
37
+
38
+
```ocaml
39
+
let f = [%bs.raw ("Math.max" : float -> float -> float) ] 3.0
40
+
let f : float -> float -> float = [%bs.raw "Math.max" ] 3.0
41
+
let f = ([%bs.raw "Math.max"] : float -> float -> float ) 3.0
42
+
```
43
+
will be translated into
44
+
45
+
```js
46
+
functionf(prim){
47
+
returnMath.max(3.0,prim);
48
+
}
49
+
```
50
+
Caveat:
51
+
1. So far we don't do any sanity check in the quoted text (syntax check is a long-term goal)
52
+
2. You should not refer symbols in OCaml code, it is not guaranteed that the order is correct.
53
+
You should avoid introducing new symbols in the raw code, if needed, use the `$$` prefix (ie `$$your_func_name`)
54
+
55
+
## Debugger support
56
+
57
+
- extension `bs.debugger`
58
+
59
+
It can be `[%bs.debugger]`
60
+
61
+
use case
62
+
63
+
```ocaml
64
+
let f x y =
65
+
[%bs.debugger];
66
+
x + y
67
+
```
68
+
69
+
which will be compiled into
70
+
71
+
```js
72
+
functionf (x,y) {
73
+
debugger; // JavaScript developer tools will set an breakpoint and stop here
74
+
x + y;
75
+
}
76
+
```
77
+
78
+
## Native uncurried calling convention support
79
+
80
+
Note that OCaml's calling convention is curried by default, while JS
81
+
does not have native support. Curried and uncurried functions can be
82
+
told from type signatures.
83
+
84
+
For example
85
+
86
+
```ocaml
87
+
val f : int -> string -> int
88
+
val f_uncurry : int * string -> int [@uncurry]
89
+
```
90
+
91
+
92
+
93
+
- How BuckleScript compiles function application
94
+
95
+
To apply a function, you can do this
96
+
97
+
```ocaml
98
+
f 3 "x"
99
+
f_uncurry #@ (3,"x")
100
+
```
101
+
For uncurried function applicaton, BuckleScript is guaranteed to
102
+
compile it in the same way as JS code
103
+
104
+
```js
105
+
f_uncurry(3,"x")
106
+
```
107
+
108
+
However, for curried function application, it depends on how compiler
109
+
optimizations goes, for most cases, when the compiler see the
110
+
definition of `f`, it will compile it in the most efficient way, i.e,
111
+
JS full aplication, if the compiler can not see the definition of `f`,
112
+
it will do a runtime dispath, so there are two possible outputs:
113
+
114
+
```js
115
+
Curry._2(f, 3, "x") // compiler fails to optimize
116
+
f(3, "x") // compiler optimized correctly
117
+
```
118
+
Both are correct code, but the second one is more efficient.
119
+
120
+
- How BuckleScript handles function definition
121
+
122
+
```ocaml
123
+
let f = fun a b -> a + string_of_int b
124
+
let f_uncurry = fun %uncurry a b -> a + string_of_int b
125
+
```
126
+
127
+
- When is uncurried function recommended
128
+
129
+
1. For FFI to JS functions, all object methods are *strongly recommended*
130
+
to type it as uncurried function
131
+
132
+
133
+
134
+
2. When function is passed as a callback
135
+
136
+
This is mostly for performance issues, it is hard to optimize in
137
+
such scenario
138
+
139
+
140
+
1
141
2
142
## FFI to js functions
3
143
@@ -151,8 +291,8 @@ gives it a type and customized attributes
0 commit comments