Skip to content

Commit

Permalink
Merge branch 'es2016-proxies'
Browse files Browse the repository at this point in the history
Closes #3
  • Loading branch information
IgnoredAmbience committed Sep 10, 2018
2 parents acc2e70 + 5b8b3a5 commit e54dd0e
Show file tree
Hide file tree
Showing 37 changed files with 1,266 additions and 504 deletions.
4 changes: 0 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
_build
*.byte
*.native
stdlib_ml/stdlib.cmi
stdlib_ml/stdlib.cmo
.ocamldebug

2 changes: 2 additions & 0 deletions .merlin
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
REC
B _build
PKG str
PKG compiler-libs.common
PKG ocaml-migrate-parsetree
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ all: byte native stdlib
byte: $(addsuffix .byte,$(EXECUTABLES))
native: $(addsuffix .native,$(EXECUTABLES))

test: byte stdlib
$(MAKE) -C tests test

stdlib:
$(MAKE) -C $(STDLIB_DIR)

Expand All @@ -27,6 +30,7 @@ clean:
ocamlbuild -clean
bash -c "rm -f .ocamldebug"
$(MAKE) -C $(STDLIB_DIR) clean
$(MAKE) -C tests clean

.PHONY: default all byte native stdlib debug clean

Expand Down
123 changes: 123 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Js\_of\_ocaml bis ("The Generator")
## Why bis? & Purpose
Because, there is already a tool named `js_of_ocaml` whose job is
to produce efficient Javascript from OCaml bytecode. We are not that tool.

Here, we try to translate OCaml syntax to 'simple' ECMAScript syntax, the
purpose of it is to generate readable ECMAScript code, so that it
could later be use in a step-by-step ECMAScript interpreter.

## Dependencies
See parent directory.

## What is built
* **main**: The main ml-to-js compiler. Can produce files in one of 5 modes,
using the `-mode` parameter:
* `log`: Executable JS output with logging function calls for use with the
debugger.
* `unlog`: Plain executable JS output
* `token`: Produces `unlog` annotated with token identifiers for `log`. And
produces an `.mlloc.js` file mapping token identifiers to locations of the
input `.ml` source file.
* `pseudo`: 'Pseudo'-js output. Makes use of monadic let bindings alike the
input OCaml to improve readability.
* `ptoken`: `token` equivalent for `pseudo` output files.
* **lineof**: Converts and combines `.token.js`, `.ptoken.js`, and `.mlloc.js`
files into `lineof.js` which maps token identifiers to file locations.
* **assembly**: Linker for compiled `.log.js` files into a single executable
`.js` file.
* **displayed_sources**: Produces string versions of the relevant source
files, for display.
* **monad_ppx**: PPX rewriter for monadic binder extension syntax. See below.

Each of these programs may be compiled to a bytecode or native target as
desired. Bytecode is the default.

### Makefile Targets
The following `make` targets are defined:
* `default`: Compiles bytecode versions of the programs and the stdlib.
* `all`: Compiles bytecode and native versions of the programs and the stdlib.
* `byte` / `native`: Compiles bytecode or native versions of the programs.
* \*`.byte` / \*`.native`: Compiles the specified program into bytecode or
native code.
* `debug`: Compiles bytecode versions of the programs with debug symbols, and
the appropriate `.ocamldebug` configuration file.
* `test`: Compiles and executes the test suite. See below.
* `clean`: Cleans built targets.

## How does it work?
In order to get the statically typed abstract syntax tree (STAST) of OCaml we
link against compiler-libs, we have tested against versions 4.04.0. Previous
versions are available for >= 4.02.1.

On top, of this STAST, there is a custom back-end that compiles OCaml to
ECMAScript. The code written in OCaml cannot rely on code from the typical
standard library. Therefore a file named `stdlib.mli` (found in the directory
`stdlib_ml`) contains all the required definitions for the examples to work.
This file as a twin which is `stdlib.js`, in this file the functions whose
prototype is in `stdlib.mli` are defined here.

## About the subset of OCaml supported
* **Let** declarations, except `let () =`. Recursive declarations are
supported.
* **If then else** statements, as expected `if then else` expressions return a
value.
* **Pattern matching**, only one level of pattern matching over arbitrary
types.
* **Type declarations**, if a constructor take arguments (one or more), you
should add an annotations to provide default names for the parameters. See
example below.
```ocaml
type 'a tree = | Leaf of 'a [@f value] | Node of 'a
tree * 'a * 'a tree [@f left, value, right]
```
* **Records** Records are translated to objects. Record copying using the
OCaml `with` syntax is supported for any number of field updates.

## About the Subset of JavaScript Used
* Object.assign (ES6)
* No type casting
* No prototypes
* Arrays (for tuples)
* Switch on strings (used for type constructor matching)
* `with` as a simplistic means of linking module definitions.

## About the Monadic Rewriter PPX
This is a OCaml AST preprocessor that converts `let%x` syntax into the
monadic binder `if_x` with the continuation as the bound expression of the
let term.

For example:
* `let%some x = expr in cont``if_some expr (fun x -> cont)`
* `let%spec (s,x) = expr in cont``if_spec expr (fun s x -> cont)`

The full list of available monads is provided in the file
[`monadic_binder_list.ml`](./monadic_binder_list.ml). This file should be
configured as appropriate for the target application. The current
configuration is for jsref.

## Test Suite
The `tests` directory contains test files for the generator to compile. Test
cases will first be built and run with the standard OCaml compiler to check
that the assertions made within the tests are correct. The tests are then
compiled with the generator and executed with Nodejs to ensure that the
compiled versions are also correct. Cross-checking of results is not
performed, it is expected that all tests should pass under both execution
environments.

The test case library interface is described in
(tests/lib/mocha.mli)[./tests/lib/mocha.mli], it is designed to be similar in
style to the Mocha JS testing framework. The JS test environment is backed
directly by Mocha, the OCaml test environment is Alcotest with a wrapper to
provide a Mocha interface.

Tests are built and executed using the `make test` command in this directory.

## Other Notes
Historical versions of the repository required the OCaml 4.02.1 compiler
source code to compile directly against. We are unable to redistribute
these files for licensing reasons. If for some reason you want to build a
historic version, then drop the parsing, typing and utils directories from
the OCaml distribution into this directory, some further configuration may
be required... The whole historic distribution archived in the private
jscert\_dev repository.
111 changes: 0 additions & 111 deletions README.org

This file was deleted.

10 changes: 1 addition & 9 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,18 @@
=> inline the definition of "if_ter" inside its body
and assign an explicit name to the local function there

*) remove Coq_value_prim (flatten the value data type)


*) make sure the "reach condition" works properly

*) clean up the ML code for: type_compare mutability_compare prim_compare;
for prim_compare, we should be able to match on pairs of arguments, with a catch-all

*) move prim_compare and value_compare to JsInterpreter because it is interesting and should be logged;
move same_value_dec from jscommonaux

*) bigger test262 testing.

*) Flag to force esprima to parse in strict mode

*) put online the tool on the jscert website
*) put online the tool on the jscert website (DONE, needs below:)
- make sure to describe the supported features
(ecma5 minus for-in and a few other things)
- explain that currently JS files are generated
Expand Down Expand Up @@ -58,10 +54,6 @@

*) find out how to have syntax highlighting

*) make sure to document that if doing "make" before "make init",
then it is needed to do a "make clean" before compilation may work.


*) in pseudo_code
- hide or change these:
- var%void _ = // hide
Expand Down
Loading

0 comments on commit e54dd0e

Please sign in to comment.