Skip to content

Latest commit

 

History

History
190 lines (139 loc) · 3.89 KB

Runtime-representation.adoc

File metadata and controls

190 lines (139 loc) · 3.89 KB

Runtime representation

Below is a description of how OCaml values are encoded in JavaScript, the internal description means users should not rely on its actual encoding (and it is subject to change). We recommend that you write setter/getter functions to manipulate safely OCaml values from JavaScript.

For example, users should not rely on how OCaml list is encoded in JavaScript; instead, the OCaml stdlib provides three functions: List.cons, List.hd and List.tl. JavaScript code should only rely on those three functions.

Simple OCaml type

ocaml type JavaScript type

int

number

nativeint

number

int32

number

float

number

bool

number

  • true → 1

  • false → 0

int64

Array of size two numbers [hi,lo]. hi is signed while lo is unsigned

char

number

for example:

  • 'a' → 97

string

string

bytes

number array

Note
We might encode it as buffer in NodeJS.

'a array

Array

record

Array internal

For instance:

type t = { x : int; y : int }
let v = {x = 1; y = 2}

Output:

var v = [1,2]

tuple

Array

For example:

  • (3,4) → [3,4]

’a option

internal

For example:

  • None0

  • Some a[a]

list

internal

For example:

  • []0

  • x::y[x,y]

  • 1::2::[3][ 1, [ 2, [ 3, 0 ] ] ]

Variant

internal (subject to change)

Simple Variants: (Variants with only one non-nullary constructor)

type tree =
  | Leaf
  | Node of int * tree * tree
(* Leaf --> 0 *)
(* Node(a,b,c) --> [a,b,c]*)

Complex Variants: (Variants with more than one non-nullary constructor)

type u =
     | A of string
     | B of int
(* A a --> [a].tag=0 -- tag 0 assignment is optional *)
(* B b --> [b].tag=1 *)

Polymorphic variant

internal

`a (* 97 *)
`a 1 2 (* [97, [1,2] ]*)

exception

internal

extension

internal

object

internal

Js.boolean

boolean

For example:

  • Js.true_ → true

  • Js.false_ → false

Js module
type boolean
val to_bool: boolean -> bool
Js.Boolean module
val to_js_boolean: bool -> Js.boolean

'a Js.Null.t

Either 'a or null. Js.Null.empty represents null too.

Js.Null module
val to_opt : 'a t -> 'a option
val from_opt : 'a option -> 'a t
val return : 'a -> 'a t
val test : 'a t -> bool

'a Js.Undefined.t

Either 'a or undefined. Same operations as 'a Js.Null.t. Js.Undefined.empty represents undefined too.

'a Js.Null_undefined.t

Either 'a, null or undefined. Same operations as 'a Js.Null.t.

Js.Null_undefined.undefined represents undefined, Js.Null_undefined.null represents null.

This module’s null tests check for both null and undefined; if you know the value’s only ever going to be null and not undefined, use Js.Null instead. Likewise for Js.Undefined.

Note
Js.to_opt is optimized when the option is not escaped
Note
In the future, we will have a debug mode, in which the corresponding js encoding will be instrumented with more information

As we clarified before, the internal representation should not be relied upon. We are working to provide a ppx extension as below:

type t =
  | A
  | B of int * int
  | C of int * int
  | D [@@bs.deriving{export}]

So that it will a automatically provide constructing and destructing functions:

val a : t
val b : int -> int -> t
val c : int -> int -> t
val d : int

val a_of_t : t -> bool
val d_of_t : t -> bool
val b_of_t : t -> (int * int ) Js.Null.t
val c_of_t : t -> (int * int ) Js.Null.t