Skip to content

Commit b925254

Browse files
ryyppymununki
authored andcommitted
Playground 2022 (rescript-lang#5375)
* Add all relevant changes from previous 2020 bundle API For reference on the previous work in 2020, refer to rescript-lang#4518 * Add ninja rule for building jsoo_refmt_main * Fix formatting edge-cases when formatting ReScript -> ReScript Configure the parser to pass forPrinter:true when parsing / printing ReScript. This fixes issues where e.g. Some((1, 2)) get misprinted to Some(1,2) etc. Relevant bug reports: - rescript-lang/syntax#274 - rescript-lang/syntax#265 * Introduce initial type hints in playground bundle results * Adapt playground to newest internal syntax apis * Make jsoo_refmt_main work again by removing refmt * Rename jsoo_refmt_main to jsoo_playground_main * Move jsoo_playground_main to jscomp/main * Remove irrelevant code * Remove Refmt_api * Make repl.js more reliable with missing .mli files * repl.js: Log target compiler file, set js_playground_main as default * Update CONTRIBUTING to align with the renamed playground jsoo entrypoint Co-authored-by: Patrick Stapfer <ryyppy@users.noreply.github.com>
1 parent fb6d001 commit b925254

11 files changed

+780
-158702
lines changed

CONTRIBUTING.md

+25-34
Original file line numberDiff line numberDiff line change
@@ -209,43 +209,38 @@ This is usually the file you want to create to test certain compile behavior wit
209209
- Verify the output, check in the `jscomp/test/my_file_test.ml` and `jscomp/test/my_file_test.js` to version control. The checked in `.js` file is essential for verifying regressions later on.
210210
- Eventually check in other relevant files changed during the rebuild (depends on your compiler changes).
211211

212-
## Contribute to the BS Playground Bundle
212+
## Contribute to the ReScript Playground Bundle
213213

214214
> Note: These instructions are designed for building the 4.06 based version of ReScript (ReScript v6).
215215
216-
The "Playground bundle" is the BS compiler compiled to JavaScript, including all necessary dependency files (stdlib / belt etc). It is useful for building tools where you want to compile and execute arbitrary Reason / OCaml in the browser.
216+
The "Playground bundle" is a JS version of the ReScript compiler; including all necessary dependency files (stdlib / belt etc). It is useful for building tools where you want to compile and execute arbitrary ReScript code in the browser.
217217

218-
The ReScript source code is compiled with a tool called [JSOO (js_of_ocaml)](https://ocsigen.org/js_of_ocaml/3.5.1/manual/overview), which uses OCaml bytecode to compile to JavaScript and is part of the bigger OCaml ecosystem. Before we can compile anything, we need to install the required tools (requires [`opam`](https://opam.ocaml.org/doc/Install.html) to be installed):
218+
The ReScript source code is compiled with a tool called [JSOO (js_of_ocaml)](https://ocsigen.org/js_of_ocaml/4.0.0/manual/overview), which uses OCaml bytecode to compile to JavaScript and is part of the bigger OCaml ecosystem.
219219

220-
```sh
221-
# Create the right switch, if not created yet (first install)
222-
opam switch create 4.06.1
223-
224-
# Makes sure to be on the right switch
225-
opam switch 4.06.1
226-
eval `opam config env`
220+
Install `jsoo` via `opam`:
227221

228-
opam install js_of_ocaml.3.5.1
222+
```sh
223+
opam install js_of_ocaml.4.0.0
229224
```
230225

231-
### Build the Bundle
226+
### Building the Bundle
232227

233-
The entry point of the JSOO bundle is located in `jscomp/main/jsoo_main.ml` and the script for running JSOO can be found in `scripts/repl.js`. A full clean build can be done like this:
228+
The entry point of the JSOO bundle is located in `jscomp/main/jsoo_playground_main.ml`, the code for packing the compiler into a single compiler file is located in `jscomp/snapshot.ninja`, and the script for running JSOO can be found in `scripts/repl.js`. A full clean build can be done like this:
234229

235230
```
236231
# We create a target directory for storing the bundle / stdlib files
237232
mkdir playground && mkdir playground/stdlib
238233
239-
# We build the ReScript source code and also the bytecode for jsoo_main.ml
234+
# We build the ReScript source code and also the bytecode for the JSOO entrypoint
240235
node scripts/ninja.js config && node scripts/ninja.js build
241236
242237
# Now we run the repl.js script pointing to our playground directory (note how it needs to be relative to the repl.js file)
243-
BS_PLAYGROUND=../playground node scripts/repl.js
238+
PLAYGROUND=../playground node scripts/repl.js
244239
```
245240

246241
_Troubleshooting: if ninja build step failed with `Error: cannot find file '+runtime.js'`, make sure `ocamlfind` is installed with `opam install ocamlfind`._
247242

248-
**You should now find following files:**
243+
After a successful compilation, you will find following files in your project:
249244

250245
- `playground/exports.js` -> This is the ReScript compiler, which binds the ReScript API to the `window` object.
251246
- `playground/stdlib/*.js` -> All the ReScript runtime files.
@@ -255,44 +250,40 @@ You can now use the `exports.js` file either directly by using a `<script src="/
255250
```
256251
$ node
257252
> require("./exports.js");
258-
undefined
259-
> let compile_result = ocaml.compile(`Js.log Sys.ocaml_version`); // You can change the code here
260-
undefined
261-
> eval(compile_result);
253+
> let compiler = rescript_compiler.make()
254+
> let result = compiler.rescript.compile(`Js.log(Sys.ocaml_version)`);
255+
> eval(result.js_code);
262256
4.06.2+BS
263-
undefined
264257
```
265258

266259
### Playground JS bundle API
267260

268-
As soon as the bundle is loaded, you will get access to following functions (as seen in [`jsoo_main.ml`](jscomp/main/jsoo_main.ml)):
261+
As soon as the bundle is loaded, you will get access to the functions exposed in [`jsoo_playground_main.ml`](jscomp/main/jsoo_playground_main.ml). Best way to check out the API is by inspecting a compiler instance it either in node, or in the browser:
269262

270-
- `window.ocaml`:
271-
- `compile(code: string)`: Compiles given code
272-
- `shake_compile(code: string)`: Compiles given code with tree-shaking
273-
- `compile_super_errors(code: string)`: Compiles given code and outputs `super_errors` related messages on `console.error`
274-
- `compile_super_errors_ppx_v2(code: string)`: Compiles given code with the React v2 syntax
275-
- `compile_super_errors_ppx_v3(code: string)`: Compiles given code with the React v3 syntax
276-
- `load_module(cmi_path: string, cmi_content: string, cmj_name: string, cmj_content: string)`: Loads a module into the compiler (see notes on `cmj` / `cmi` below)
263+
```
264+
$ node
265+
require('./exports.js')
277266
278-
For each compile every successful operation will return `{js_code: string}`. On compile errors, the returned object will be `{js_error_msg: string}`.
267+
> let compiler = rescript_compiler.make()
268+
> console.log(compiler)
269+
```
279270

280271
### Working on the Playground JS API
281272

282-
Whenever you are modifying any files in the ReScript compiler, or in the `jsoo_main.ml` file, you'll need to rebuild the source and recreate the JS bundle.
273+
Whenever you are modifying any files in the ReScript compiler, or in the `jsoo_playground_main.ml` file, you'll need to rebuild the source and recreate the JS bundle.
283274

284275
```sh
285276
node scripts/ninja.js config && node scripts/ninja.js build
286-
BS_PLAYGROUND=../playground node scripts/repl.js
277+
PLAYGROUND=../playground node scripts/repl.js
287278
```
288279

289280
**.cmj files in the Web**
290281

291-
A `.cmj` file contains compile information and JS package information of ReScript build artifacts (your `.re / .ml` modules) and are generated on build (`scripts/ninja.js build`).
282+
A `.cmj` file contains compile information and JS package information of ReScript build artifacts (your `.res / .ml` modules) and are generated on build (`scripts/ninja.js build`).
292283

293284
A `.cmi` file is an [OCaml originated file extension](https://waleedkhan.name/blog/ocaml-file-extensions/) and contains all interface information of a certain module without any implementation.
294285

295-
In this repo, these files usually sit right next to each compiled `.ml` / `.re` file. The structure of a `.cmj` file is defined in [js_cmj_format.ml](jscomp/core/js_cmj_format.ml). You can run a tool called `./jscomp/bin/cmjdump.exe [some-file.cmj]` to inspect the contents of given `.cmj` file.
286+
In this repo, these files usually sit right next to each compiled `.ml` / `.res` file. The structure of a `.cmj` file is defined in [js_cmj_format.ml](jscomp/core/js_cmj_format.ml). You can run a tool called `./jscomp/bin/cmjdump.exe [some-file.cmj]` to inspect the contents of given `.cmj` file.
296287

297288
`.cmj` files are required for making ReScript compile modules (this includes modules like ReasonReact). ReScript includes a subset of modules by default, which can be found in `jscomp/stdlib-406` and `jscomp/others`. You can also find those modules listed in the `jsoo` call in `scripts/repl.js`. As you probably noticed, the generated `playground` files are all plain `.js`, so how are the `cmj` / `cmi` files embedded?
298289

jscomp/main/jsoo_common.ml

+10
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@ module Js = struct
3838
external create_file : js_string t -> js_string t -> unit = "caml_create_file"
3939

4040
external to_bytestring : js_string t -> string = "caml_js_to_byte_string"
41+
42+
type number
43+
44+
external number_of_float : float -> number t = "caml_js_from_float"
45+
46+
external bool : bool -> bool t = "caml_js_from_bool"
47+
48+
type 'a js_array
49+
50+
external array : 'a array -> 'a js_array t = "caml_js_from_array"
4151
end
4252

4353
let mk_js_error (loc : Location.t) (msg : string) =

jscomp/main/jsoo_common.mli

+10
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ module Js : sig
4141
external create_file : js_string t -> js_string t -> unit = "caml_create_file"
4242

4343
external to_bytestring : js_string t -> string = "caml_js_to_byte_string"
44+
45+
type number
46+
47+
external number_of_float : float -> number t = "caml_js_from_float"
48+
49+
external bool : bool -> bool t = "caml_js_from_bool"
50+
51+
type 'a js_array
52+
53+
external array : 'a array -> 'a js_array t = "caml_js_from_array"
4454
end
4555

4656
(*

0 commit comments

Comments
 (0)