Last active
January 27, 2017 12:07
-
-
Save dk00/d1291a66bccdc79bc3771501781e39eb to your computer and use it in GitHub Desktop.
Livescript AST to babel AST converter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ``import * as types from 'babel-types'`` | |
| function L | |
| start: line: it.first_line, column: it.first_column | |
| end: line: it.last_line, column: it.last_column | |
| [none = [] empty = {} REF = 1 ASSIGN = 2 DECL = 4 PARAM = 8] | |
| function pass => it | |
| type-name = (.constructor.display-name) | |
| function t node, scope | |
| convert = t[type-name node] || t.unk | |
| node.children .= map -> node[it] | |
| convert node, scope | |
| ..loc = L node | |
| t <<< types | |
| function merge scope, nested | |
| Object.keys nested .forEach (key) -> scope[key] .|.= nested[key] | |
| scope | |
| function collect scope, convert, node | |
| convert t node, scope | |
| merge scope, ..scope | |
| function reduce nodes, upper, types=none | |
| scope = Object.create upper | |
| args = nodes.map (node, index) -> | |
| convert = collect.bind void scope, types[index] || pass | |
| node.map? convert or convert node | |
| [args, scope] | |
| function define {types=none, pre=pass, post=pass, args, build} | |
| => (node, upper) -> | |
| scope = pre upper, node | |
| [nodes, scope] = post ...(reduce node.children, scope, types), upper, node | |
| params = args? node or [] | |
| t[build] ...params ++ nodes | |
| ..scope = scope | |
| #Node types | |
| function map-values object, value | |
| Object.keys object .reduce (result, key) -> | |
| result[key]? = value object[key] | |
| result | |
| , {} | |
| function set-assign scope, type | |
| map-values scope, -> if it.&.PARAM then (it.&.~PARAM).|.type else it | |
| function make-assign args, scope,, node | |
| type = if node.op == \= then DECL else ASSIGN | |
| [args, set-assign scope, type] | |
| function declare names | |
| t.variableDeclaration \let names.map -> t.variableDeclarator t.id it | |
| function close-scope upper, scope | |
| to-declare = -> (upper[it].|.0) < DECL && scope[it] >= DECL | |
| Object.keys scope | |
| declared = ..filter to-declare | |
| referenced = ..filter -> !to-declare it | |
| declarations = declare declared if declared.length > 0 | |
| [declarations, referenced] | |
| function make-block [body] scope, upper | |
| [declarations, referenced] = close-scope upper, scope | |
| body = body.reduce (body, node) -> | |
| body ++= (node.lines || []) ++ node | |
| , [] | |
| body.unshift that if declarations | |
| scope = {[k, scope[k]] for k in referenced} | |
| [[body] scope] | |
| function omit-declared => it if it < DECL | |
| function make-function [params, block] scope | |
| if params.length == 0 && block.scope.it | |
| params.push t.id \it | |
| block.scope.it = DECL | |
| block.body[*-1] = t.return block.body[*-1] | |
| [[params, block] map-values block.scope, omit-declared] | |
| #Child types | |
| function derive convert, node | |
| that <<< node{scope, lines} if convert node | |
| statement = derive.bind void -> | |
| t.toStatement switch | |
| | t.isExpression it => t.expressionStatement it | |
| | _ => it | |
| expr = derive.bind void -> | |
| | it?expression => that | |
| | t.isExpression it => it | |
| function lval node | |
| node.scope[that] .|.= PARAM if node.name | |
| node | |
| t <<< | |
| id: -> t.identifier it | |
| unk: -> t.id (type-name it) + \$ | |
| return: -> if expr it then t.returnStatement that else it | |
| Var: -> (t.id it.value) <<< scope: (it.value): REF | |
| Assign: define do | |
| build: \assignmentExpression types: [lval, expr] | |
| post: make-assign, args: (node) -> [node.op] | |
| Block: define do | |
| build: \blockStatement types: [statement] pre: -> {} | |
| post: make-block | |
| Fun: define do | |
| build: \functionExpression types: [lval, statement] | |
| pre: (, node) -> if node.params.length == 0 then it: DECL else {} | |
| post: make-function, args: (node) -> [t.id node.name || ''] | |
| function transform root | |
| program = t root, top: DECL | |
| ..type = \Program | |
| p program.scope | |
| t.file program, [] [] | |
| ..loc = program.loc | |
| ``export default transform`` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| readFileSync = require \fs .readFileSync | |
| ast = require \livescript .ast | |
| transform = require \./transform | |
| gen = require \babel-generator .\default | |
| function compile code => gen transform ast code | |
| module.exports = compile |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "name": "livescript-babel", | |
| "version": "0.0.1", | |
| "description": "Livescript AST to babel AST transformer", | |
| "main": "compile.ls", | |
| "dependencies": { | |
| "babel-types": "", | |
| "livescript": "", | |
| "babel-generator": "" | |
| } | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Moved to github
let,const, and:=constconstor not = 2nd pass.=
Almost every side effect executed in the same order of they occurrence, expect:
[val=console.log('default')] = console.log('expr'), []LVal
memberExpressionarrayPatternrestElementobjectPatternrestPropertyassignmentPatternAssignment
a ?= b=>a ? a = ba ? ba != nullaba? = bb != nulla=bvoida? btypeof a == \functiona bvoida?ba != nulla.bvoidScopes
itis marked as declared for inner nodes of functions, and will be declared actually when referenced.