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

Livescript Compiler Intro

mindos
April 20, 2013

Livescript Compiler Intro

mindos

April 20, 2013
Tweet

Other Decks in Programming

Transcript

  1. “Easy things should be easy, and hard things should be

    possible.” -- Larry Wall Saturday, 20 April, 13
  2. Function Call sink = (v)-> v * 0.9 sink 8

    var sink; sink = function(v){ return v * 0.9; }; sink(8); Saturday, 20 April, 13
  3. Function Call sink = (v)-> v * 0.9 sink 8

    var sink; sink = function(v){ return v * 0.9; }; sink(8); Saturday, 20 April, 13
  4. Backcall <-! $ 'h1' .on 'click' alert 'boom!' ! means

    no return $('h1').on('click', function(){ alert('boom!'); }); Saturday, 20 April, 13
  5. Closure sink = do -> factor = 0.9 (v)-> map

    (* factor), v sink [3, 2, 0] var sink; sink = function(){ var factor; factor = 0.9; return function(v){ return map((function(it){ return it * factor; }), v); }; }(); sink([3, 2, 0]); Saturday, 20 April, 13
  6. Closure sink = do -> factor = 0.9 (v)-> map

    (* factor), v sink [3, 2, 0] var sink; sink = function(){ var factor; factor = 0.9; return function(v){ return map((function(it){ return it * factor; }), v); }; }(); sink([3, 2, 0]); Saturday, 20 April, 13
  7. Closure sink = do -> factor = 0.9 (v)-> map

    (* factor), v sink [3, 2, 0] var sink; sink = function(){ var factor; factor = 0.9; return function(v){ return map((function(it){ return it * factor; }), v); }; }(); sink([3, 2, 0]); Saturday, 20 April, 13
  8. Closure sink = do -> factor = 0.9 (v)-> map

    (* factor), v sink [3, 2, 0] var sink; sink = function(){ var factor; factor = 0.9; return function(v){ return map((function(it){ return it * factor; }), v); }; }(); sink([3, 2, 0]); Saturday, 20 April, 13
  9. “Buildin” Library times = (x, y) --> x * y

    times 2, 3 #=> 6 double = times 2 double 5 #=> 10 var times, double; times = curry$(function(x, y){ return x * y; }); times(2, 3); double = times(2); double(5); function curry$(f, bound){ var context, _curry = function(args) { return f.length > 1 ? function(){ var params = args ? args.concat() : []; context = bound ? context || this : this; return params.push.apply(params, arguments) < f.length && arguments.length ? _curry.call(context, params) : f.apply(context, params); } : f; }; return _curry(); } From http://livescript.net/ Saturday, 20 April, 13
  10. Class Made Easy class A (num) -> @x = num

    method: (y) -> @x + y a = new A 3 b = new A 4 a.method 6 b.method 7 var A, a, b; A = (function(){ A.displayName = 'A'; var prototype = A.prototype; var constructor = A; function A(num){ this.x = num; } prototype.method = function(y){ return this.x + y; }; return A; }()); a = new A(3); b = new A(4); a.method(6); b.method(7); From http://livescript.net/ Saturday, 20 April, 13
  11. Livescript Compiler sink = do -> factor = 0.9 (v)->

    map (* factor), v var sink; sink = function(){ var factor; factor = 0.9; return function(v){ return map((function(it){ return it * factor; }), v); }; }(); Saturday, 20 April, 13
  12. lexer sink = do -> factor = 0.9 (s)-> s

    * factor NEWLINE:\n ID:sink ASSIGN:= UNARY:do PARAM(: )PARAM: -> INDENT:2 ID:factor ASSIGN:= STRNUM:0.9 NEWLINE:\n PARAM(:( ID:s )PARAM:) -> INDENT:2 ID:s MATH:* ID:factor DEDENT:2 DEDENT:2 NEWLINE:\n parser Compile Block Assign = Var sink Unary do Fun Block Assign = Var factor Literal 0.9 Fun Var s Block Binary * Var s Var factor var sink; sink = function(){ var factor; factor = 0.9; return function(v){ return map((function(it){ return it * factor; }), v); }; }(); parser.parse do (lexer.lex code) .compileRoot options Saturday, 20 April, 13
  13. Lexer => Tokens sink = do -> factor = 0.9

    (s)-> s * factor ID:sink ASSIGN:= UNARY:do PARAM(: )PARAM: -> INDENT:2 ID:factor ASSIGN:= STRNUM:0.9 NEWLINE:\n PARAM(:( ID:s )PARAM:) -> INDENT:2 ID:s MATH:* ID:factor DEDENT:2 DEDENT:2 NEWLINE:\n Saturday, 20 April, 13
  14. Handling Parameters (v) (v) -> ret -> ret ( ID:v

    ) NEWLINE:\n PARAM(:( ID:v )PARAM:) -> INDENT:2 ID:ret DEDENT: 2 NEWLINE:\n PARAM(: )PARAM: -> INDENT:2 ID:ret DEDENT: 2 NEWLINE:\n Saturday, 20 April, 13
  15. Handling Parameters PARAM(:( ID:v )PARAM:) -> PARAM(: )PARAM: -> (v)

    -> ret -> ret @last = [tag, value, @line] parameters: !(arrow, offset) -> if @last.0 is \) is @last.1 @lpar.0 = \PARAM( @last.0 = \)PARAM return if arrow is \-> then @token \PARAM( '' else for t, i in @tokens by -1 when t.0 in <[ NEWLINE INDENT THEN => ( ]> then break @tokens.splice (i+1), 0 [\PARAM( '' t.2] if offset then @tokens.splice (@tokens.length + offset), 0 [\)PARAM '' t.2] else @token \)PARAM '' Saturday, 20 April, 13
  16. Parser =>AST sink = do -> factor = 0.9 (s)->

    s * factor Block Assign = Var sink Unary do Fun Block Assign = Var factor Literal 0.9 Fun Var s Block Binary * Var s Var factor Saturday, 20 April, 13
  17. Generate => JS lexer sink = do -> factor =

    0.9 (s)-> s * factor NEWLINE:\n ID:sink ASSIGN:= UNARY:do PARAM(: )PARAM: -> INDENT:2 ID:factor ASSIGN:= STRNUM:0.9 NEWLINE:\n PARAM(:( ID:s )PARAM:) -> INDENT:2 ID:s MATH:* ID:factor DEDENT:2 DEDENT:2 NEWLINE:\n parser Compile Block Assign = Var sink Unary do Fun Block Assign = Var factor Literal 0.9 Fun Var s Block Binary * Var s Var factor var sink; sink = function(){ var factor; factor = 0.9; return function(v){ return map((function(it){ return it * factor; }), v); }; }(); Saturday, 20 April, 13
  18. compileRoot compileRoot: (options) -> o = {level: LEVEL_TOP, scope: @scope

    = Scope.root = new Scope, ...options} if saveTo = delete o.saveScope o.scope = saveTo.savedScope or= o.scope delete o.filename o.indent = if bare = delete o.bare then '' else TAB if /^\s*(?:[/#]|javascript:)/test @lines.0?code prefix = @lines.shift!code + \\n if delete o.eval and @chomp!lines.length if bare then @lines.push Parens @lines.pop! else @makeReturn! code = @compileWithDeclarations o # Wrap everything in a safety closure unless requested not to. bare or code = "(function(){\n#code\n}).call(this);\n" [prefix] + code Saturday, 20 April, 13
  19. compileWithDeclarations compileWithDeclarations: (o) -> o.level = LEVEL_TOP pre = ''

    if i = @neck! rest = @lines.splice i, 9e9 pre = @compile o @lines = rest return pre unless post = @compile o (pre and "#pre\n") + if @scope then that.emit post, o.indent else post Saturday, 20 April, 13
  20. compile compile: (o, level ? o.level) -> return @compileExpressions o,

    level if level o.block = this; tab = o.indent codes = for node in @lines node = node.unfoldSoak o or node continue unless code = (node <<< {+front})compile o, level node.isStatement! or code += node.terminator tab + code codes.join \\n Saturday, 20 April, 13
  21. compileExpression compileExpressions: (o, level) -> {lines} = @chomp!; i =

    -1 while lines[++i] then lines.splice i-- 1 if that.comment lines.push Literal \void unless lines.length lines.0 <<< {@front}; lines[*-1] <<< {@void} return lines.0.compile o, level unless lines.1 code = ''; last = lines.pop! for node in lines then code += (node <<< {+void})compile(o, LEVEL_PAREN) + ', ' code += last.compile o, LEVEL_PAREN if level < LEVEL_LIST then code else "(#code)" Saturday, 20 April, 13
  22. compile compileExpression Assign. compile Fun. compile For. compile Require. compile

    Assign. compile Assign. compile For. compile For. compile Require. compile Require. compile Fun. compile Fun. compile Saturday, 20 April, 13
  23. Cool things Destructuring {name, age} = {weight: 110, name: 'emma',

    age: 20} name #=> 'emma' age #=> 20 Piping [1 2 3] |> map (* 2) |> filter (> 3) |> fold1 (+) #=> 10 Partition scores = [49 58 76 43 88 77 90] [passed, failed] = partition (> 60), scores passed #=> [76, 88, 77, 90] failed #=> [49, 58, 43] From http://livescript.net/ http://livescript.net/blog/livescript-one- liners-to-impress-your-friends.html Saturday, 20 April, 13
  24. Cool things Units 64_000km Truth Values true false on off

    yes no From http://livescript.net/ http://livescript.net/blog/livescript-one- liners-to-impress-your-friends.html Saturday, 20 April, 13
  25. In Parallel Universe Units consistent check ship. setSpeed 64_000m ......

    ship. setSpeed 65_000 # okey ...... ship.setSpeed 64_000km # Warning Truth Values check ? Functional Syntax Optimization Saturday, 20 April, 13
  26. In Parallel Universe Functional Syntax Optimization fold1 (+), [1 to

    5] fold1(curry$(function(x$, y$){ return x$ + y$; }), [1, 2, 3, 4, 5]); function curry$(f, bound){ var context, _curry = function(args) { return f.length > 1 ? function(){ var params = args ? args.concat() : []; context = bound ? context || this : this; return params.push.apply(params, arguments) < f.length && arguments.length ? _curry.call(context, params) : f.apply(context, params); } : f; }; return _curry(); } Saturday, 20 April, 13
  27. In Parallel Universe Functional Syntax Optimization fold1 (+), [1 to

    5] fold1(curry$(function(x$, y$){ return x$ + y$; }), [1, 2, 3, 4, 5]); src = [1 to 5] x = src[0] for i from 1 til src.length x+=src[i] x var src, x, i$, to$, i; src = [1, 2, 3, 4, 5]; x = src[0]; for (i$ = 1, to$ = src.length; i$ < to$; ++i$) { i = i$; x += src[i]; } x; Saturday, 20 April, 13