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

Unshackling JavaScript with Macros

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on. →

Unshackling JavaScript with Macros

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

James Long

May 30, 2014

Transcript

72 slides
  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. ⾠

  6. @Inject(TodoList)! export class AppView extends View {! ! constructor(todos) {!

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

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

    "macros are not allowed, go home”,! #{$ctx}! );! }! }
  9. 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;! }! }
  10. 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);
  11. defineRecord Point {! x : double,! y : double! }!

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

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

  14. # 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! }! }
  15. # Expansion Strategies: rule macro foo {! rule { <pattern1>

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

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

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

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

    $r } => #{! add($l, $r)! } add(1, add(2, add(3, 4))) 1 + 2 + 3 + 4
  20. # 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! }! }! }
  21. # 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
  22. # 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

More Decks by James Long

Other Decks in Technology