Home

Awesome

JavaScript to ReasonML Transpiler

Check it out Live on GitHub Pages. Tested with:

Table of contents

Introduction

This is a helper script to port small examples from JS to ReasonML. It should be mainly for generating a baseline for externals, unless it grows to something bigger :p . Requires to actually run the code with eval because it will inspect the types for declaration at runtime. Code path coverage in example must be 100% for now (TODO: implement partial transpilation with unresolvedAnyT if requested).

Why eval and not flow? I tried flow and it wasn't able to infer much, while evaling the code gets all types without much effort. Conditional code paths may present complications though, so try to avoid them in example code, or if used you must ensure that all conditional paths are evaluated at least once for types to resolve. See "Manual labour" for more information.

I am using :

Example transpilation

Input

var app = new PIXI.Application(800, 600, { backgroundColor: 0x1099bb });
/*
console.log(app.constructor.name);
*/
document.body.appendChild(app.view);

// Scale mode for all textures, will retain pixelation
PIXI.settings.SCALE_MODE = PIXI.SCALE_MODES.NEAREST;

var sprite = PIXI.Sprite.fromImage('http://pixijs.io/examples/required/assets/basics/bunny.png');

// Set the initial position
sprite.anchor.set(0.5);
sprite.x = app.screen.width / 2;
sprite.y = app.screen.height / 2;

// Opt-in to interactivity
sprite.interactive = true;

// Shows hand cursor
sprite.buttonMode = true;

/* PS: Functions are not automatically lifted and must be in order for
 * generated script to use them correctly. */
function onClick(evt) {
  /* PS: Make sure your event handlers are called at least once by script */
  console.log(evt);
  sprite.scale.x *= 1.25;
  sprite.scale.y *= 1.25;
  return 0;
}

// Pointers normalize touch and mouse
sprite.on('pointerdown', onClick);

/* PS: Make sure your event handlers are called at least once by script, and
 * done after function passed around, like in the following line: */
onClick(new Event('test'));

// Alternatively, use the mouse & touch events:
// sprite.on('click', onClick); // mouse-only
// sprite.on('tap', onClick); // touch-only

app.stage.addChild(sprite);

if (true) {
  console.log("hello");
} else {
  console.log("blah");
}

var x = 3;

x *= 2;

Output

ReasonML syntax, reformatted with refmt.

type appApplicationT;

type appHTMLDocumentT;

type appHTMLBodyElementT;

type appHTMLCanvasElementT;

type usageFunSpriteT;

type appSpriteT;

type appObservablePointT;

type appRectangleT;

type appEventT;

type appMemoryInfoT;

type appContainerT;

type smallObject0T = {. "backgroundColor": int};

type smallObject21T = {. "RESOLUTION": int};

type smallObject42T = {
  .
  "LINEAR": int,
  "NEAREST": int
};

type smallObject65T = {. "memory": appMemoryInfoT};

type usageFunOnClickT = appEventT => int;

[@bs.new] [@bs.module "pixi.js"]
external newApplication3 : (int, int, smallObject0T) => appApplicationT =
  "Application";

[@bs.val] external document : appHTMLDocumentT = "document";

[@bs.get] external getBody : appHTMLDocumentT => appHTMLBodyElementT = "body";

[@bs.get] external getView : appApplicationT => appHTMLCanvasElementT = "view";

[@bs.send]
external appendChild1 :
  (appHTMLBodyElementT, appHTMLCanvasElementT) => appHTMLCanvasElementT =
  "appendChild";

[@bs.val] [@bs.module "pixi.js"]
external getSettings : smallObject21T = "settings";

[@bs.set]
external setSCALE_MODE : (smallObject21T, int) => unit = "SCALE_MODE";

[@bs.val] [@bs.module "pixi.js"] [@bs.scope "settings"]
external getSCALE_MODE : int = "SCALE_MODE";

[@bs.val] [@bs.module "pixi.js"]
external getSCALE_MODES : smallObject42T = "SCALE_MODES";

[@bs.val] [@bs.module "pixi.js"] [@bs.scope "SCALE_MODES"]
external getNEAREST : int = "NEAREST";

[@bs.val] [@bs.module "pixi.js"]
external getSprite : usageFunSpriteT = "Sprite";

[@bs.val] [@bs.module "pixi.js"] [@bs.scope "Sprite"]
external fromImage1 : string => appSpriteT = "fromImage";

[@bs.get] external getAnchor : appSpriteT => appObservablePointT = "anchor";

[@bs.send] external set1 : (appObservablePointT, float) => unit = "set";

[@bs.set] external setX : (appSpriteT, int) => unit = "x";

[@bs.get] external getX : appSpriteT => int = "x";

[@bs.get] external getScreen : appApplicationT => appRectangleT = "screen";

[@bs.get] external getWidth : appRectangleT => int = "width";

[@bs.set] external setY : (appSpriteT, int) => unit = "y";

[@bs.get] external getY : appSpriteT => int = "y";

[@bs.get] external getHeight : appRectangleT => int = "height";

[@bs.set]
external setInteractive : (appSpriteT, Js.boolean) => unit = "interactive";

[@bs.get] external getInteractive : appSpriteT => Js.boolean = "interactive";

[@bs.set]
external setButtonMode : (appSpriteT, Js.boolean) => unit = "buttonMode";

[@bs.get] external getButtonMode : appSpriteT => Js.boolean = "buttonMode";

[@bs.val] external console : smallObject65T = "console";

[@bs.get] external getScale : appSpriteT => appObservablePointT = "scale";

[@bs.set]
external setXappObservablePointTfloat : (appObservablePointT, float) => unit =
  "x";

[@bs.get]
external getXappObservablePointT : appObservablePointT => float = "x";

[@bs.set]
external setYappObservablePointTfloat : (appObservablePointT, float) => unit =
  "y";

[@bs.get]
external getYappObservablePointT : appObservablePointT => float = "y";

[@bs.send]
external on2 : (appSpriteT, string, usageFunOnClickT) => appSpriteT = "on";

[@bs.new] external newEvent1 : string => appEventT = "Event";

[@bs.get] external getStage : appApplicationT => appContainerT = "stage";

[@bs.send]
external addChild1 : (appContainerT, appSpriteT) => appSpriteT = "addChild";

let app = newApplication3(800, 600, {"backgroundColor": 0x1099bb});

/*
 console.log(app.constructor.name);
  */
document |. getBody |. appendChild1(app |. getView);

/* Scale mode for all textures, will retain pixelation */
setSCALE_MODE(getSettings, getNEAREST);

let sprite =
  fromImage1("http://pixijs.io/examples/required/assets/basics/bunny.png");

/* Set the initial position */
sprite |. getAnchor |. set1(0.5);

setX(sprite, (app |. getScreen |. getWidth) / 2);

setY(sprite, (app |. getScreen |. getHeight) / 2);

/* Opt-in to interactivity */
setInteractive(sprite, Js.true_);

/* Shows hand cursor */
setButtonMode(sprite, Js.true_);

/* PS: Functions are not automatically lifted and must be in order for
 * generated script to use them correctly.  */
let onClick = evt => {
  /* PS: Make sure your event handlers are called at least once by script  */
  Js.log(evt);
  setXappObservablePointTfloat(
    sprite |. getScale,
    (sprite |. getScale |. getXappObservablePointT) *. 1.25
  );
  setYappObservablePointTfloat(
    sprite |. getScale,
    (sprite |. getScale |. getYappObservablePointT) *. 1.25
  );
  0;
};

/* Pointers normalize touch and mouse */
sprite |. on2("pointerdown", onClick);

/* PS: Make sure your event handlers are called at least once by script, and
 * done after function passed around, like in the following line:  */
onClick(newEvent1("test"));

/* Alternatively, use the mouse & touch events:
   sprite.on('click', onClick); // mouse-only
   sprite.on('tap', onClick); // touch-only */
app |. getStage |. addChild1(sprite);

if (Js.to_bool(Js.true_)) {
  Js.log("hello");
} else {
  Js.log("blah");
};

let xRef = ref(3);

xRef := xRef^ * 2;

Manual labour

This section lists workarounds for unimplemented features and transpilations.

After transpile:

Testing examples

Node example

Node support is basic so far, but an example can be found in src/example-node.txt.

To run the example:

npm run webpack # to compile dist/node.js
node dist/node.js # will transpile src/example-node.txt to src/TestNode.re
npm start # to compile src/TestNode.re
node src/TestNode.bs.js

Browser examples

node src/puppet.js examples/pixiBasics/example_001.js >| src/Test.re
npm start

Caveats

Go to http://localhost:8080/test .

Running tests

# run tests script
npm run test

Supported syntax

This list of ESprima syntax nodes is from here and annotated with whether transpilation is implemented or not yet. Create an issue if you want a syntax implemented.

FeatureSupported
AssignmentExpression<img src="https://upload.wikimedia.org/wikipedia/commons/b/bd/Checkmark_green.svg" alt="YES" width="20"/>
AssignmentPattern<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
ArrayExpression<img src="https://upload.wikimedia.org/wikipedia/commons/b/bd/Checkmark_green.svg" alt="YES" width="20"/>
ArrayPattern<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
ArrowFunctionExpression<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
AwaitExpression<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
BlockStatement<img src="https://upload.wikimedia.org/wikipedia/commons/b/bd/Checkmark_green.svg" alt="YES" width="20"/>
BinaryExpression<img src="https://upload.wikimedia.org/wikipedia/commons/b/bd/Checkmark_green.svg" alt="YES" width="20"/>
BreakStatement<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
CallExpression<img src="https://upload.wikimedia.org/wikipedia/commons/b/bd/Checkmark_green.svg" alt="YES" width="20"/>
CatchClause<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
ClassBody<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
ClassDeclaration<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
ClassExpression<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
ConditionalExpression<img src="https://upload.wikimedia.org/wikipedia/commons/b/bd/Checkmark_green.svg" alt="YES" width="20"/>
ContinueStatement<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
DoWhileStatement<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
DebuggerStatement<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
EmptyStatement<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
ExportAllDeclaration<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
ExportDefaultDeclaration<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
ExportNamedDeclaration<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
ExportSpecifier<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
ExpressionStatement<img src="https://upload.wikimedia.org/wikipedia/commons/b/bd/Checkmark_green.svg" alt="YES" width="20"/>
ForStatement<img src="https://upload.wikimedia.org/wikipedia/commons/b/bd/Checkmark_green.svg" alt="YES" width="20"/>
ForOfStatement<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
ForInStatement<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
FunctionDeclaration<img src="https://upload.wikimedia.org/wikipedia/commons/b/bd/Checkmark_green.svg" alt="YES" width="20"/>
FunctionExpression<img src="https://upload.wikimedia.org/wikipedia/commons/b/bd/Checkmark_green.svg" alt="YES" width="20"/>
Identifier<img src="https://upload.wikimedia.org/wikipedia/commons/b/bd/Checkmark_green.svg" alt="YES" width="20"/>
IfStatement<img src="https://upload.wikimedia.org/wikipedia/commons/b/bd/Checkmark_green.svg" alt="YES" width="20"/>
Import<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
ImportDeclaration<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
ImportDefaultSpecifier<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
ImportNamespaceSpecifier<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
ImportSpecifier<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
Literal<img src="https://upload.wikimedia.org/wikipedia/commons/b/bd/Checkmark_green.svg" alt="YES" width="20"/>
LabeledStatement<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
LogicalExpression<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
MemberExpression<img src="https://upload.wikimedia.org/wikipedia/commons/b/bd/Checkmark_green.svg" alt="YES" width="20"/>
MetaProperty<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
MethodDefinition<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
NewExpression<img src="https://upload.wikimedia.org/wikipedia/commons/b/bd/Checkmark_green.svg" alt="YES" width="20"/>
ObjectExpression<img src="https://upload.wikimedia.org/wikipedia/commons/b/bd/Checkmark_green.svg" alt="YES" width="20"/>
ObjectPattern<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
Program<img src="https://upload.wikimedia.org/wikipedia/commons/b/bd/Checkmark_green.svg" alt="YES" width="20"/>
Property<img src="https://upload.wikimedia.org/wikipedia/commons/b/bd/Checkmark_green.svg" alt="YES" width="20"/>
RestElement<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
ReturnStatement<img src="https://upload.wikimedia.org/wikipedia/commons/b/bd/Checkmark_green.svg" alt="YES" width="20"/>
SequenceExpression<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
SpreadElement<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
Super<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
SwitchCase<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
SwitchStatement<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
TaggedTemplateExpression<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
TemplateElement<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
TemplateLiteral<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
ThisExpression<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
ThrowStatement<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
TryStatement<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
UnaryExpression<img src="https://upload.wikimedia.org/wikipedia/commons/b/bd/Checkmark_green.svg" alt="YES" width="20"/>
UpdateExpression<img src="https://upload.wikimedia.org/wikipedia/commons/b/bd/Checkmark_green.svg" alt="YES" width="20"/>
VariableDeclaration<img src="https://upload.wikimedia.org/wikipedia/commons/b/bd/Checkmark_green.svg" alt="YES" width="20"/>
VariableDeclarator<img src="https://upload.wikimedia.org/wikipedia/commons/b/bd/Checkmark_green.svg" alt="YES" width="20"/>
WhileStatement<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
WithStatement<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>
YieldExpression<img src="https://upload.wikimedia.org/wikipedia/commons/8/85/Red_checkbox-unchecked.svg" alt="NO" width="20"/>

Alternatives