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. Macros
    Unshackling JavaScript
    James Long / @jlongster
    with

    View full-size slide

  2. with
    http://www.quirkyscience.com/wp-content/uploads/2012/06/Explosion-Image-by-US-Department-of-Defense.jpg
    ASI
    http://markakiprof.files.wordpress.com/2009/11/stresss.jpg
    ==

    View full-size slide

  3. 1998
    EcmaScript 2

    View full-size slide

  4. 1999
    EcmaScript 3

    View full-size slide

  5. 2014
    EcmaScript 6

    View full-size slide

  6. var {x, y} = pos;

    View full-size slide

  7. <3

    COMPILERS

    View full-size slide

  8. (defmacro if (test cons alt)!
    ...)

    View full-size slide

  9. (defmethod (ship :speed) ()!
    (sqrt (+ (^ x-velocity 2)!
    (^ y-velocity 2)))

    View full-size slide

  10. method ship speed() {!
    return sqrt(pow(this.xVelocity, 2),!
    pow(this.yVelocity, 2));!
    }

    View full-size slide

  11. Emotion as a Value

    View full-size slide

  12. var happy = ;!
    // ILLEGAL
    # Emotion Literals

    View full-size slide

  13. var happy = ;!
    // OK!
    # Emotion Literals

    View full-size slide

  14. # Emotional Algebra
    + == ;
    + ==
    + == ;

    View full-size slide

  15. if(1 == “1”) { ... }!
    // Error: "==" is not allowed
    # Enforce Good Practices

    View full-size slide

  16. # Enforce Good Practices
    if(1 “1”) { ... }

    View full-size slide

  17. # Errors
    throw new Error(!
    “something is wrong”!
    )

    View full-size slide

  18. # Errors
    "something is wrong"

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  21. # Better Expressiveness
    if(user < ) {!
    "be happy"!
    }

    View full-size slide

  22. $ npm install emojiscript
    $ emo file.js > output.js

    View full-size slide

  23. $ npm install emojiscript
    $ sjs -m emojiscript/macros/poop.js file.js

    View full-size slide

  24. macros/fat-arrow.js
    x => x * x
    function(x) {!
    return x * x;!
    }.bind(this)

    View full-size slide

  25. 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];

    View full-size slide

  26. macros/class.js
    class Foo {!
    move(x, y) {!
    this.x = x;!
    this.y = y;!
    }!
    }

    View full-size slide

  27. macros/class.js
    function Foo() {}!
    Foo.prototype.move = function(x, y) {!
    this.x = x;!
    this.y = y;

    }

    View full-size slide

  28. $ sjs!
    -m emojiscript/macros/poop.js !
    -m es6-macros/macros/fat-arrow.js!
    file.js

    View full-size slide

  29. • Proposal
    • Discussion
    • Finalization
    • Implementation
    • Maturation

    View full-size slide

  30. @Inject(TodoList)!
    export class AppView extends View {!
    !
    constructor(todos) {!
    this.todos = todos;!
    //...!
    }!
    !
    // ...!
    !
    }
    # Angular & ES6+

    View full-size slide

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

    View full-size slide

  32. macro macro {!
    case { $ctx } => {!
    throwSyntaxError(!
    "macros are not allowed, go home”,!
    #{$ctx}!
    );!
    }!
    }

    View full-size slide

  33. # Function Tracing

    View full-size slide

  34. 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;!
    }!
    }

    View full-size slide

  35. $('#app').html('');

    View full-size slide

  36. # Stack Allocation

    View full-size slide

  37. 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);

    View full-size slide

  38. defineRecord Point {!
    x : double,!
    y : double!
    }!
    !
    Point pos;!
    pos.x = 100;!
    pos.y = 80;

    View full-size slide

  39. var ptr = SP;!
    SP -= 16;!
    F8[ptr + 0] = 100;!
    F8[ptr + 8] = 80;

    View full-size slide

  40. # Sweet.js Features
    • Pattern Matching
    • Various expansion strategies
    • Hygiene

    View full-size slide

  41. # 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!
    }!
    }

    View full-size slide

  42. # Expansion Strategies: rule
    macro foo {!
    rule { } => {!
    // expanded code!
    }!
    !
    rule { } => {!
    // expanded code!
    }!
    !
    rule { } => {!
    // expanded code!
    }!
    }

    View full-size slide

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

    View full-size slide

  44. # Expansion Strategies: infix
    macro => {!
    rule infix { ($value (,) ...) | {$body ...} } => {!
    function($value (,) ...) {!
    $body ...!
    }.bind(this)!
    }!
    rule infix { ($value (,) ...) | $guard:expr } => {!
    function($value (,) ...) {!
    return $guard;!
    }.bind(this)!
    }!
    }!

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  47. # Expansion Strategies: case
    !
    macro foo {!
    case { $ctx } => {!
    // any JavaScript executed here!!
    !
    if(!cond) {!
    throwSyntaxError("bad thing!", #{$ctx});!
    }!
    !
    letstx $name = [token];!
    return #{!
    // expanded code here!
    $name!
    }!
    }!
    }

    View full-size slide

  48. # 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

    View full-size slide

  49. # Syntax Highlighting

    View full-size slide

  50. # 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

    View full-size slide

  51. Thanks!
    James Long / @jlongster
    https://github.com/jlongster/emojiscript

    View full-size slide