Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Unshackling JavaScript with Macros

Unshackling JavaScript with Macros

My JSConf 2014 talk (not so useful without speaker notes. video coming soon)

James Long

May 30, 2014
Tweet

More Decks by James Long

Other Decks in Technology

Transcript

  1. if(1 == “1”) { ... }! // Error: "==" is

    not allowed # Enforce Good Practices
  2. # Automatic Cat Insertion var foo = 1 + 2;!

    var bar = baz();! var user = + ;
  3. # Automatic Cat Insertion var foo = 1 + 2!

    var bar = baz()! var user = +
  4. macros/destructure.js var {x, y} = obj;! var [one, two] =

    arr; var x = obj.x;! var y = obj.y;! var one = arr[0];! var two = arr[1];
  5. @Inject(TodoList)! export class AppView extends View {! ! constructor(todos) {!

    this.todos = todos;! //...! }! ! // ...! ! } # Angular & ES6+
  6. macro == {! case { $ctx } => {! throwSyntaxError(!

    "== is not allowed”,! #{$ctx}! );! }! }
  7. macro macro {! case { $ctx } => {! throwSyntaxError(!

    "macros are not allowed, go home”,! #{$ctx}! );! }! }
  8. let function = macro {! rule { $name($args ...) {

    $body ... } } => {! console.log(! "calling " + syntaxToString $name + “..”! );! ! var ret = (function($args ...) {! $body ...;! })($args ...);! ! console.log(! "returning " + syntaxToString $name! );! return ret;! }! }
  9. var MB = 1024 * 1024;! var STACK_SIZE = 2

    * MB;! var buffer = new ArrayBuffer(STACK_SIZE);! var U1 = new Uint8Array(buffer);! var I1 = new Int8Array(buffer);! var U2 = new Uint16Array(buffer);! var I2 = new Int16Array(buffer);! var U4 = new Uint32Array(buffer);! var I4 = new Int32Array(buffer);! var F4 = new Float32Array(buffer);! var F8 = new Float64Array(buffer);
  10. defineRecord Point {! x : double,! y : double! }!

    ! Point pos;! pos.x = 100;! pos.y = 80;
  11. var ptr = SP;! SP -= 16;! F8[ptr + 0]

    = 100;! F8[ptr + 8] = 80;
  12. ?

  13. # Pattern Matching macro var {! rule { { $name

    (,) ... } = $obj } => {! var $($name = $obj.$name) (,) ...! }! ! rule { [ $name (,) ... ] = $arr } => {! var i = 0;! var $($name = $arr[i++]) (,) ...! }! ! rule { $name } => {! var $name! }! }
  14. # Expansion Strategies: rule macro foo {! rule { <pattern1>

    } => {! // expanded code! }! ! rule { <pattern2> } => {! // expanded code! }! ! rule { <pattern3> } => {! // expanded code! }! }
  15. # Expansion Strategies: let let var = macro {! rule

    { $name = $val:expr } => {! var $name = $val! }! }
  16. # Expansion Strategies: infix macro => {! rule infix {

    ($value (,) ...) | {$body ...} } => {! function($value (,) ...) {! $body ...! }.bind(this)! }! rule infix { ($value (,) ...) | $guard:expr } => {! function($value (,) ...) {! return $guard;! }.bind(this)! }! }!
  17. # Expansion Strategies: operator operator + 12 left { $l,

    $r } => #{! add($l, $r)! } add(add(add(1, 2), 3), 4); 1 + 2 + 3 + 4
  18. # Expansion Strategies: operator operator + 12 right { $l,

    $r } => #{! add($l, $r)! } add(1, add(2, add(3, 4))) 1 + 2 + 3 + 4
  19. # Expansion Strategies: case ! macro foo {! case {

    $ctx <pattern1> } => {! // any JavaScript executed here!! ! if(!cond) {! throwSyntaxError("bad thing!", #{$ctx});! }! ! letstx $name = [token];! return #{! // expanded code here! $name! }! }! }
  20. # Hygiene macro square {! rule { $expr:expr } =>

    {! var x = $expr;! x * x! }! }! ! var x = 5;! square x; var x$1 = 5;! var x$2 = x$1;! x$2 * x$2
  21. # Quick Recap • JavaScript is under a lot of

    pressure to
 evolve • sweet.js provides macros for adding language features as libraries • Compilers can’t work together • We can help TC39 and liberate JavaScript