By Cody
23/09/2016
C/C++: Preprocessor > Compiler > Assembler > Linker
JavaScript: Lexer > Parser > Translator > Interpreter
An extraordinarily optimizable, low-level subset of JavaScript.
function DiagModule(stdlib) {
"use asm";
var sqrt = stdlib.Math.sqrt;
function square(x) {
x = +x;
return +(x*x);
}
function diag(x, y) {
x = +x;
y = +y;
return +sqrt(square(x) + square(y));
}
return { diag: diag };
}
// Browsers: this === window
var fast = DiagModule(this); // link the module
console.log(fast.diag(3, 4)); // 5
function MyAsmModule(stdlib, foreign, heap) {
"use asm"; // marks this function as an asm.js module
// module body:
function f1(...) { ... }
function f2(...) { ... }
// ...
return {
export1: f1,
export2: f2,
// ...
};
}
stdlib: a standard library object, providing access to (a subset of) the standard library.
foreign: a foreign function interface (FFI) providing access to arbitrary external JavaScript functions.
heap: a heap buffer, an instance of ArrayBuffer that acts as the asm.js heap.
Via its initializer
var a = 0; // a has type int
var b = 0.0; // b has type double
Via type annotations
function foo(x, y) {
var x = x|0; // x has type int
var y = +y; // y has type double
return +(x * y); // function returns a double
}
In the real world, it's like this:
Tips: Emscripten does all these.
#include <stdio.h>
int fib(int x) {
if (x < 2) {
return 1;
} else {
return fib(x - 1) + fib(x - 2);
}
}
int main() {
int result = fib(45);
printf("%d\n", result);
return 1;
}
./emcc -O1 -s ASM_JS=1 ./hello_world.cpp
node ./a.out.js
CoffeeScript
divisible = 3
divisibleReporter = (lastFound, nextDivisible) ->
"Found: #{lastFound}, Next: #{nextDivisible}"
divisibleKeeper = ((divisible) ->
lastFound = 0
nextDivisible = divisible
(number) ->
if (number >= nextDivisible)
nextDivisible = (Math.floor(number/divisible) + 1) * divisible
lastFound = Math.floor(number/divisible) * divisible
console.log divisibleReporter(lastFound, nextDivisible)
)(divisible);
for n in [1..100]
divisibleKeeper(n)
TypeScript
var divisible = 3;
var divisibleReporter = function(lastFound:number, nextDivisible:number){
return "Found: " + lastFound + ", Next: " + nextDivisible;
};
var divisibleKeeper = (function(divisible:number) {
var lastFound = 0;
var nextDivisible = divisible;
return function(number:number) {
if (number >= nextDivisible) {
nextDivisible = (Math.floor(number / divisible) + 1) * divisible;
lastFound = Math.floor(number / divisible) * divisible;
console.log(divisibleReporter(lastFound, nextDivisible));
}
};
})(divisible);
for (var i = 1; i <= 100; ++i) {
divisibleKeeper(i);
}
Dart
int divisible = 3;
String divisibleReporter(int lastFound, int nextDivisible) => "Found: ${lastFound}, Next: ${nextDivisible}";
var divisibleKeeper = ((int divisible) {
int lastFound = 0;
int nextDivisible = divisible;
return (int number){
if (number >= nextDivisible) {
nextDivisible = ((number/divisible).floor() + 1) * divisible;
lastFound = (number/divisible).floor() * divisible;
print(divisibleReporter(lastFound, nextDivisible));
}
};
})(divisible);
void main() {
for (var i = 0; i < 100; i++) {
divisibleKeeper(i);
}
}
GWT
public class ButtonExample implements EntryPoint {
public void onModuleLoad() {
// Make a new button that does something when you click it.
Button b = new Button("Jump!", new ClickHandler() {
public void onClick(ClickEvent event) {
Window.alert("How high?");
}
});
// Add it to the root panel.
RootPanel.get().add(b);
}
}
Currently ONLY Firefox and Edge support this
The asm.js is still JS, ONLY saving time during interpretion
Hard to debug
WebAssembly or wasm is a new portable, size- and load-time-efficient format suitable for compilation to the web.
others said...
WebAssembly is (roughly) a binary format for delivering asm.js code.
The text format is equivalent and isomorphic to the binary format.
The Binaryen shell, which can load a WebAssembly module, transform it, execute it in an interpreter, print it, etc.
Tool pack: asm2wasm / wasm2asm / s2wasm / wasm.js