diff --git a/Sakefile b/Sakefile index 2b5ccf8..8583835 100644 --- a/Sakefile +++ b/Sakefile @@ -20,55 +20,12 @@ task('compile:six', () => { task('watch:six', () => launch('node bin/six -cwo ./lib ./src')) -var dot = require("dot") - -dot.templateSettings = { - evaluate: /\{\{([\s\S]+?)\}\}/g, - interpolate: /\{\{=([\s\S]+?)\}\}/g, - encode: /\{\{!([\s\S]+?)\}\}/g, - use: /\{\{#([\s\S]+?)\}\}/g, - define: /\{\{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\}\}/g, - conditional: /\{\{\?(\?)?\s*([\s\S]*?)\s*\}\}/g, - iterate: /\{\{~\s*(?:\}\}|([\s\S]+?)\s*\:\s*([\w$]+)\s*(?:\:\s*([\w$]+))?\s*\}\})/g, - varname: 'it', - strip: true, - append: true, - selfcontained: true -} - -var filterPath = __dirname + "/src/filters/" -var filterOut = __dirname + "/lib/filters/" - -task('compile:dot', () => { - readdirSync(filterPath).forEach(file => { - if (path.extname(file) === ".dot") { - var source = readFileSync(filterPath + file).toString() - source = "exports.filter = " + dot.template(source).toString() - writeFileSync(filterOut + file.replace(".dot", ".js"), source, 'utf8') - } - }) -}) - -task('watch:dot', () => { - watch(filterPath, (event, filename) => invoke("compile:dot")) -}) - task('compile', () => { invoke('compile:six') - invoke('compile:dot') }) task('watch', () => { invoke('watch:six') - invoke('watch:dot') -}) - -var Six = require("./lib/six") - -task("build:browserrr", () => { - - console.log(Six.compile(readFileSync("./src/six.six").toString(), {global:true})) - }) import compile from "./lib/six" diff --git a/lib/es6.js b/lib/core/es6.js similarity index 66% rename from lib/es6.js rename to lib/core/es6.js index 381ca55..c04534c 100644 --- a/lib/es6.js +++ b/lib/core/es6.js @@ -18,15 +18,15 @@ define(function (require, exports) { writable: true, configurable: true }}); - Array.prototype.iterator = function () { - return { - elements: this, - index: 0, - next: function () { - if (this.index >= this.elements.length) - throw StopIteration; - return this.elements[this.index++]; - } - }; - }; + Object.defineProperty(Array.prototype, "iterator", {value: function () { + return { + elements: this, + index: 0, + next: function () { + if (this.index >= this.elements.length) + throw StopIteration; + return this.elements[this.index++]; + } + }; + }}); }); \ No newline at end of file diff --git a/lib/core/hooks.js b/lib/core/hooks.js new file mode 100644 index 0000000..ea9596e --- /dev/null +++ b/lib/core/hooks.js @@ -0,0 +1,28 @@ +if (typeof exports === 'object' && typeof define !== 'function') { + var define = function (factory) { + factory(require, exports); + }; +} +define(function (require, exports) { + var esprima = require("esprima-six"); + var parse = esprima.parse; + var hooks = exports.hooks = []; + hooks.push(function (tree) { + var egal = parse("(function ( x, y ) { return (x === y)?( x !== 0 || 1/x === 1/y ) : ( x !== x && y !==y )})()").body[0].expression; + var egaller = function (left, right) { + return { + type: egal.type, + arguments: [ + left, + right + ], + callee: egal.callee + }; + }; + tree.traverse(function (node) { + if (node.type === "BinaryExpression" && /^is/.test(node.operator)) { + node.overload(egaller(node.left.toAST(), node.right.toAST())); + } + }.bind(this)); + }.bind(this)); +}); \ No newline at end of file diff --git a/lib/core/rewriter.js b/lib/core/rewriter.js new file mode 100644 index 0000000..77820f8 --- /dev/null +++ b/lib/core/rewriter.js @@ -0,0 +1,37 @@ +if (typeof exports === 'object' && typeof define !== 'function') { + var define = function (factory) { + factory(require, exports); + }; +} +define(function (require, exports) { + require("./es6"); + var esprima = require("esprima-six"); + var parse = esprima.parse; + var esgen = require("escodegen").generate; + var Tree = require("./tree").Tree; + var hooks = require("./hooks").hooks; + var config = exports.config = { + format: { + indent: {style: " "}, + quotes: "double", + compact: false + }, + comment: true + }; + var rewrite = exports.rewrite = function (src, options) { + var sourceTree = new Tree(parse(src), options); + var hook; + void function (_iterator) { + try { + while (true) { + hook = _iterator.next(); + hook(sourceTree, options); + } + } catch (e) { + if (e !== StopIteration) + throw e; + } + }.call(this, hooks.iterator()); + return esgen(sourceTree.toAST(), config); + }; +}); \ No newline at end of file diff --git a/lib/core/tree.js b/lib/core/tree.js new file mode 100644 index 0000000..de796e6 --- /dev/null +++ b/lib/core/tree.js @@ -0,0 +1,188 @@ +if (typeof exports === 'object' && typeof define !== 'function') { + var define = function (factory) { + factory(require, exports); + }; +} +define(function (require, exports) { + var isArray = Array.isArray; + var push = Array.prototype.push; + var slice = Array.prototype.slice; + var iterator = Array.prototype.iterator; + var indexOf = Array.prototype.indexOf; + var forEach = Array.prototype.forEach; + var keys = Object.keys; + var defineProperty = Object.defineProperty; + var defineProperties = Object.defineProperties; + var Tree = function () { + function Tree(ast, options) { + this.root = new Node(ast); + } + Tree.prototype.traverse = function (visitor) { + visitor.call(this.root, this.root); + this.root.traverse(visitor); + }; + Tree.prototype.toAST = function () { + return this.root.toAST(); + }; + return Tree; + }(); + var Node = function () { + function Node(ast, opts) { + opts || (opts = {}); + defineProperties(this, { + children: {value: new NodeSet(null, { + parent: this, + key: "children" + })}, + nodeType: {value: "Node"}, + nodeKey: {value: opts.key || null}, + parent: {value: opts.parent || null} + }); + this.set(ast); + } + Node.prototype.create = function (ast, opts) { + return new (isArray(ast) ? NodeSet : Node)(ast, opts); + }; + Node.prototype.clean = function () { + var key; + void function (_iterator) { + try { + while (true) { + key = _iterator.next(), key = key.key; + delete this[key]; + } + } catch (e) { + if (e !== StopIteration) + throw e; + } + }.call(this, this.iterator()); + this.children = new NodeSet(null, { + parent: this, + key: "children" + }); + }; + Node.prototype.set = function (ast) { + var key; + void function (_iterator) { + try { + while (true) { + key = _iterator.next(); + if (typeof ast[key] === "object" && key !== "range" && ast[key] !== null) { + this.append(this[key] = this.create(ast[key], { + parent: this, + key: key + })); + } else { + this[key] = ast[key]; + } + } + } catch (e) { + if (e !== StopIteration) + throw e; + } + }.call(this, keys(ast).iterator()); + }; + Node.prototype.overload = function (ast) { + this.clean(); + this.set(ast); + }; + Node.prototype.append = function (node) { + push.call(this.children, node); + }; + Node.prototype.traverse = function (visitor) { + var child; + void function (_iterator) { + try { + while (true) { + child = _iterator.next(); + visitor.call(child, child); + child.traverse(visitor); + } + } catch (e) { + if (e !== StopIteration) + throw e; + } + }.call(this, this.children.iterator()); + }; + Node.prototype.iterator = function () { + return { + elements: keys(this).map(function (key) { + return { + key: key, + value: this[key] + }; + }.bind(this)), + index: 0, + next: function () { + if (this.index >= this.elements.length) + throw StopIteration; + return this.elements[this.index++]; + } + }; + }; + Node.prototype.toAST = function () { + var ast = {}; + var key, value; + void function (_iterator) { + try { + while (true) { + key = _iterator.next(), value = key.value, key = key.key; + ast[key] = typeof value === "object" ? value.toAST() : value; + } + } catch (e) { + if (e !== StopIteration) + throw e; + } + }.call(this, this.iterator()); + return ast; + }; + return Node; + }(); + var NodeSet = function (_super) { + function __ctor() { + this.constructor = NodeSet; + } + __ctor.prototype = _super.prototype; + NodeSet.prototype = new __ctor(); + NodeSet.__super__ = _super.prototype; + function NodeSet(items, opts) { + opts || (opts = {}); + defineProperties(this, { + nodeType: {value: "NodeSet"}, + nodeKey: {value: opts.key || null}, + parent: {value: opts.parent || null} + }); + this.length = 0; + items && items.forEach(function (item) { + return push.call(this, this.create(item, {parent: this})); + }.bind(this)); + } + NodeSet.prototype.traverse = function (visitor) { + var child; + void function (_iterator) { + try { + while (true) { + child = _iterator.next(); + visitor.call(child, child); + child.traverse(visitor); + } + } catch (e) { + if (e !== StopIteration) + throw e; + } + }.call(this, this.iterator()); + }; + NodeSet.prototype.toAST = function () { + return slice.call(this); + }; + return NodeSet; + }(Node); + defineProperties(NodeSet.prototype, { + iterator: {value: iterator}, + push: {value: push}, + slice: {value: slice}, + forEach: {value: forEach}, + indexOf: {value: indexOf} + }); + exports.Tree = Tree; +}); \ No newline at end of file diff --git a/lib/dumper.js b/lib/dumper.js deleted file mode 100644 index 01eda21..0000000 --- a/lib/dumper.js +++ /dev/null @@ -1,19 +0,0 @@ -if (typeof exports === 'object' && typeof define !== 'function') { - var define = function (factory) { - factory(require, exports); - }; -} -define(function (require, exports) { - var Tree = require("./esom/tree").Tree; - var dumpAst = exports.dumpAst = function (src, includeRanges) { - var program = Tree.create(src); - if (!includeRanges) { - var delRange = function (node) { - delete node.ast.range; - node.children.forEach(delRange); - }.bind(this); - delRange(program.root); - } - return JSON.stringify(program.ast, null, 2); - }; -}); \ No newline at end of file diff --git a/lib/esom/rel.js b/lib/esom/rel.js deleted file mode 100644 index d676697..0000000 --- a/lib/esom/rel.js +++ /dev/null @@ -1,32 +0,0 @@ -if (typeof exports === 'object' && typeof define !== 'function') { - var define = function (factory) { - factory(require, exports); - }; -} -define(function (require, exports) { - var Relatives = exports.Relatives = { - first: function () { - return this.children[0]; - }, - last: function () { - return this.children[this.children.length - 1]; - }, - next: function () { - var siblings = this.parent.children; - return siblings[siblings.indexOf(this) + 1]; - }, - prev: function () { - var siblings = this.parent.children; - return siblings[siblings.indexOf(this) - 1]; - }, - deepest: function () { - var deepest = []; - this.children.forEach(function (child) { - !child.children.length ? deepest.push(child) : child.deepest.forEach(function (child) { - return deepest.push(child); - }.bind(this)); - }.bind(this)); - return deepest; - } - }; -}); \ No newline at end of file diff --git a/lib/esom/trav.js b/lib/esom/trav.js deleted file mode 100644 index 1bad98a..0000000 --- a/lib/esom/trav.js +++ /dev/null @@ -1,173 +0,0 @@ -if (typeof exports === 'object' && typeof define !== 'function') { - var define = function (factory) { - factory(require, exports); - }; -} -define(function (require, exports) { - var queryPat = /((?:[\>|\+][\s]*)?(?=[\w|\.])(?:[A-Za-z]+)?(?:\.[A-Za-z]+)?(?:\[[\w]+(?:(?:[*|^|$]?=?(?!\]))(?:[0-9]+(?=\]))?(?:['"][\w]+['"](?=\]))?(?:true|false(?=\]))?)?\])*(?:\:(?!$)(?:[\w]+)(?:\((?:[\s\S]+)\))?)*)/g; - var queryMatch = /^(?:([\>|\+])[\s]*)?(?=[\w|\.])([A-Za-z]+)?(?:\.([A-Za-z]+))?((?:\[[\w]+(?:(?:[*|^|$]?=?(?!\]))(?:[0-9]+(?=\]))?(?:['"][\w]+['"](?=\]))?(?:true|false(?=\]))?)?\])*)((?:\:(?!$)(?:[\w]+)(?:\((?:[\s\S]+)\))?)*)$/; - var attrPat = /^([\w]+)(?:(?:([*|^|$]?=)?(?!\]))(?:([0-9]+)(?=\]))?(?:['"]([\w]+)['"](?=\]))?(?:(true|false)(?=\]))?)?\]$/; - function parse(selector) { - return new Query(queryMatch.exec(selector)); - } - var Query = function () { - function Query(dir) { - this.dir = dir; - this.ret = {}; - this.relative(); - this.key(); - this.type(); - this.properties(); - this.pseudos(); - return this.ret; - } - Query.prototype.relative = function () { - switch (this.dir[1]) { - case ">": - this.ret.child = true; - break; - case "+": - this.ret.sibling = true; - break; - } - }; - Query.prototype.key = function () { - if (this.dir[2]) - this.ret.key = this.dir[2]; - }; - Query.prototype.type = function () { - if (this.dir[3]) - this.ret.type = this.dir[3]; - }; - Query.prototype.properties = function () { - if (this.dir[4]) { - this.ret.properties = []; - this.dir[4].split("[").forEach(function (prop) { - if (prop) - this.property(prop); - }.bind(this)); - } - }; - Query.prototype.property = function (prop) { - var parts = attrPat.exec(prop); - var obj = {}; - if (parts && parts[1]) { - obj.property = parts[1]; - if (parts[2]) { - obj.operation = parts[2]; - if (parts[3]) - obj.value = Number(parts[3]); - else if (parts[4]) - obj.value = parts[4]; - else if (parts[5]) - obj.value = Boolean(parts[5]); - } - this.ret.properties.push(obj); - } - }; - Query.prototype.pseudos = function () { - var pat = /(?:\:([\w]+)(?:\(([\s\S]+)\))?)/g; - var pat2 = /(?:\:([\w]+)(?:\(([\s\S]+)\))?)/; - if (this.dir[5]) { - this.ret.pseudos = []; - this.dir[5].match(pat).forEach(function (seg) { - var parts = pat2.exec(seg); - var obj = {}; - if (parts && parts[1]) { - obj.pseudo = parts[1]; - if (parts[2]) - obj.argument = parts[2]; - this.ret.pseudos.push(obj); - } - }.bind(this)); - } - }; - return Query; - }(); - var Traversal = exports.Traversal = { - select: function (query, frags) { - var results = []; - var sels = query.match(queryPat); - var sel = sels.pop(); - var dir = parse(sel); - frags = frags || sels; - this.children.forEach(function (child) { - if (dir.child && child.matches(dir)) { - var pass = true; - var cur = child; - frags.reverse().forEach(function (frag) { - var dir = parse(frag); - if (pass & dir.child) { - if (cur.parent.matches(dir)) { - cur = cur.parent; - } else { - pass = false; - } - } - }.bind(this)); - if (pass) - results.push(child); - } else if (child.matches(sel)) { - results.push(child); - } - child.select(sel, frags).forEach(function (child) { - return results.push(child); - }.bind(this)); - }.bind(this)); - void function enhance(sel) { - if (sels.length) { - sel = sels.pop(); - results = results.filter(function (node) { - return node.closest(sel) ? true : false; - }.bind(this)); - enhance(); - } - }(); - return results; - }, - closest: function (selector) { - var dir = parse(selector); - var closest; - if (this.parent && this.parent !== this.root) { - closest = this.parent.matches(selector) ? this.parent : this.parent.closest(selector); - } - return closest; - }, - matches: function (dir) { - var match = true; - if (typeof dir === "string") - return this.matches(parse(dir)); - if (match && dir.key && this.key !== dir.key) - match = false; - if (match && dir.type && this.ast.type !== dir.type) - match = false; - if (dir.properties) - dir.properties.forEach(function (prop) { - if (match && prop.property && typeof this.ast[prop.property] === "undefined") - match = false; - if (match && prop.property && prop.operation && typeof prop.value !== "undefined") { - if (prop.operation === "=" && this.ast[prop.property] !== prop.value) - match = false; - else if (typeof this.ast[prop.property] === "string") { - switch (prop.operation) { - case "^=": - if (!this.ast[prop.property].match("^" + prop.value)) - match = false; - break; - case "$=": - if (!this.ast[prop.property].match(prop.value + "$")) - match = false; - break; - case "*=": - if (!~this.ast[prop.property].indexOf(prop.value)) - match = false; - break; - } - } - } - }.bind(this)); - return match; - } - }; - Object.define(Traversal, require("./rel").Relatives); -}); \ No newline at end of file diff --git a/lib/esom/tree.js b/lib/esom/tree.js deleted file mode 100644 index a2ba9b3..0000000 --- a/lib/esom/tree.js +++ /dev/null @@ -1,98 +0,0 @@ -if (typeof exports === 'object' && typeof define !== 'function') { - var define = function (factory) { - factory(require, exports); - }; -} -define(function (require, exports) { - var esprima = require("esprima-six"); - var parse = esprima.parse; - var Syntax = esprima.Syntax; - var Tree = function () { - function Tree(source, options) { - var ast = parse(source, {range: true}); - var children = []; - this.root = this; - this.source = source; - this.ast = ast; - this.children = children; - children.push(this.create({ - ast: ast, - key: "root", - type: "Node" - })); - var node = children[0]; - node.global = options && options.global; - return node; - } - Tree.prototype.create = function (base) { - var node = Object.create(this.root); - var parent = this; - var children = []; - Object.define(node, base); - node.climb(function (child) { - if (child.type === "Node" || child.type === "NodeSet" && child.ast.length) { - if (child.type === "NodeSet") { - child.ast.range = [ - child.ast[0].range[0], - child.ast[child.ast.length - 1].range[1] - ]; - } - children.push(node.create(child)); - } - }.bind(this)); - node.ast = base.ast; - node.parent = parent; - node.children = children; - Object.define(node, { - unshift: function (node) { - children.unshift(node); - }, - push: function (node) { - children.push(node); - } - }); - return node; - }; - Tree.prototype.climb = function (visit) { - var node = this.ast; - Object.keys(node).forEach(function (key) { - var ast = node[key], type; - if (ast && typeof ast === "object" && key !== "range") { - type = ast.type ? "Node" : Array.isArray(ast) ? "NodeSet" : "Unknown"; - visit({ - key: key, - ast: ast, - type: type - }); - } - }.bind(this)); - }; - Tree.prototype.visitByType = function (typeCallbacks) { - this.children.forEach(function (child) { - if (!child.ast) { - return; - } - var callback = typeCallbacks[child.ast.type]; - if (callback) { - callback(child); - } - child.visitByType(typeCallbacks); - }.bind(this)); - }; - Tree.prototype.raw = function () { - return this.source.substring(this.ast.range[0], this.ast.range[1]); - }; - Tree.prototype.isRoot = function () { - return this.parent === this.root; - }; - Tree.prototype.path = function () { - return this.isRoot() ? "" : this.parent.path + "." + this.key; - }; - return Tree; - }(); - Object.define(Tree, {create: function (src, options) { - return new this(src, options); - }}); - Object.define(Tree.prototype, require("./trav").Traversal); - exports.Tree = Tree; -}); \ No newline at end of file diff --git a/lib/filters.js b/lib/filters.js deleted file mode 100644 index 3da1f00..0000000 --- a/lib/filters.js +++ /dev/null @@ -1,8 +0,0 @@ -if (typeof exports === 'object' && typeof define !== 'function') { - var define = function (factory) { - factory(require, exports); - }; -} -define(function (require, exports) { - var filters = exports.filters = {"class": require("./filters/class").filter}; -}); \ No newline at end of file diff --git a/lib/filters/class.js b/lib/filters/class.js deleted file mode 100644 index 2718ebd..0000000 --- a/lib/filters/class.js +++ /dev/null @@ -1,3 +0,0 @@ -exports.filter = function anonymous(it) { -var out=''; var id = it.id ? it.id.compile() : "_Class"; var dec = it.type === "ClassDeclaration"; if(dec){out+='var '+( id)+' =';}out+='(function(';if(it.superClass){out+='_super';}out+=') {';if(it.superClass){out+='function __ctor() { this.constructor = '+( id)+'; }__ctor.prototype = _super.prototype;'+( id)+'.prototype = new __ctor();'+( id)+'.__super__ = _super.prototype;';}out+='function '+( id)+'(';if(it.constructor){if(it.constructor.value.params && it.constructor.value.params.ast){out+=( it.constructor.value.params.compile() );}out+=')'+( it.constructor.value.body.compile() );}else{out+='){}';}var arr1=it.methods;if(arr1){var method,index=-1,l1=arr1.length-1;while(index= this.elements.length) - throw StopIteration; - return this.elements[this.index++]; - } - }; - } - var hooks = { - ".Program": function (node) { - var compile = node.compile; - node.compile = function () { - var src = compile.call(node); - var body = generate(node.constructor.create(src).ast, { - format: { - indent: { - style: " ", - base: node.global ? 0 : 1 - }, - quotes: "double", - compact: false - }, - comment: true - }); - if (!node.global) { - body = "if (typeof exports === 'object' && typeof define !== 'function') {\n" + " var define = function (factory) {\n" + " factory(require, exports);\n" + " };\n" + "}\n" + "define(function (require, exports) {\n" + body + "\n});"; - } - return body; - }.bind(this); - }.bind(this), - ".ArrowFunctionExpression": function (node) { - node.compile = function () { - var ctx = node.context(); - var params = ctx.params.compile ? ctx.params.compile() : ""; - var body = ctx.body.compile(), body = ctx.expression ? function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "{return ", - "}" - ], - "raw": [ - "{return ", - "}" - ] - }, body) : body; - return function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "function(", - ")", - ".bind(this)" - ], - "raw": [ - "function(", - ")", - ".bind(this)" - ] - }, params, body); - }.bind(this); - }.bind(this), - ".Property[method=true]": function (node) { - node.compile = function () { - var ctx = node.context(); - var key = ctx.key.compile(); - var value = ctx.value; - var params = value.params && value.params.compile ? value.params.compile() : ""; - var body = value.body.compile(), body = value.expression ? function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "{return ", - "}" - ], - "raw": [ - "{return ", - "}" - ] - }, body) : body; - return function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "", - ":function(", - ")", - "" - ], - "raw": [ - "", - ":function(", - ")", - "" - ] - }, key, params, body); - }.bind(this); - }.bind(this), - ".BinaryExpression[operator^='is']": function (node) { - node.compile = function () { - return function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "(", - "function ( x, y ) { return (x === y)?( x !== 0 || 1/x === 1/y ) : ( x !== x && y !==y ) }( ", - ", ", - " ))" - ], - "raw": [ - "(", - "function ( x, y ) {\n return (x === y)?( x !== 0 || 1/x === 1/y ) : ( x !== x && y !==y )\n }( ", - ", ", - " ))" - ] - }, node.ast.operator === "isnt" ? "!" : "", node.first().compile(), node.last().compile()); - }.bind(this); - }.bind(this), - ".TemplateLiteral": function (node) { - node.compile = function () { - var it = node.context(); - var cooked = [], raw = []; - it.quasis.node.children.forEach(function (child) { - raw.push(child.ast.value.raw); - cooked.push(child.ast.value.cooked); - }.bind(this)); - return function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "(function(__quasi__){ var rawStrs = __quasi__['cooked']; var out = []; for (var i = 0, k = -1, n = rawStrs.length; i < n;) { out[++k] = rawStrs[i]; out[++k] = arguments[++i]; } return out.join(''); })( ", - " ", - " )" - ], - "raw": [ - "(function(__quasi__){\n var rawStrs = __quasi__['cooked'];\n var out = [];\n for (var i = 0, k = -1, n = rawStrs.length; i < n;) {\n out[++k] = rawStrs[i];\n out[++k] = arguments[++i];\n }\n return out.join('');\n })(\n ", - "\n ", - "\n )" - ] - }, JSON.stringify({ - cooked: cooked, - raw: raw - }), it.expressions && it.expressions.node && it.expressions.node.children.length ? "," + it.expressions.node.children.map(function (exp) { - return exp.compile(); - }).join(",") : ""); - }.bind(this); - }.bind(this) - }; - Array.prototype.map.call([ - hooks, - "./classes", - "./forof", - "./objectpattern", - "./modules", - "./restparams" - ], function (hook) { - Object.define(exports, typeof hook === "string" ? require(hook) : hook); - }.bind(this)); - Object.defineProperty(exports, "iterator", { - value: iterator, - enumerable: false - }); -}); \ No newline at end of file diff --git a/lib/hooks/classes.js b/lib/hooks/classes.js deleted file mode 100644 index 6b9cea5..0000000 --- a/lib/hooks/classes.js +++ /dev/null @@ -1,99 +0,0 @@ -if (typeof exports === 'object' && typeof define !== 'function') { - var define = function (factory) { - factory(require, exports); - }; -} -define(function (require, exports) { - var filters = require("../filters").filters; - function ClassRewrite(node) { - var ctx = node.context(); - var constructor; - var methods = []; - if (ctx.body && ctx.body.body && ctx.body.body.node) { - ctx.body.body.node.children.forEach(function (child) { - var sub = child.context(); - if (sub.key.node.matches(".Identifier[name='constructor']")) - constructor = sub; - else - methods.push(sub); - }.bind(this)); - } - ctx.constructor = constructor; - ctx.methods = methods; - return filters.class(ctx); - } - Object.define(exports, { - ".ClassDeclaration": function (node) { - node.compile = function () { - return ClassRewrite(node); - }.bind(this); - }.bind(this), - ".ClassExpression": function (node) { - node.compile = function () { - return ClassRewrite(node); - }.bind(this); - }.bind(this), - ".CallExpression > .MemberExpression > .Identifier[name='super']": function (node) { - var Call = node.closest(".CallExpression").context(); - var callee = Call.callee; - var args = Call.arguments; - if (args && args.compile) { - var argsc = args = args.compile(); - } - node.compile = function () { - return "this.constructor.__super__"; - }.bind(this); - callee.property.node.compile = function () { - return callee.property.name + ".call"; - }.bind(this); - if (args && args.node) - args.node.compile = function () { - return function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "this", - "" - ], - "raw": [ - "this", - "" - ] - }, args.node ? "," + argsc : ""); - }.bind(this); - }.bind(this), - ".CallExpression > callee[name='super']": function (node) { - var Call = node.parent.context(); - var args = Call.arguments; - if (args && args.compile) { - args = args.compile(); - } - Call.node.compile = function () { - return function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "this.constructor.__super__.constructor.call(this ", - ")" - ], - "raw": [ - "this.constructor.__super__.constructor.call(this ", - ")" - ] - }, args.node ? "," + args : ""); - }.bind(this); - }.bind(this) - }); -}); \ No newline at end of file diff --git a/lib/hooks/forof.js b/lib/hooks/forof.js deleted file mode 100644 index 64dce89..0000000 --- a/lib/hooks/forof.js +++ /dev/null @@ -1,89 +0,0 @@ -if (typeof exports === 'object' && typeof define !== 'function') { - var define = function (factory) { - factory(require, exports); - }; -} -define(function (require, exports) { - var hooks = {".ForOfStatement": function (node) { - node.compile = function () { - var context = node.context(); - var right = context.right.compile(); - var body = context.body.compile().replace(/^{([\s\S]*)}$/, "$1"); - var dec = context.left.matches(".VariableDeclaration[kind='var']"); - var decs = []; - var left = dec ? context.left.declarations.node.first().context() : context.left.node.context(); - if (left.type === "Identifier" || left.id && left.id.type === "Identifier") { - decs.push(left.compile()); - left = function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "", - " = _iterator.next()" - ], - "raw": [ - "", - " = _iterator.next()" - ] - }, left.compile()); - } else if (left.type === "VariableDeclarator" && left.id.type === "ObjectPattern") { - left.select(".ObjectPattern").forEach(function (node) { - decs = decs.concat(node.properties().map(function (prop) { - return prop.key; - }.bind(this))); - left = node.assemble("_iterator.next()"); - }.bind(this)); - } else { - left = function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "(", - ")" - ], - "raw": [ - "(", - ")" - ] - }, left.compile()); - } - return function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - " ", - " void function(_iterator){ try { while (true) { ", - " ", - " } } catch (e) { if (e !== StopIteration ) throw e } }.call(this, ", - ".iterator()); " - ], - "raw": [ - "\n ", - "\n void function(_iterator){\n try {\n while (true) {\n ", - "\n ", - "\n }\n } catch (e) { if (e !== StopIteration ) throw e }\n }.call(this, ", - ".iterator());\n " - ] - }, dec ? "var " + decs.join(", ") + ";" : "", left, body, right); - }.bind(this); - }.bind(this)}; - Object.define(exports, hooks); -}); \ No newline at end of file diff --git a/lib/hooks/modules.js b/lib/hooks/modules.js deleted file mode 100644 index 324ad07..0000000 --- a/lib/hooks/modules.js +++ /dev/null @@ -1,351 +0,0 @@ -if (typeof exports === 'object' && typeof define !== 'function') { - var define = function (factory) { - factory(require, exports); - }; -} -define(function (require, exports) { - var existsSync = require("fs").existsSync; - var sep = require("path").sep; - var hooks = { - ".ModuleDeclaration": function (node) { - var compile = node.compile; - node.compile = function () { - var ret = "var "; - var ctx = node.context(); - var from = ctx.from; - if (!from) - return compile.call(node); - if (function (x, y) { - return x === y ? x !== 0 || 1 / x === 1 / y : x !== x && y !== y; - }(from.type, "Literal")) { - var modRoot = from.value; - return function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "var ", - " = require(\"", - "\");" - ], - "raw": [ - "var ", - " = require(\"", - "\");" - ] - }, ctx.id.name, modRoot); - } else { - var modRoot = from.compile(); - return function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "var ", - " = ", - ";" - ], - "raw": [ - "var ", - " = ", - ";" - ] - }, ctx.id.name, modRoot); - } - }.bind(this); - }.bind(this), - ".ImportDeclaration": function (node) { - node.compile = function () { - var ret = "var "; - var ctx = node.context(); - var from = ctx.from; - if (function (x, y) { - return x === y ? x !== 0 || 1 / x === 1 / y : x !== x && y !== y; - }(from.type, "Literal")) { - var modRoot = from.value; - var modVarName = modRoot.replace(/[\/\.]/g, "_"); - modRoot = function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "require(\"", - "\")" - ], - "raw": [ - "require(\"", - "\")" - ] - }, modRoot); - } else { - from = from.context().body.node; - var modNames = from.children.map(function (path) { - return path.name; - }.bind(this)); - var modVarName = modNames.join("_"); - var modRoot = from.compile(); - } - var specifiers = ctx.specifiers.node.children; - if (function (x, y) { - return x === y ? x !== 0 || 1 / x === 1 / y : x !== x && y !== y; - }(specifiers.length, 1)) { - modVarName = modRoot; - } else { - ret += function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "", - " = ", - "" - ], - "raw": [ - "", - " = ", - "" - ] - }, modVarName, modRoot); - } - specifiers.forEach(function (spec) { - if (specifiers.length > 1) - ret += ", "; - var ctx = spec.context(); - if (function (x, y) { - return x === y ? x !== 0 || 1 / x === 1 / y : x !== x && y !== y; - }(ctx.type, "ImportSpecifier")) { - var name = ctx.id.name; - var from = ctx.from ? ctx.from.node.children[0].ast[0].name : name; - ret += function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "", - " = ", - ".", - "" - ], - "raw": [ - "", - " = ", - ".", - "" - ] - }, from, modVarName, name); - } else { - ret += function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "", - " = ", - ".", - "" - ], - "raw": [ - "", - " = ", - ".", - "" - ] - }, ctx.name, modVarName, ctx.name); - } - }.bind(this)); - return ret + ";"; - }.bind(this); - }.bind(this), - ".ExportDeclaration": function (node) { - var ctx = node.context(); - node.compile = function () { - var declaration = ctx.declaration; - if (!declaration) { - var ret = ""; - ctx.specifiers.node.children.forEach(function (value) { - var name = value.context().id.name; - ret += function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "exports.", - " = ", - ";" - ], - "raw": [ - "exports.", - " = ", - ";" - ] - }, name, name); - }.bind(this)); - return ret; - } - var exportee = declaration; - switch (exportee.type) { - case "FunctionDeclaration": - var name = exportee.id.name; - return function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "var ", - " = exports.", - " = function(" - ], - "raw": [ - "var ", - " = exports.", - " = function(" - ] - }, name, name) + (exportee.params[0] ? exportee.params.compile() : "") + function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - ") ", - ";\n" - ], - "raw": [ - ") ", - ";\\n" - ] - }, exportee.body.compile()); - case "VariableDeclaration": - var ret = ""; - exportee.declarations.children.forEach(function (value, idx) { - var declaration = value.context(); - var name = declaration.id.name; - ret += function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "var ", - " = exports.", - " = " - ], - "raw": [ - "var ", - " = exports.", - " = " - ] - }, name, name) + (declaration.init ? declaration.init.compile() : "null") + ";\n"; - }.bind(this)); - return ret; - case "ModuleDeclaration": - var from = exportee.from; - if (from) { - var name = exportee.id.name; - if (function (x, y) { - return x === y ? x !== 0 || 1 / x === 1 / y : x !== x && y !== y; - }(from.type, "Literal")) { - var modRoot = from.value; - return function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "var ", - " = exports.", - " = require(\"", - "\");" - ], - "raw": [ - "var ", - " = exports.", - " = require(\"", - "\");" - ] - }, name, name, modRoot); - } else { - var modRoot = fromcompile(); - return function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "var ", - " = exports.", - " = ", - ";" - ], - "raw": [ - "var ", - " = exports.", - " = ", - ";" - ] - }, name, name, modRoot); - } - } - default: - return ctx.declaration.compile(); - } - }.bind(this); - }.bind(this) - }; - Object.define(exports, hooks); -}); \ No newline at end of file diff --git a/lib/hooks/objectpattern.js b/lib/hooks/objectpattern.js deleted file mode 100644 index 40dc4f7..0000000 --- a/lib/hooks/objectpattern.js +++ /dev/null @@ -1,101 +0,0 @@ -if (typeof exports === 'object' && typeof define !== 'function') { - var define = function (factory) { - factory(require, exports); - }; -} -define(function (require, exports) { - var hooks = {".VariableDeclarator > id.ObjectPattern": function (node) { - node.properties = function () { - var ctx = node.parent.context(); - var props = []; - ctx.id.properties.node.children.forEach(function (child) { - var prop = child.context(); - var key = prop.key.compile(); - var value = prop.value.compile(); - props.push({ - key: key, - value: value - }); - }.bind(this)); - return props; - }.bind(this); - node.assemble = function (init) { - var ctx = node.parent.context(); - var props = node.properties(); - var result = ""; - if (!ctx.init || !ctx.init.matches(".Identifier") && props.length > 1) { - var first = props.shift(); - result += function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "", - " = ", - ", " - ], - "raw": [ - "", - " = ", - ", " - ] - }, first.key, init); - props.push(first); - init = first.key; - } - props = props.map(function (prop, index) { - return function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "", - " = ", - ".", - "" - ], - "raw": [ - "", - " = ", - ".", - "" - ] - }, prop.key, init, prop.value); - }.bind(this)); - return function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "", - "", - "" - ], - "raw": [ - "", - "", - "" - ] - }, result, props.join(", ")); - }.bind(this); - node.parent.compile = function () { - return node.assemble(node.parent.context().init.compile()); - }.bind(this); - }.bind(this)}; - Object.define(exports, hooks); -}); \ No newline at end of file diff --git a/lib/hooks/restparams.js b/lib/hooks/restparams.js deleted file mode 100644 index 73f9272..0000000 --- a/lib/hooks/restparams.js +++ /dev/null @@ -1,52 +0,0 @@ -if (typeof exports === 'object' && typeof define !== 'function') { - var define = function (factory) { - factory(require, exports); - }; -} -define(function (require, exports) { - var hooks = {".FunctionDeclaration": function (node) { - var ctx = node.context(); - if (!ctx.params.node) - return; - var params = ctx.params.node.children; - var lastIdx = params.length - 1; - var lastParam = params[lastIdx]; - if (lastParam.ast.type === "RestParameter") { - var restParamName = lastParam.ast.value.name; - params.pop(); - ctx.params.node.compile = function () { - return params.map(function (p) { - return p.context().name; - }.bind(this)).join(", "); - }.bind(this); - ctx.body.body.unshift({ - raw: function () { - return ""; - }, - compile: function () { - return function (__quasi__) { - var rawStrs = __quasi__["cooked"]; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(""); - }({ - "cooked": [ - "var ", - " = [].slice.call(arguments, ", - ");" - ], - "raw": [ - "var ", - " = [].slice.call(arguments, ", - ");" - ] - }, restParamName, lastIdx); - } - }); - } - }.bind(this)}; - Object.define(exports, hooks); -}); \ No newline at end of file diff --git a/lib/rewriter.js b/lib/rewriter.js deleted file mode 100644 index 262abb6..0000000 --- a/lib/rewriter.js +++ /dev/null @@ -1,90 +0,0 @@ -if (typeof exports === 'object' && typeof define !== 'function') { - var define = function (factory) { - factory(require, exports); - }; -} -define(function (require, exports) { - require("./es6"); - var Tree = require("./esom/tree").Tree; - var hooks = require("./hooks/base"); - var visitors = {}; - function optimizeHooks() { - var sels = Object.keys(hooks); - var optimizable = /^\.[a-zA-Z]+$/; - var sel; - void function (_iterator) { - try { - while (true) { - sel = _iterator.next(); - if (optimizable.exec(sel)) { - visitors[sel.substring(1)] = hooks[sel]; - delete hooks[sel]; - } - } - } catch (e) { - if (e !== StopIteration) - throw e; - } - }.call(this, sels.iterator()); - } - optimizeHooks(); - var rewrite = exports.rewrite = function (src, options) { - var program = Tree.create(src, options); - var selector, hook; - void function (_iterator) { - try { - while (true) { - selector = _iterator.next(), hook = selector.value, selector = selector.key; - program.root.select(selector).forEach(hook); - } - } catch (e) { - if (e !== StopIteration) - throw e; - } - }.call(this, hooks.iterator()); - program.root.visitByType(visitors); - return program.compile(); - }; - Object.define(Tree.prototype, { - compile: function () { - var src = this.raw(); - this.children.reverse().forEach(function (child) { - var raw = child.raw(); - var start = src.indexOf(raw); - var end = start + raw.length; - src = src.substring(0, start) + child.compile() + src.substring(end); - }.bind(this)); - return src; - }, - context: function () { - var ctx = new Context(this); - return ctx; - } - }); - var Context = function () { - function Context(node) { - var stack = Object.create(node); - var parent; - Object.define(stack, node.ast); - Object.define(stack, { - node: node, - get parent() { - parent ? parent : node.parent ? parent = node.parent.context() : undefined; - } - }); - if (stack.hasOwnProperty("loc")) - delete stack["loc"]; - node.children.forEach(function (child) { - var ctx; - Object.defineProperty(stack, child.key, { - get: function () { - return ctx ? ctx : ctx = child.context(); - }, - enumerable: true - }); - }.bind(this)); - return stack; - } - return Context; - }(); -}); \ No newline at end of file diff --git a/lib/six.js b/lib/six.js index 0e0a115..f253476 100644 --- a/lib/six.js +++ b/lib/six.js @@ -6,8 +6,7 @@ if (typeof exports === 'object' && typeof define !== 'function') { define(function (require, exports) { var fs = require("fs"); var path = require("path"); - var rewrite = require("./rewriter").rewrite; - var dumpAst = require("./dumper").dumpAst; + var rewrite = require("./core/rewriter").rewrite; var run = exports.run = function (code, options) { var mainModule = require.main; if (!options) diff --git a/src/browser.six b/src/browser.six index f3f62fa..f8447e3 100644 --- a/src/browser.six +++ b/src/browser.six @@ -3,56 +3,56 @@ module Six = "./six" Six.require = require Six.eval = function(code, options) { - return eval(Six.compile(code, options)) + return eval(Six.compile(code, options)) } Six.run = function(code, options) { - Function(Six.compile(code, options || {global:true}))() + Function(Six.compile(code, options || {global:true}))() } // Load a remote script from the current domain via XHR. Six.load = function(url, callback) { - var xhr = window.ActiveXObject - ? new window.ActiveXObject('Microsoft.XMLHTTP') - : new XMLHttpRequest() - - xhr.open('GET', url, true) - if ('overrideMimeType' in xhr) xhr.overrideMimeType('text/plain') - xhr.onreadystatechange = function() { - if ( xhr.readyState === 4 ) { - if ( xhr.status === 200 || xhr.status === 0 ) Six.run(xhr.responseText) - else throw new Error("Could not load " + url) - callback && callback() + var xhr = window.ActiveXObject + ? new window.ActiveXObject('Microsoft.XMLHTTP') + : new XMLHttpRequest() + + xhr.open('GET', url, true) + if ('overrideMimeType' in xhr) xhr.overrideMimeType('text/plain') + xhr.onreadystatechange = function() { + if ( xhr.readyState === 4 ) { + if ( xhr.status === 200 || xhr.status === 0 ) Six.run(xhr.responseText) + else throw new Error("Could not load " + url) + callback && callback() + } } - } - xhr.send(null) + xhr.send(null) } // Activate Six in the browser by having it compile and evaluate // all script tags with a content-type of `text/six`. // This happens on page load. var runScripts = function() { - var scripts = document.getElementsByTagName('script') - var sixes = [] - sixes.forEach.call(scripts, s => s.type === 'text/six' && sixes.push(s)) - - var index = 0 - var length = sixes.length - - var execute = () => { - var script = sixes[index++] - if ( script && script.type === 'text/six'){ - if ( script.src ) Six.load(script.src, execute) - else { - Six.run(script.innerHTML) - execute() - } + var scripts = document.getElementsByTagName('script') + var sixes = [] + sixes.forEach.call(scripts, s => s.type === 'text/six' && sixes.push(s)) + + var index = 0 + var length = sixes.length + + var execute = () => { + var script = sixes[index++] + if ( script && script.type === 'text/six'){ + if ( script.src ) Six.load(script.src, execute) + else { + Six.run(script.innerHTML) + execute() + } + } } - } - execute() + execute() - return null + return null } // Listen for window load, both in browsers and in IE. diff --git a/src/command.six b/src/command.six index c38530d..0a1a30f 100644 --- a/src/command.six +++ b/src/command.six @@ -25,24 +25,24 @@ var hidden = function(file) { return /^\.|~$/.test(file) } // The list of all the valid option flags that `six` knows how to handle. var SWITCHES = [ - ['-b', '--bare', 'compile without a top-level function wrapper'], - ['-c', '--compile', 'compile to JavaScript and save as .js files'], - ['-e', '--eval', 'pass a string from the command line as input'], - ['-g', '--global', 'put code directly into global scope rather than UMD define'], - ['-h', '--help', 'display this help message'], - ['-i', '--interactive', 'run an interactive Six REPL'], - ['-j', '--join [FILE]', 'concatenate the source Six before compiling'], - ['-l', '--lint', 'pipe the compiled JavaScript through JavaScript Lint'], - ['-n', '--nodes', 'print out the parse tree that the parser produces'], - [ '--nodejs [ARGS]', 'pass options directly to the "node" binary'], - ['-o', '--output [DIR]', 'set the output directory for compiled JavaScript'], - ['-p', '--print', 'print out the compiled JavaScript'], - ['-r', '--require [FILE*]', 'require a library before executing your script'], - ['-s', '--stdio', 'listen for and compile scripts over stdio'], - ['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce'], - ['-v', '--version', 'display the version number'], - ['-V', '--verbose', 'increase verbosity'], - ['-w', '--watch', 'watch scripts for changes and rerun commands'] + ['-b', '--bare', 'compile without a top-level function wrapper'], + ['-c', '--compile', 'compile to JavaScript and save as .js files'], + ['-e', '--eval', 'pass a string from the command line as input'], + ['-g', '--global', 'put code directly into global scope rather than UMD define'], + ['-h', '--help', 'display this help message'], + ['-i', '--interactive', 'run an interactive Six REPL'], + ['-j', '--join [FILE]', 'concatenate the source Six before compiling'], + ['-l', '--lint', 'pipe the compiled JavaScript through JavaScript Lint'], + ['-n', '--nodes', 'print out the parse tree that the parser produces'], + [ '--nodejs [ARGS]', 'pass options directly to the "node" binary'], + ['-o', '--output [DIR]', 'set the output directory for compiled JavaScript'], + ['-p', '--print', 'print out the compiled JavaScript'], + ['-r', '--require [FILE*]', 'require a library before executing your script'], + ['-s', '--stdio', 'listen for and compile scripts over stdio'], + ['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce'], + ['-v', '--version', 'display the version number'], + ['-V', '--verbose', 'increase verbosity'], + ['-w', '--watch', 'watch scripts for changes and rerun commands'] ] // Top-level objects shared by all the functions. @@ -57,328 +57,328 @@ var optionParser = null // Many flags cause us to divert before compiling anything. Flags passed after // `--` will be passed verbatim to your script as arguments in `process.argv` export function run() { - parseOptions() - if ( opts.nodejs ) return forkNode() - if ( opts.help ) return usage() - if ( opts.version ) return version() - if ( opts.require ) loadRequires() - if ( opts.interactive ) return require('./repl') - if ( opts.watch && !fs.watch ) { - return printWarn("The --watch feature depends on Node v0.6.0+. You are running " + process.version + ".") - } - if ( opts.stdio ) return compileStdio() - if ( opts.eval ) return compileScript(null, sources[0]) - if ( !sources.length ) return require('./repl') - var literals = opts.run ? sources.splice(1) : [] - - process.argv = process.argv.slice(0, 2).concat(literals) - process.argv[0] = 'six' - process.execPath = require.main.filename - - sources.forEach(function(source){ - compilePath(source, true, path.normalize(source)) - }) + parseOptions() + if ( opts.nodejs ) return forkNode() + if ( opts.help ) return usage() + if ( opts.version ) return version() + if ( opts.require ) loadRequires() + if ( opts.interactive ) return require('./repl') + if ( opts.watch && !fs.watch ) { + return printWarn("The --watch feature depends on Node v0.6.0+. You are running " + process.version + ".") + } + if ( opts.stdio ) return compileStdio() + if ( opts.eval ) return compileScript(null, sources[0]) + if ( !sources.length ) return require('./repl') + var literals = opts.run ? sources.splice(1) : [] + + process.argv = process.argv.slice(0, 2).concat(literals) + process.argv[0] = 'six' + process.execPath = require.main.filename + + sources.forEach(function(source){ + compilePath(source, true, path.normalize(source)) + }) } // Compile a path, which could be a script or a directory. If a directory // is passed, recursively compile all '.six' extension source files in it // and all subdirectories. var compilePath = function(source, topLevel, base) { - fs.stat(source, function(err, stats) { - - if (err && err.code !== 'ENOENT') throw err - - if ((err != null ? err.code : void 0) === 'ENOENT') { - if (topLevel && source.slice(-4) !== '.six') { - source = sources[sources.indexOf(source)] = "" + source + ".six" - return compilePath(source, topLevel, base) - } - if (topLevel) { - console.error("File not found: " + source) - process.exit(1) - } - return - } - - - if (stats.isDirectory()) { - if (opts.watch) watchDir(source, base) - fs.readdir(source, function(err, files){ - var file + fs.stat(source, function(err, stats) { if (err && err.code !== 'ENOENT') throw err - if ((err != null ? err.code : void 0) === 'ENOENT') return - var index = sources.indexOf(source) - files = files.filter(function(file) { return !hidden(file) }) + if ((err != null ? err.code : void 0) === 'ENOENT') { + if (topLevel && source.slice(-4) !== '.six') { + source = sources[sources.indexOf(source)] = "" + source + ".six" + return compilePath(source, topLevel, base) + } + if (topLevel) { + console.error("File not found: " + source) + process.exit(1) + } + return + } + - var _ref1 - [].splice.apply(sources, [index, index - index + 1].concat(_ref1 = (function() { - var _i, _len, _results - _results = [] - for (_i = 0, _len = files.length; _i < _len; _i++) { - file = files[_i] - _results.push(path.join(source, file)) - } - return _results - })())), _ref1 - - var _ref2 - [].splice.apply(sourceCode, [index, index - index + 1].concat(_ref2 = files.map(function() { - return null - }))), _ref2 - - return files.forEach(function(file) { - return compilePath(path.join(source, file), false, base) - }) - }) - } else if (topLevel || path.extname(source) === '.six') { - if (opts.watch) watch(source, base) - fs.readFile(source, function(err, code) { - if (err && err.code !== 'ENOENT') throw err - if ((err != null ? err.code : void 0) === 'ENOENT') return - return compileScript(source, code.toString(), base) - }) - } else { - notSources[source] = true - return removeSource(source, base) - } - }) + if (stats.isDirectory()) { + if (opts.watch) watchDir(source, base) + fs.readdir(source, function(err, files){ + var file + + if (err && err.code !== 'ENOENT') throw err + if ((err != null ? err.code : void 0) === 'ENOENT') return + + var index = sources.indexOf(source) + files = files.filter(function(file) { return !hidden(file) }) + + var _ref1 + [].splice.apply(sources, [index, index - index + 1].concat(_ref1 = (function() { + var _i, _len, _results + _results = [] + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i] + _results.push(path.join(source, file)) + } + return _results + })())), _ref1 + + var _ref2 + [].splice.apply(sourceCode, [index, index - index + 1].concat(_ref2 = files.map(function() { + return null + }))), _ref2 + + return files.forEach(function(file) { + return compilePath(path.join(source, file), false, base) + }) + }) + } else if (topLevel || path.extname(source) === '.six') { + if (opts.watch) watch(source, base) + fs.readFile(source, function(err, code) { + if (err && err.code !== 'ENOENT') throw err + if ((err != null ? err.code : void 0) === 'ENOENT') return + return compileScript(source, code.toString(), base) + }) + } else { + notSources[source] = true + return removeSource(source, base) + } + }) } // Compile a single source script, containing the given code, according to the // requested options. If evaluating the script directly sets `__filename`, // `__dirname` and `module.filename` to be correct relative to the script's path. var compileScript = function(file, input, base) { - var o = opts - var options = compileOptions(file) - try { - - t = task = { - file: file, - input: input, - options: options - } - - six.emit('compile', task) - if (o.tokens) printTokens(six.tokens(t.input)) - else if (o.nodes) printLine(six.nodes(t.input, t.options)) - else if (o.run) six.run(t.input, t.options) - else if (o.join && t.file !== o.join) { - sourceCode[sources.indexOf(t.file)] = t.input - compileJoin() - } else { - t.output = six.compile(t.input, t.options) - - six.emit('success', task) - if (o.print) printLine(t.output.trim()) - else if (o.compile) writeJs(t.file, t.output, base) - else if (o.lint) lint(t.file, t.output) + var o = opts + var options = compileOptions(file) + try { + + t = task = { + file: file, + input: input, + options: options + } + + six.emit('compile', task) + if (o.tokens) printTokens(six.tokens(t.input)) + else if (o.nodes) printLine(six.nodes(t.input, t.options)) + else if (o.run) six.run(t.input, t.options) + else if (o.join && t.file !== o.join) { + sourceCode[sources.indexOf(t.file)] = t.input + compileJoin() + } else { + t.output = six.compile(t.input, t.options) + + six.emit('success', task) + if (o.print) printLine(t.output.trim()) + else if (o.compile) writeJs(t.file, t.output, base) + else if (o.lint) lint(t.file, t.output) + } + } catch (err) { + six.emit('failure', err, task) + if (six.listeners('failure').length) return + if (o.watch) return printLine(err.message + '\x07') + printWarn(err instanceof Error && err.stack || ("ERROR: " + err)) + return process.exit(1) } - } catch (err) { - six.emit('failure', err, task) - if (six.listeners('failure').length) return - if (o.watch) return printLine(err.message + '\x07') - printWarn(err instanceof Error && err.stack || ("ERROR: " + err)) - return process.exit(1) - } } // Watch a source Six file using `fs.watch`, recompiling it every // time the file is updated. May be used in combination with other options, // such as `--lint` or `--print`. var watch = function(source, base) { - var watcher - var prevStats = null - var compileTimeout = null - - var watchErr = function(e) { - if (e.code === 'ENOENT') { - if (sources.indexOf(source) === -1) return - try { - rewatch() - compile() - } catch (e) { - removeSource(source, base, true) - compileJoin() - } - } else { throw e } - } - - var compile = function() { - clearTimeout(compileTimeout) - compileTimeout = wait(25, function(){ - fs.stat(source, function(err, stats) { - if (err) return watchErr(err) - - if (prevStats && - stats.size === prevStats.size && - stats.mtime.getTime() === prevStats.mtime.getTime() - ) return rewatch() - - prevStats = stats - fs.readFile(source, function(err, code) { - if (err) return watchErr(err) - compileScript(source, code.toString(), base) - rewatch() + var watcher + var prevStats = null + var compileTimeout = null + + var watchErr = function(e) { + if (e.code === 'ENOENT') { + if (sources.indexOf(source) === -1) return + try { + rewatch() + compile() + } catch (e) { + removeSource(source, base, true) + compileJoin() + } + } else { throw e } + } + + var compile = function() { + clearTimeout(compileTimeout) + compileTimeout = wait(25, function(){ + fs.stat(source, function(err, stats) { + if (err) return watchErr(err) + + if (prevStats && + stats.size === prevStats.size && + stats.mtime.getTime() === prevStats.mtime.getTime() + ) return rewatch() + + prevStats = stats + fs.readFile(source, function(err, code) { + if (err) return watchErr(err) + compileScript(source, code.toString(), base) + rewatch() + }) + }) }) - }) - }) - } - - try { - watcher = fs.watch(source, compile) - } catch (e) { - watchErr(e) - } - - var rewatch = function() { - watcher && watcher.close() - watcher = fs.watch(source, compile) - } + } + + try { + watcher = fs.watch(source, compile) + } catch (e) { + watchErr(e) + } + + var rewatch = function() { + watcher && watcher.close() + watcher = fs.watch(source, compile) + } } // Watch a directory of files for new additions. var watchDir = function(source, base) { - var watcher - var readdirTimeout = null - try { - watcher = fs.watch(source, function(){ - clearTimeout(readdirTimeout) - readdirTimeout = wait(25, function(){ - fs.readdir(source, function(err, files) { - if (err) { - if (err && err.code !== 'ENOENT') throw err - watcher.close() - return unwatchDir(source, base) - } - files.forEach(function(file){ - if (!(!hidden(file) && !notSources[file])){ - file = path.join(source, file) - if (sources.some(function(s){ s.indexOf(file) >= 0 })) { - sources.push(file) - sourceCode.push(null) - compilePath(file, false, base) - } - } - }) + var watcher + var readdirTimeout = null + try { + watcher = fs.watch(source, function(){ + clearTimeout(readdirTimeout) + readdirTimeout = wait(25, function(){ + fs.readdir(source, function(err, files) { + if (err) { + if (err && err.code !== 'ENOENT') throw err + watcher.close() + return unwatchDir(source, base) + } + files.forEach(function(file){ + if (!(!hidden(file) && !notSources[file])){ + file = path.join(source, file) + if (sources.some(function(s){ s.indexOf(file) >= 0 })) { + sources.push(file) + sourceCode.push(null) + compilePath(file, false, base) + } + } + }) + }) + }) }) - }) - }) - } catch (e) { - if (e.code !== 'ENOENT') throw e - } + } catch (e) { + if (e.code !== 'ENOENT') throw e + } } var unwatchDir = function(source, base) { - var file, prevSources, toRemove, _i, _len - prevSources = sources.slice(0) - toRemove = (function() { - var _i, _len, _results - _results = [] - for (_i = 0, _len = sources.length; _i < _len; _i++) { - file = sources[_i] - if (file.indexOf(source) >= 0) { - _results.push(file) - } + var file, prevSources, toRemove, _i, _len + prevSources = sources.slice(0) + toRemove = (function() { + var _i, _len, _results + _results = [] + for (_i = 0, _len = sources.length; _i < _len; _i++) { + file = sources[_i] + if (file.indexOf(source) >= 0) { + _results.push(file) + } + } + return _results + })(); + for (_i = 0, _len = toRemove.length; _i < _len; _i++) { + file = toRemove[_i] + removeSource(file, base, true) } - return _results - })(); - for (_i = 0, _len = toRemove.length; _i < _len; _i++) { - file = toRemove[_i] - removeSource(file, base, true) - } - if (!sources.some(function(s, i) { - return prevSources[i] !== s - })) { - return - } - return compileJoin() + if (!sources.some(function(s, i) { + return prevSources[i] !== s + })) { + return + } + return compileJoin() } // Remove a file from our source list, and source code cache. Optionally remove // the compiled JS version as well. var removeSource = function(source, base, removeJs) { - var index = sources.indexOf(source) - sources.splice(index, 1) - sourceCode.splice(index, 1) - if (removeJs && !opts.join) { - var jsPath = outputPath(source, base) - exists(jsPath, function(itExists) { - if (itExists) { - fs.unlink(jsPath, function(err) { - if (err && err.code !== 'ENOENT') throw err - return timeLog("removed " + source) + var index = sources.indexOf(source) + sources.splice(index, 1) + sourceCode.splice(index, 1) + if (removeJs && !opts.join) { + var jsPath = outputPath(source, base) + exists(jsPath, function(itExists) { + if (itExists) { + fs.unlink(jsPath, function(err) { + if (err && err.code !== 'ENOENT') throw err + return timeLog("removed " + source) + }) + } }) - } - }) - } + } } // Get the corresponding output JavaScript path for a source file. var outputPath = function(source, base) { - var filename = path.basename(source, path.extname(source)) + '.js' - var srcDir = path.dirname(source) - var baseDir = (base === '.') ? srcDir : srcDir.substring(base.length) - var dir = (opts.output) ? path.join(opts.output, baseDir) : srcDir - return path.join(dir, filename) + var filename = path.basename(source, path.extname(source)) + '.js' + var srcDir = path.dirname(source) + var baseDir = (base === '.') ? srcDir : srcDir.substring(base.length) + var dir = (opts.output) ? path.join(opts.output, baseDir) : srcDir + return path.join(dir, filename) } // Write out a JavaScript source file with the compiled code. By default, files // are written out in `cwd` as `.js` files with the same name, but the output // directory can be customized with `--output`. var writeJs = function(source, js, base) { - var jsPath = outputPath(source, base) - var jsDir = path.dirname(jsPath) - - var compile = function(){ - if (js.length <= 0) js = ' ' - fs.writeFile(jsPath, js, function(err) { - if (err) printLine(err.message) - else if (opts.compile && opts.watch) timeLog("compiled " + source) + var jsPath = outputPath(source, base) + var jsDir = path.dirname(jsPath) + + var compile = function(){ + if (js.length <= 0) js = ' ' + fs.writeFile(jsPath, js, function(err) { + if (err) printLine(err.message) + else if (opts.compile && opts.watch) timeLog("compiled " + source) + }) + } + exists(jsDir, function(itExists) { + if (itExists) compile() + else exec("mkdir -p " + jsDir, compile) }) - } - exists(jsDir, function(itExists) { - if (itExists) compile() - else exec("mkdir -p " + jsDir, compile) - }) } // Convenience for cleaner setTimeouts. var wait = function(milliseconds, func) { return setTimeout(func, milliseconds) } var timeLog = function(message) { - return console.log("" + ((new Date).toLocaleTimeString()) + " - " + message) + return console.log("" + ((new Date).toLocaleTimeString()) + " - " + message) } var parseOptions = function() { - var i, o, source, _i, _len; - optionParser = new optparse.OptionParser(SWITCHES, '') - o = opts = optionParser.parse(process.argv.slice(2)) - o.compile || (o.compile = !!o.output) - o.run = !(o.compile || o.print || o.lint) - o.print = !!(o.print || (o["eval"] || o.stdio && o.compile)) - sources = o["arguments"] - for (i = _i = 0, _len = sources.length; _i < _len; i = ++_i) { - source = sources[i] - sourceCode[i] = null - } + var i, o, source, _i, _len; + optionParser = new optparse.OptionParser(SWITCHES, '') + o = opts = optionParser.parse(process.argv.slice(2)) + o.compile || (o.compile = !!o.output) + o.run = !(o.compile || o.print || o.lint) + o.print = !!(o.print || (o["eval"] || o.stdio && o.compile)) + sources = o["arguments"] + for (i = _i = 0, _len = sources.length; _i < _len; i = ++_i) { + source = sources[i] + sourceCode[i] = null + } } var compileOptions = function(filename) { - return { - filename: filename, - bare: opts.bare, - header: opts.compile, - verbose: opts.verbose, - global: opts.global - } + return { + filename: filename, + bare: opts.bare, + header: opts.compile, + verbose: opts.verbose, + global: opts.global + } } var usage = function() { - return printLine((new optparse.OptionParser(SWITCHES, '')).help()) + return printLine((new optparse.OptionParser(SWITCHES, '')).help()) } var version = function() { - return printLine("SIX version 0.0.x") + return printLine("SIX version 0.0.x") } diff --git a/src/core/es6.six b/src/core/es6.six new file mode 100644 index 0000000..0261750 --- /dev/null +++ b/src/core/es6.six @@ -0,0 +1,32 @@ +global.StopIteration = {} + +// Object static extensions +Object.defineProperties(global.Object, { + + define: { + value(target, source) { + var desc = {} + Object.keys(source).forEach(key => desc[key] = Object.getOwnPropertyDescriptor(source, key)) + Object.defineProperties(target, desc) + return target + }, + enumerable: false, + writable: true, + configurable: true + } + +}) + +Object.defineProperty(Array.prototype, "iterator", { + value() { + return { + elements: this, + index: 0, + next: function() { + if (this.index >= this.elements.length) + throw StopIteration + return this.elements[this.index++] + } + } + } +}) \ No newline at end of file diff --git a/src/core/hooks.six b/src/core/hooks.six new file mode 100644 index 0000000..38d511a --- /dev/null +++ b/src/core/hooks.six @@ -0,0 +1,25 @@ +module esprima = "esprima-six"; + +import parse from esprima; + +export var hooks = []; + +hooks.push(tree => { + + var { egal: expression } = parse("(function ( x, y ) { return (x === y)?( x !== 0 || 1/x === 1/y ) : ( x !== x && y !==y )})()").body[0]; + + var egaller = function(left, right) { + return { + type: egal.type, + arguments: [left, right], + callee: egal.callee + } + } + + tree.traverse(node => { + if( node.type === "BinaryExpression" && /^is/.test(node.operator) ) { + node.overload(egaller(node.left.toAST(), node.right.toAST())); + } + }); + +}); \ No newline at end of file diff --git a/src/core/rewriter.six b/src/core/rewriter.six new file mode 100644 index 0000000..0c38c68 --- /dev/null +++ b/src/core/rewriter.six @@ -0,0 +1,31 @@ +require("./es6"); + +module esprima = "esprima-six"; + +import parse from esprima; +import { generate: esgen } from "escodegen"; + +import Tree from "./tree"; + +import hooks from "./hooks"; + +export var config = { + format: { + indent: { + style: " " + }, + quotes: "double", + compact: false + }, + comment: true +}; + +export function rewrite(src, options) { + var sourceTree = new Tree( parse(src), options ); + + for( var hook of hooks ) { + hook(sourceTree, options); + } + + return esgen( sourceTree.toAST(), config ); +} diff --git a/src/core/tree.six b/src/core/tree.six new file mode 100644 index 0000000..9468155 --- /dev/null +++ b/src/core/tree.six @@ -0,0 +1,123 @@ +import isArray from Array; + +import push from Array.prototype; +import slice from Array.prototype; +import iterator from Array.prototype; +import indexOf from Array.prototype; +import forEach from Array.prototype; + +import keys from Object; +import defineProperty from Object; +import defineProperties from Object; + +class Tree { + constructor( ast, options ) { + this.root = new Node( ast ); + } + traverse( visitor ) { + visitor.call(this.root, this.root); + this.root.traverse(visitor); + } + toAST() { + return this.root.toAST(); + } +} + +class Node { + constructor( ast, opts ) { + opts || (opts = {}); + + defineProperties(this, { + children: { value: new NodeSet(null, { parent: this, key: "children" }) }, + nodeType: { value: "Node" }, + nodeKey: { value: opts.key || null }, + parent: { value: opts.parent || null } + }); + + this.set(ast); + } + create( ast, opts ) { + return new ( isArray(ast) ? NodeSet : Node )( ast, opts ) + } + clean() { + for( var { key } of this ) { + delete this[key]; + } + this.children = new NodeSet(null, { parent: this, key: "children" }); + } + set( ast ) { + for( var key of keys(ast) ) { + if( typeof ast[key] === "object" && key !== "range" && ast[key] !== null) { + this.append( this[key] = this.create(ast[key], { parent: this, key }) ); + } else { + this[key] = ast[key]; + } + } + } + overload( ast ) { + this.clean(); + this.set(ast); + } + append( node ) { + push.call(this.children, node); + } + traverse( visitor ) { + for( var child of this.children ) { + visitor.call(child, child); + child.traverse(visitor); + } + } + iterator() { + return { + elements: keys(this).map( key => ({ key, value: this[key] }) ), + index: 0, + next() { + if( this.index >= this.elements.length ) throw StopIteration; + return this.elements[this.index++]; + } + } + } + toAST() { + var ast = {}; + + for( var { key, value } of this ) { + ast[key] = typeof value === "object" ? value.toAST() : value; + } + + return ast; + } +} + +class NodeSet extends Node { + constructor( items, opts ) { + opts || (opts = {}); + + defineProperties(this, { + nodeType: { value: "NodeSet" }, + nodeKey: { value: opts.key || null }, + parent: { value: opts.parent || null } + }); + + this.length = 0; + items && items.forEach( item => push.call(this, this.create(item, { parent: this })) ); + } + traverse( visitor ) { + for( var child of this ) { + visitor.call(child, child); + child.traverse(visitor); + } + } + toAST() { + return slice.call(this); + } +} + +defineProperties(NodeSet.prototype, { + iterator: { value: iterator }, + push: { value: push }, + slice: { value: slice }, + forEach: { value: forEach }, + indexOf: { value: indexOf } +}); + +export Tree; diff --git a/src/dumper.six b/src/dumper.six deleted file mode 100644 index 9c5a125..0000000 --- a/src/dumper.six +++ /dev/null @@ -1,15 +0,0 @@ -import Tree from "./esom/tree" - -export function dumpAst(src, includeRanges) { - var program = Tree.create(src) - - if (! includeRanges) { - var delRange = (node) => { - delete node.ast.range - node.children.forEach(delRange) - } - delRange(program.root) - } - - return JSON.stringify(program.ast, null, 2) -} diff --git a/src/es6.six b/src/es6.six deleted file mode 100644 index 00e1fed..0000000 --- a/src/es6.six +++ /dev/null @@ -1,30 +0,0 @@ -global.StopIteration = {} - -// Object static extensions -Object.defineProperties(global.Object, { - - define: { - value(target, source) { - var desc = {} - Object.keys(source).forEach(key => desc[key] = Object.getOwnPropertyDescriptor(source, key)) - Object.defineProperties(target, desc) - return target - }, - enumerable: false, - writable: true, - configurable: true - } - -}) - -Array.prototype.iterator = function() { - return { - elements: this, - index: 0, - next: function() { - if (this.index >= this.elements.length) - throw StopIteration - return this.elements[this.index++] - } - } -} \ No newline at end of file diff --git a/src/esom/rel.six b/src/esom/rel.six deleted file mode 100644 index 4ad824b..0000000 --- a/src/esom/rel.six +++ /dev/null @@ -1,27 +0,0 @@ -export var Relatives = { - - first() this.children[ 0 ], - last() this.children[ this.children.length -1 ], - - next() { - var siblings = this.parent.children - return siblings[siblings.indexOf(this) + 1] - }, - - prev() { - var siblings = this.parent.children - return siblings[siblings.indexOf(this) - 1] - }, - - deepest() { - var deepest = [] - - this.children.forEach(child => { - !child.children.length ? deepest.push(child) - : child.deepest.forEach( child => deepest.push(child)) - }) - - return deepest - } - -} diff --git a/src/esom/trav.six b/src/esom/trav.six deleted file mode 100644 index 78a752b..0000000 --- a/src/esom/trav.six +++ /dev/null @@ -1,181 +0,0 @@ - -var queryPat = /((?:[\>|\+][\s]*)?(?=[\w|\.])(?:[A-Za-z]+)?(?:\.[A-Za-z]+)?(?:\[[\w]+(?:(?:[*|^|$]?=?(?!\]))(?:[0-9]+(?=\]))?(?:['"][\w]+['"](?=\]))?(?:true|false(?=\]))?)?\])*(?:\:(?!$)(?:[\w]+)(?:\((?:[\s\S]+)\))?)*)/g - -var queryMatch = /^(?:([\>|\+])[\s]*)?(?=[\w|\.])([A-Za-z]+)?(?:\.([A-Za-z]+))?((?:\[[\w]+(?:(?:[*|^|$]?=?(?!\]))(?:[0-9]+(?=\]))?(?:['"][\w]+['"](?=\]))?(?:true|false(?=\]))?)?\])*)((?:\:(?!$)(?:[\w]+)(?:\((?:[\s\S]+)\))?)*)$/ - -/*var queryPat2 = /(?:(?:[\s]*(?=[\S]))?([\+|>])?(?:[\s]*(?=[\S]))?([A-Za-z]+)?(?:\.([A-Za-z]+))?((?:\[[\w]+(?:(?:([*|^|$]?=)?(?!\]))(?:[0-9]+(?=\]))?(?:['"][\w]+['"](?=\]))?(?:true|false(?=\]))?)?\])*)((?:\:(?!$)(?:[\w]+)(?:\((?:[\s\S]+){1}\))?)*)[\s]*)/g*/ - -/*var tagPat = "([A-Za-z]+)?" -var classPat = "(?:\.([A-Za-z]+))?" -var relPat = "(?:([\>|\+])[\s]*)?(?=[\w|\.])" -var propPat = "(?:\[[\w]+(?:(?:[*|^|$]?=?(?!\]))(?:[0-9]+(?=\]))?(?:['\"][\w]+['\"](?=\]))?(?:true|false(?=\]))?)?\])*" -var pseudoPat = "(?:\:(?!$)(?:[\w]+)(?:\((?:[\s\S]+)\))?)*"*/ - -var attrPat = /^([\w]+)(?:(?:([*|^|$]?=)?(?!\]))(?:([0-9]+)(?=\]))?(?:['"]([\w]+)['"](?=\]))?(?:(true|false)(?=\]))?)?\]$/ - -function parse(selector) { - return new Query(queryMatch.exec(selector)) -} - -class Query { - - /* - 1: Relative - 2: Tag - 3: Class - 4: Attributes - 5: Pseudos - */ - - constructor(dir) { - this.dir = dir - this.ret = {} - - this.relative() - this.key() - this.type() - this.properties() - this.pseudos() - - return this.ret - } - - relative() { - switch ( this.dir[1] ) { - case ">": this.ret.child = true; break - case "+": this.ret.sibling = true; break - } - } - - key() { if ( this.dir[2] ) this.ret.key = this.dir[2] } - type() { if ( this.dir[3] ) this.ret.type = this.dir[3] } - - properties() { - if ( this.dir[4] ) { - this.ret.properties = [] - - this.dir[4].split("[").forEach(prop => { - if ( prop ) this.property(prop) - }) - } - } - - property(prop) { - var parts = attrPat.exec(prop) - var obj = {} - - if ( parts && parts[1]) { - obj.property = parts[1] - if ( parts[2] ) { - obj.operation = parts[2] - if ( parts[3] ) obj.value = Number(parts[3]) - else if ( parts[4] ) obj.value = parts[4] - else if ( parts[5] ) obj.value = Boolean(parts[5]) - } - this.ret.properties.push(obj) - } - } - - pseudos() { - var pat = /(?:\:([\w]+)(?:\(([\s\S]+)\))?)/g - var pat2 = /(?:\:([\w]+)(?:\(([\s\S]+)\))?)/ - if ( this.dir[5] ) { - this.ret.pseudos = [] - this.dir[5].match(pat).forEach(seg => { - var parts = pat2.exec(seg) - var obj = {} - if ( parts && parts[1] ) { - obj.pseudo = parts[1] - if ( parts[2] ) obj.argument = parts[2] - this.ret.pseudos.push(obj) - } - }) - } - } - -} - -export var Traversal = { - - select(query, frags) { - var results = [] - - var sels = query.match(queryPat) - var sel = sels.pop() - var dir = parse(sel) - frags = frags || sels - - this.children.forEach(child => { - if (dir.child && child.matches(dir)) { - var pass = true - var cur = child - frags.reverse().forEach(frag => { - var dir = parse(frag) - if (pass & dir.child) { - if (cur.parent.matches(dir)) { - cur = cur.parent - } else { - pass = false - } - } - }) - if (pass) results.push(child) - } else if(child.matches(sel)) { - results.push(child) - } - - child.select(sel, frags).forEach(child => results.push(child)) - }) - - void function enhance(sel) { - if (sels.length) { - sel = sels.pop() - results = results.filter(node => node.closest(sel) ? true : false) - enhance() - } - }() - - return results - }, - - closest(selector) { - var dir = parse(selector) - var closest - - if ( this.parent && this.parent !== this.root ){ - closest = this.parent.matches(selector) ? this.parent : this.parent.closest(selector) - } - - return closest - }, - - matches(dir) { - var match = true - - if ( typeof dir === 'string' ) return this.matches(parse(dir)) - - if ( match && dir.key && this.key !== dir.key ) match = false - if ( match && dir.type && this.ast.type !== dir.type ) match = false - if ( dir.properties ) dir.properties.forEach(prop => { - if ( match && prop.property && typeof this.ast[prop.property] === 'undefined' ) match = false - if ( match && prop.property && prop.operation && typeof prop.value !== 'undefined') { - if ( prop.operation === "=" && this.ast[prop.property] !== prop.value) match = false - else if ( typeof this.ast[prop.property] === 'string' ) { - switch (prop.operation) { - case "^=": - if ( !this.ast[prop.property].match("^" + prop.value) ) match = false; break - case "$=": - if ( !this.ast[prop.property].match(prop.value + "$") ) match = false; break - case "*=": - if ( !(~this.ast[prop.property].indexOf(prop.value)) ) match = false; break - } - } - } - }) - - return match - } - -} - -Object.define(Traversal, require("./rel").Relatives) diff --git a/src/esom/tree.six b/src/esom/tree.six deleted file mode 100644 index bd09001..0000000 --- a/src/esom/tree.six +++ /dev/null @@ -1,93 +0,0 @@ -module esprima = "esprima-six"; - -var parse = esprima.parse; -var Syntax = esprima.Syntax; - -class Tree { - - constructor(source, options) { - var ast = parse(source, { range: true, }) - var children = [] - - this.root = this - this.source = source - this.ast = ast - this.children = children - - children.push(this.create({ ast, key: 'root', type: 'Node' })) - - var node = children[0] - node.global = options && options.global - return node - } - - create (base) { - var node = Object.create(this.root) - var parent = this - var children = [] - - Object.define(node, base) - - node.climb(child => { - - if (child.type === 'Node' || (child.type === "NodeSet" && child.ast.length)) { - if (child.type === "NodeSet") { - child.ast.range = [child.ast[0].range[0], child.ast[child.ast.length - 1].range[1]] - } - children.push(node.create(child)) - } - }) - - node.ast = base.ast - node.parent = parent - node.children = children - - Object.define(node, { - unshift(node) { children.unshift(node) }, - push(node) { children.push(node) } - }) - - return node - } - - climb (visit) { - var node = this.ast - Object.keys(node).forEach(key => { - var ast = node[key], type - - if (ast && typeof ast === 'object' && key !== "range") { - type = (ast.type) ? "Node" : Array.isArray(ast) ? "NodeSet" : "Unknown" - visit({ key, ast, type }) - } - - }) - } - - visitByType (typeCallbacks) { - this.children.forEach(child => { - if (! child.ast) { - return - } - - var callback = typeCallbacks[child.ast.type] - if (callback) { - callback(child) - } - - child.visitByType(typeCallbacks) - }) - } - - raw() { return this.source.substring(this.ast.range[0], this.ast.range[1]) } - isRoot() { return this.parent === this.root } - path() { return this.isRoot() ? "" : this.parent.path + "." + this.key } - -} - -Object.define(Tree, { - create(src, options) new this(src, options) -}) - -Object.define(Tree.prototype, require("./trav").Traversal) - -exports.Tree = Tree diff --git a/src/filters.six b/src/filters.six deleted file mode 100644 index 1d49761..0000000 --- a/src/filters.six +++ /dev/null @@ -1,3 +0,0 @@ -export var filters = { - 'class': require("./filters/class").filter, -} diff --git a/src/filters/class.dot b/src/filters/class.dot deleted file mode 100644 index 8a48916..0000000 --- a/src/filters/class.dot +++ /dev/null @@ -1,42 +0,0 @@ -{{ var id = it.id ? it.id.compile() : "_Class"; }} -{{ var dec = it.type === "ClassDeclaration"; }} -{{? dec}}var {{= id}} ={{?}} -(function( -{{? it.superClass }}_super{{?}} -) { - {{? it.superClass }} - function __ctor() { this.constructor = {{= id}}; } - __ctor.prototype = _super.prototype; - {{= id}}.prototype = new __ctor(); - {{= id}}.__super__ = _super.prototype; - {{?}} - - function {{= id}}({{? it.constructor }} - {{? it.constructor.value.params && it.constructor.value.params.ast}}{{= it.constructor.value.params.compile() }}{{?}}) - {{= it.constructor.value.body.compile() }} - {{??}} - ){} - {{?}} - - {{~ it.methods :method:index }} - {{var params = method.value.params && method.value.params.ast;}} - {{? method.kind === 'set' || method.kind === 'get' }} - Object.defineProperty({{= id}}.prototype, "{{= method.key.compile() }}", { - configurable: true, - enumerable: true, - {{= method.kind }}: function({{? params }}{{= method.value.params.compile() }}{{?}}) - {{= method.value.body.compile() }} - }); - {{??}} - {{= id}}.prototype.{{= method.key.compile() }} = function({{? params }}{{= method.value.params.compile() }}{{?}}) - {{= method.value.body.compile() }}; - {{?}} - - {{~}} - - return {{= id }}; -})( - -{{? it.superClass }}{{= it.superClass.compile()}}{{?}} - -){{? dec}};{{?}} \ No newline at end of file diff --git a/src/helpers.six b/src/helpers.six index 300034e..c34367e 100644 --- a/src/helpers.six +++ b/src/helpers.six @@ -1,8 +1,8 @@ export function extend(object, properties) { - var key, val - for (key in properties) { - val = properties[key] - object[key] = val - } - return object + var key, val + for (key in properties) { + val = properties[key] + object[key] = val + } + return object } diff --git a/src/hooks/base.six b/src/hooks/base.six deleted file mode 100644 index 0234e50..0000000 --- a/src/hooks/base.six +++ /dev/null @@ -1,124 +0,0 @@ -import generate from "escodegen" -import filters from "../filters" - -function iterator() { - return { - elements: Object.keys(this).map(key => ({ key, value: this[key] })), - index: 0, - next() { - if (this.index >= this.elements.length) - throw StopIteration - return this.elements[this.index++] - } - } -} - -var hooks = { - - ".Program": node => { - var compile = node.compile - node.compile = () => { - var src = compile.call(node) - var body = generate(node.constructor.create(src).ast, { - format: { - indent: { - style: ' ', - base: node.global ? 0 : 1 - }, - quotes: "double", - compact: false - }, - comment: true - }) - - if (! node.global) { - body = - "if (typeof exports === 'object' && typeof define !== 'function') {\n" + - " var define = function (factory) {\n" + - " factory(require, exports);\n" + - " };\n" + - "}\n" + - "define(function (require, exports) {\n" + body + "\n});" - } - - return body - } - }, - - ".ArrowFunctionExpression": node => { - node.compile = ()=> { - var ctx = node.context() - var params = ctx.params.compile ? ctx.params.compile() : "" - var body = ctx.body.compile(), body = ctx.expression ? `{return ${body}}` : body - return `function(${params})${body}.bind(this)` - } - }, - - ".Property[method=true]": node => { - node.compile = () => { - var ctx = node.context() - var key = ctx.key.compile() - var value = ctx.value - var params = value.params && value.params.compile ? value.params.compile() : "" - var body = value.body.compile(), body = value.expression ? `{return ${body}}`: body - - return `${key}:function(${params})${body}` - } - }, - - ".BinaryExpression[operator^='is']": node => { - node.compile = () => { - return `(${ node.ast.operator === "isnt" ? "!" : "" }function ( x, y ) { - return (x === y)?( x !== 0 || 1/x === 1/y ) : ( x !== x && y !==y ) - }( ${ node.first().compile() }, ${ node.last().compile() } ))` - } - }, - - ".TemplateLiteral": node => { - node.compile = () => { - var it = node.context() - var cooked = [], raw = [] - - it.quasis.node.children.forEach(child => { - raw.push(child.ast.value.raw) - cooked.push(child.ast.value.cooked) - }) - - return `(function(__quasi__){ - var rawStrs = __quasi__['cooked']; - var out = []; - for (var i = 0, k = -1, n = rawStrs.length; i < n;) { - out[++k] = rawStrs[i]; - out[++k] = arguments[++i]; - } - return out.join(''); - })( - ${ JSON.stringify({cooked:cooked, raw:raw}) } - ${it.expressions && it.expressions.node && it.expressions.node.children.length - ? "," + it.expressions.node.children.map(function(exp){return exp.compile()}).join(",") - : "" - } - )` - } - } -} - -Array.prototype.map.call([ - - hooks, - "./classes", - "./forof", - "./objectpattern", - "./modules", - "./restparams" - -], - -hook => { - Object.define(exports, typeof hook === "string" ? require(hook) : hook ) -}) - -Object.defineProperty(exports, "iterator", { - value: iterator, - enumerable: false -}) diff --git a/src/hooks/classes.six b/src/hooks/classes.six deleted file mode 100644 index facb301..0000000 --- a/src/hooks/classes.six +++ /dev/null @@ -1,56 +0,0 @@ -import filters from "../filters" - -function ClassRewrite(node) { - var ctx = node.context() - var constructor - var methods = [] - - if ( ctx.body && ctx.body.body && ctx.body.body.node ) { - ctx.body.body.node.children.forEach(child => { - var sub = child.context() - if ( sub.key.node.matches(".Identifier[name='constructor']") ) constructor = sub - else methods.push(sub) - }) - } - - ctx.constructor = constructor - ctx.methods = methods - - return filters.class(ctx) -} - -Object.define(exports, { - - ".ClassDeclaration": node => { - node.compile = () => ClassRewrite(node) - }, - - ".ClassExpression": node => { - node.compile = () => ClassRewrite(node) - }, - - ".CallExpression > .MemberExpression > .Identifier[name='super']": node => { - var Call = node.closest(".CallExpression").context() - var callee = Call.callee - var args = Call.arguments - - if (args && args.compile){ - var argsc = args = args.compile() - } - - node.compile = () => "this.constructor.__super__" - callee.property.node.compile = () => callee.property.name + ".call" - if (args && args.node) args.node.compile = () => `this${ args.node ? "," + argsc : "" }` - }, - - ".CallExpression > callee[name='super']": node => { - var Call = node.parent.context() - var args = Call.arguments - if(args && args.compile){ - args = args.compile() - } - - Call.node.compile = () => `this.constructor.__super__.constructor.call(this ${ args.node ? "," + args:"" })` - } - -}) diff --git a/src/hooks/forof.six b/src/hooks/forof.six deleted file mode 100644 index 1b328cc..0000000 --- a/src/hooks/forof.six +++ /dev/null @@ -1,40 +0,0 @@ -var hooks = { - - ".ForOfStatement": node => { - node.compile = () => { - var context = node.context() - var right = context.right.compile() - var body = context.body.compile().replace(/^{([\s\S]*)}$/, "$1") - var dec = context.left.matches(".VariableDeclaration[kind='var']") - var decs = [] - var left = dec ? context.left.declarations.node.first().context() : context.left.node.context() - - if (left.type === "Identifier" || (left.id && left.id.type === "Identifier")) { - decs.push(left.compile()) - left = `${left.compile()} = _iterator.next()` - } else if (left.type === "VariableDeclarator" && left.id.type === "ObjectPattern") { - left.select(".ObjectPattern").forEach(node => { - decs = decs.concat(node.properties().map(prop=>prop.key)) - left = node.assemble("_iterator.next()") - }) - } else { - left = `(${left.compile()})` - } - - return ` - ${ dec ? "var " + decs.join(", ") + ";" : "" } - void function(_iterator){ - try { - while (true) { - ${ left } - ${ body } - } - } catch (e) { if (e !== StopIteration ) throw e } - }.call(this, ${ right }.iterator()); - ` - } - } - -} - -Object.define(exports, hooks) \ No newline at end of file diff --git a/src/hooks/modules.six b/src/hooks/modules.six deleted file mode 100644 index 8bd548f..0000000 --- a/src/hooks/modules.six +++ /dev/null @@ -1,127 +0,0 @@ -import existsSync from "fs" -import sep from "path" - -var hooks = { - ".ModuleDeclaration": node => { - var compile = node.compile - node.compile = () => { - var ret = "var " - var ctx = node.context() - var from = ctx.from - - if (! from) - return compile.call(node) - - if (from.type is 'Literal') { - // import directly from file - var modRoot = from.value - return `var ${ctx.id.name} = require("${modRoot}");` - } - else { - var modRoot = from.compile() - return `var ${ctx.id.name} = ${modRoot};` - } - } - }, - ".ImportDeclaration": node => { - node.compile = () => { - var ret = "var " - var ctx = node.context() - var from = ctx.from - - if (from.type is 'Literal') { - // import directly from file - var modRoot = from.value - var modVarName = modRoot.replace(/[\/\.]/g, '_') - modRoot = `require("${modRoot}")` - } - else { - // the only other valid text here is a namespace path - from = from.context().body.node - var modNames = from.children.map(path => path.name) - var modVarName = modNames.join("_") - var modRoot = from.compile() - } - - var specifiers = ctx.specifiers.node.children - - if (specifiers.length is 1) { - modVarName = modRoot - } - else { - ret += `${modVarName} = ${modRoot}` - } - - specifiers.forEach(spec => { - if (specifiers.length > 1) - ret += ', ' - - var ctx = spec.context() - if (ctx.type is "ImportSpecifier") { - var name = ctx.id.name - var from = ctx.from ? ctx.from.node.children[0].ast[0].name : name - - ret += `${from} = ${modVarName}.${name}` - } - else { - ret += `${ctx.name} = ${modVarName}.${ctx.name}` - } - }) - - return ret + ";"; - } - }, - ".ExportDeclaration": node => { - var ctx = node.context() - node.compile = () => { - var declaration = ctx.declaration - if (! declaration) { - var ret = '' - ctx.specifiers.node.children.forEach(value => { - var name = value.context().id.name - ret += `exports.${name} = ${name};` - }) - return ret - } - - var exportee = declaration - switch (exportee.type) { - case "FunctionDeclaration": - var name = exportee.id.name - // test params[0] as when empty it is an array, otherwise an object - return `var ${name} = exports.${name} = function(` + - (exportee.params[0] ? exportee.params.compile() : '') + - `) ${exportee.body.compile()};\n` - case "VariableDeclaration": - var ret = '' - exportee.declarations.children.forEach((value, idx) => { - var declaration = value.context() - var name = declaration.id.name - ret += `var ${name} = exports.${name} = ` + - (declaration.init ? declaration.init.compile() : 'null') + ";\n" - }) - return ret - case "ModuleDeclaration": - var from = exportee.from - if (from) { - var name = exportee.id.name - if (from.type is 'Literal') { - // import directly from file - var modRoot = from.value - return `var ${name} = exports.${name} = require("${modRoot}");` - } - else { - var modRoot = fromcompile() - return `var ${name} = exports.${name} = ${modRoot};` - } - } - // TODO - default: - // should be unreachable but fallthrough in case the standard changes - return ctx.declaration.compile() - } - } - } -} - -Object.define(exports, hooks) diff --git a/src/hooks/objectpattern.six b/src/hooks/objectpattern.six deleted file mode 100644 index 6bfc000..0000000 --- a/src/hooks/objectpattern.six +++ /dev/null @@ -1,40 +0,0 @@ -var hooks = { - - ".VariableDeclarator > id.ObjectPattern": node => { - node.properties = () => { - var ctx = node.parent.context() - var props = [] - - ctx.id.properties.node.children.forEach(child => { - var prop = child.context() - var key = prop.key.compile() - var value = prop.value.compile() - props.push({ key, value }) - }) - - return props - } - - node.assemble = (init) => { - var ctx = node.parent.context() - var props = node.properties() - var result = "" - - if (!ctx.init || (!ctx.init.matches(".Identifier") && props.length > 1)) { - var first = props.shift() - result += `${first.key} = ${init}, ` - props.push(first) - init = first.key - } - - props = props.map((prop, index) => `${prop.key} = ${init}.${prop.value}`) - - return `${result}${props.join(", ")}` - } - - node.parent.compile = () => node.assemble(node.parent.context().init.compile()) - } - -} - -Object.define(exports, hooks) \ No newline at end of file diff --git a/src/hooks/restparams.six b/src/hooks/restparams.six deleted file mode 100644 index 8ef576c..0000000 --- a/src/hooks/restparams.six +++ /dev/null @@ -1,25 +0,0 @@ -var hooks = { - ".FunctionDeclaration": node => { - var ctx = node.context() - if (! ctx.params.node) - return - var params = ctx.params.node.children - - var lastIdx = params.length - 1 - var lastParam = params[lastIdx] - - if (lastParam.ast.type === 'RestParameter') { - var restParamName = lastParam.ast.value.name - params.pop() - - ctx.params.node.compile = () => params.map(p => p.context().name).join(', ') - - ctx.body.body.unshift({ - raw() "", - compile() `var ${restParamName} = [].slice.call(arguments, ${lastIdx});` - }) - } - } -} - -Object.define(exports, hooks) diff --git a/src/optparse.six b/src/optparse.six index b4c216c..ef1f912 100644 --- a/src/optparse.six +++ b/src/optparse.six @@ -1,138 +1,138 @@ // Generated by CoffeeScript 1.3.3 (function() { - var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments; + var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments; - exports.OptionParser = OptionParser = (function() { + exports.OptionParser = OptionParser = (function() { - function OptionParser(rules, banner) { - this.banner = banner; - this.rules = buildRules(rules); - } - - OptionParser.prototype.parse = function(args) { - var arg, i, isOption, matchedRule, options, originalArgs, pos, rule, seenNonOptionArg, skippingArgument, value, _i, _j, _len, _len1, _ref; - options = { - "arguments": [] - }; - skippingArgument = false; - originalArgs = args; - args = normalizeArguments(args); - for (i = _i = 0, _len = args.length; _i < _len; i = ++_i) { - arg = args[i]; - if (skippingArgument) { - skippingArgument = false; - continue; - } - if (arg === '--') { - pos = originalArgs.indexOf('--'); - options["arguments"] = options["arguments"].concat(originalArgs.slice(pos + 1)); - break; + function OptionParser(rules, banner) { + this.banner = banner; + this.rules = buildRules(rules); } - isOption = !!(arg.match(LONG_FLAG) || arg.match(SHORT_FLAG)); - seenNonOptionArg = options["arguments"].length > 0; - if (!seenNonOptionArg) { - matchedRule = false; - _ref = this.rules; - for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { - rule = _ref[_j]; - if (rule.shortFlag === arg || rule.longFlag === arg) { - value = true; - if (rule.hasArgument) { - skippingArgument = true; - value = args[i + 1]; - } - options[rule.name] = rule.isList ? (options[rule.name] || []).concat(value) : value; - matchedRule = true; - break; + + OptionParser.prototype.parse = function(args) { + var arg, i, isOption, matchedRule, options, originalArgs, pos, rule, seenNonOptionArg, skippingArgument, value, _i, _j, _len, _len1, _ref; + options = { + "arguments": [] + }; + skippingArgument = false; + originalArgs = args; + args = normalizeArguments(args); + for (i = _i = 0, _len = args.length; _i < _len; i = ++_i) { + arg = args[i]; + if (skippingArgument) { + skippingArgument = false; + continue; + } + if (arg === '--') { + pos = originalArgs.indexOf('--'); + options["arguments"] = options["arguments"].concat(originalArgs.slice(pos + 1)); + break; + } + isOption = !!(arg.match(LONG_FLAG) || arg.match(SHORT_FLAG)); + seenNonOptionArg = options["arguments"].length > 0; + if (!seenNonOptionArg) { + matchedRule = false; + _ref = this.rules; + for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { + rule = _ref[_j]; + if (rule.shortFlag === arg || rule.longFlag === arg) { + value = true; + if (rule.hasArgument) { + skippingArgument = true; + value = args[i + 1]; + } + options[rule.name] = rule.isList ? (options[rule.name] || []).concat(value) : value; + matchedRule = true; + break; + } + } + if (isOption && !matchedRule) { + throw new Error("unrecognized option: " + arg); + } + } + if (seenNonOptionArg || !isOption) { + options["arguments"].push(arg); + } } - } - if (isOption && !matchedRule) { - throw new Error("unrecognized option: " + arg); - } - } - if (seenNonOptionArg || !isOption) { - options["arguments"].push(arg); - } - } - return options; - }; + return options; + }; - OptionParser.prototype.help = function() { - var letPart, lines, rule, spaces, _i, _len, _ref; - lines = []; - if (this.banner) { - lines.unshift("" + this.banner + "\n"); - } - _ref = this.rules; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - rule = _ref[_i]; - spaces = 15 - rule.longFlag.length; - spaces = spaces > 0 ? Array(spaces + 1).join(' ') : ''; - letPart = rule.shortFlag ? rule.shortFlag + ', ' : ' '; - lines.push(' ' + letPart + rule.longFlag + spaces + rule.description); - } - return "\n" + (lines.join('\n')) + "\n"; - }; + OptionParser.prototype.help = function() { + var letPart, lines, rule, spaces, _i, _len, _ref; + lines = []; + if (this.banner) { + lines.unshift("" + this.banner + "\n"); + } + _ref = this.rules; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + rule = _ref[_i]; + spaces = 15 - rule.longFlag.length; + spaces = spaces > 0 ? Array(spaces + 1).join(' ') : ''; + letPart = rule.shortFlag ? rule.shortFlag + ', ' : ' '; + lines.push(' ' + letPart + rule.longFlag + spaces + rule.description); + } + return "\n" + (lines.join('\n')) + "\n"; + }; - return OptionParser; + return OptionParser; - })(); + })(); - LONG_FLAG = /^(--\w[\w\-]*)/; + LONG_FLAG = /^(--\w[\w\-]*)/; - SHORT_FLAG = /^(-\w)$/; + SHORT_FLAG = /^(-\w)$/; - MULTI_FLAG = /^-(\w{2,})/; + MULTI_FLAG = /^-(\w{2,})/; - OPTIONAL = /\[(\w+(\*?))\]/; + OPTIONAL = /\[(\w+(\*?))\]/; - buildRules = function(rules) { - var tuple, _i, _len, _results; - _results = []; - for (_i = 0, _len = rules.length; _i < _len; _i++) { - tuple = rules[_i]; - if (tuple.length < 3) { - tuple.unshift(null); - } - _results.push(buildRule.apply(null, tuple)); - } - return _results; - }; + buildRules = function(rules) { + var tuple, _i, _len, _results; + _results = []; + for (_i = 0, _len = rules.length; _i < _len; _i++) { + tuple = rules[_i]; + if (tuple.length < 3) { + tuple.unshift(null); + } + _results.push(buildRule.apply(null, tuple)); + } + return _results; + }; - buildRule = function(shortFlag, longFlag, description, options) { - var match; - if (options == null) { - options = {}; - } - match = longFlag.match(OPTIONAL); - longFlag = longFlag.match(LONG_FLAG)[1]; - return { - name: longFlag.substr(2), - shortFlag: shortFlag, - longFlag: longFlag, - description: description, - hasArgument: !!(match && match[1]), - isList: !!(match && match[2]) + buildRule = function(shortFlag, longFlag, description, options) { + var match; + if (options == null) { + options = {}; + } + match = longFlag.match(OPTIONAL); + longFlag = longFlag.match(LONG_FLAG)[1]; + return { + name: longFlag.substr(2), + shortFlag: shortFlag, + longFlag: longFlag, + description: description, + hasArgument: !!(match && match[1]), + isList: !!(match && match[2]) + }; }; - }; - normalizeArguments = function(args) { - var arg, l, match, result, _i, _j, _len, _len1, _ref; - args = args.slice(0); - result = []; - for (_i = 0, _len = args.length; _i < _len; _i++) { - arg = args[_i]; - if (match = arg.match(MULTI_FLAG)) { - _ref = match[1].split(''); - for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { - l = _ref[_j]; - result.push('-' + l); + normalizeArguments = function(args) { + var arg, l, match, result, _i, _j, _len, _len1, _ref; + args = args.slice(0); + result = []; + for (_i = 0, _len = args.length; _i < _len; _i++) { + arg = args[_i]; + if (match = arg.match(MULTI_FLAG)) { + _ref = match[1].split(''); + for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { + l = _ref[_j]; + result.push('-' + l); + } + } else { + result.push(arg); + } } - } else { - result.push(arg); - } - } - return result; - }; + return result; + }; }).call(this); \ No newline at end of file diff --git a/src/rewriter.six b/src/rewriter.six deleted file mode 100644 index 7340140..0000000 --- a/src/rewriter.six +++ /dev/null @@ -1,84 +0,0 @@ -require("./es6") - -import Tree from "./esom/tree" -module hooks = "./hooks/base" - -// A cache of hooks that can be run in a single pass. -var visitors = {} - -// Push applicable hooks into visitor pass. -function optimizeHooks() { - var sels = Object.keys(hooks) - var optimizable = /^\.[a-zA-Z]+$/ - for (var sel of sels) { - if (optimizable.exec(sel)) { - visitors[sel.substring(1)] = hooks[sel] - delete hooks[sel] - } - } -} - -optimizeHooks() - -export function rewrite(src, options) { - var program = Tree.create(src, options) - - for(var { selector: key, hook: value } of hooks) { - program.root.select(selector).forEach(hook) - } - - program.root.visitByType(visitors) - - return program.compile() -} - -Object.define(Tree.prototype, { - - compile () { - var src = this.raw() - - this.children.reverse().forEach(child => { - var raw = child.raw() - var start = src.indexOf(raw) - var end = start + raw.length - src = src.substring(0, start) + child.compile() + src.substring(end) - }) - - return src - }, - - context() { - var ctx = new Context(this) - return ctx - } - -}) - -class Context { - - constructor(node) { - var stack = Object.create(node) - var parent - - Object.define(stack, node.ast) - Object.define(stack, { - node, - get parent() { - parent ? parent : node.parent ? (parent = node.parent.context()) : undefined - } - }) - - if (stack.hasOwnProperty("loc")) delete stack['loc'] - - node.children.forEach(child => { - var ctx - Object.defineProperty(stack, child.key, { - get() ctx ? ctx : (ctx = child.context()), - enumerable: true - }) - }) - - return stack - } - -} diff --git a/src/sake.six b/src/sake.six index 251fac7..417d372 100644 --- a/src/sake.six +++ b/src/sake.six @@ -24,30 +24,30 @@ var oparse = null // Mixin the top-level Sake functions for Sakefiles to use directly. helpers.extend(global, { - // Define a Sake task with a short name, an optional sentence description, - // and the function to run as the action itself. - task: function(name, description, action) { - var _ref; - if (!action) { - _ref = [description, action], action = _ref[0], description = _ref[1]; + // Define a Sake task with a short name, an optional sentence description, + // and the function to run as the action itself. + task: function(name, description, action) { + var _ref; + if (!action) { + _ref = [description, action], action = _ref[0], description = _ref[1]; + } + return tasks[name] = { + name: name, + description: description, + action: action + } + }, + // Define an option that the Sakefile accepts. The parsed options hash, + // containing all of the command-line options passed, will be made available + // as the first argument to the action. + option: function(letter, flag, description) { + return switches.push([letter, flag, description]) + }, + // Invoke another task in the current Sakefile. + invoke: function(name) { + if (!tasks[name]) missingTask(name) + return tasks[name].action(options) } - return tasks[name] = { - name: name, - description: description, - action: action - } - }, - // Define an option that the Sakefile accepts. The parsed options hash, - // containing all of the command-line options passed, will be made available - // as the first argument to the action. - option: function(letter, flag, description) { - return switches.push([letter, flag, description]) - }, - // Invoke another task in the current Sakefile. - invoke: function(name) { - if (!tasks[name]) missingTask(name) - return tasks[name].action(options) - } }) // Run `sake`. Executes all of the tasks you pass, in order. Note that Node's @@ -55,43 +55,43 @@ helpers.extend(global, { // If no tasks are passed, print the help screen. Keep a reference to the // original directory name, when running Sake tasks from subdirectories. export function run() { - global.__originalDirname = fs.realpathSync('.') - process.chdir(sakefileDirectory(__originalDirname)) - var args = process.argv.slice(2) - Six.run(fs.readFileSync('Sakefile').toString(), {filename: 'Sakefile'}) - oparse = new optparse.OptionParser(switches) - if (!args.length) return printTasks() - try { - var options = oparse.parse(args) - } catch (e) { - return fatalError(e + "") - } + global.__originalDirname = fs.realpathSync('.') + process.chdir(sakefileDirectory(__originalDirname)) + var args = process.argv.slice(2) + Six.run(fs.readFileSync('Sakefile').toString(), {filename: 'Sakefile'}) + oparse = new optparse.OptionParser(switches) + if (!args.length) return printTasks() + try { + var options = oparse.parse(args) + } catch (e) { + return fatalError(e + "") + } - options.arguments.forEach(function(arg){ - invoke(arg) - }); + options.arguments.forEach(function(arg){ + invoke(arg) + }); } // Display the list of Sake tasks in a format similar to `rake -T` var printTasks = function() { - var relative = path.relative || path.resolve - var sakefilePath = path.join(relative(__originalDirname, process.cwd()), 'Sakefile') - console.log(sakefilePath + " defines the following tasks:\n") - Object.keys(tasks).forEach(function(name){ - var task = tasks[name] - var spaces = 20 - name.length - spaces = (spaces > 0) ? Array(spaces + 1).join(' ') : '' - var desc = task.description ? '# ' + task.description : '' - console.log("sake " + name + spaces + " " + desc) - }) - if (switches.length) console.log(oparse.help()) + var relative = path.relative || path.resolve + var sakefilePath = path.join(relative(__originalDirname, process.cwd()), 'Sakefile') + console.log(sakefilePath + " defines the following tasks:\n") + Object.keys(tasks).forEach(function(name){ + var task = tasks[name] + var spaces = 20 - name.length + spaces = (spaces > 0) ? Array(spaces + 1).join(' ') : '' + var desc = task.description ? '# ' + task.description : '' + console.log("sake " + name + spaces + " " + desc) + }) + if (switches.length) console.log(oparse.help()) } // Print an error and exit when attempting to use an invalid task/option. var fatalError = function(message) { - console.error(message + '\n') - console.log('To see a list of all tasks/options, run "sake"') - process.exit(1) + console.error(message + '\n') + console.log('To see a list of all tasks/options, run "sake"') + process.exit(1) } var missingTask = function(task) { fatalError("No such task: " + task) } @@ -99,8 +99,8 @@ var missingTask = function(task) { fatalError("No such task: " + task) } // When `sake` is invoked, search in the current and all parent directories // to find the relevant Sakefile. var sakefileDirectory = function(dir) { - if (existsSync(path.join(dir, 'Sakefile'))) return dir - var parent = path.normalize(path.join(dir), '..') - if (parent !== dir) return sakefileDirectory(parent) - throw new Error("Sakefile not found in " + process.cwd()) + if (existsSync(path.join(dir, 'Sakefile'))) return dir + var parent = path.normalize(path.join(dir), '..') + if (parent !== dir) return sakefileDirectory(parent) + throw new Error("Sakefile not found in " + process.cwd()) } diff --git a/src/six.six b/src/six.six index fd1ed62..dd35c9a 100644 --- a/src/six.six +++ b/src/six.six @@ -2,37 +2,36 @@ module fs = "fs" module path = "path" -import rewrite from "./rewriter" -import dumpAst from "./dumper" +import rewrite from "./core/rewriter" export function run (code, options) { - var mainModule = require.main + var mainModule = require.main - if(!options) options = {} + if(!options) options = {} - mainModule.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : '.' - mainModule.moduleCache && (mainModule.moduleCache = {}) - mainModule.paths = require('module')._nodeModulePaths(path.dirname(fs.realpathSync(options.filename))) + mainModule.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : '.' + mainModule.moduleCache && (mainModule.moduleCache = {}) + mainModule.paths = require('module')._nodeModulePaths(path.dirname(fs.realpathSync(options.filename))) - if (path.extname(mainModule.filename) !== '.six' || require.extensions) { - mainModule._compile(compile(code, options), mainModule.filename) - } else { - mainModule._compile(code, mainModule.filename) - } + if (path.extname(mainModule.filename) !== '.six' || require.extensions) { + mainModule._compile(compile(code, options), mainModule.filename) + } else { + mainModule._compile(code, mainModule.filename) + } } export function compile (src, options, callback) { - src = rewrite(src, options) - return src + src = rewrite(src, options) + return src } export function nodes (src, options) { - return dumpAst(src, options.verbose) + return dumpAst(src, options.verbose) } // Register .six exension with node if (require && require.extensions) { - require.extensions['.six'] = function(module, filename) { - var content = compile(fs.readFileSync(filename, 'utf8')); - return module._compile(content, filename); - }; + require.extensions['.six'] = function(module, filename) { + var content = compile(fs.readFileSync(filename, 'utf8')); + return module._compile(content, filename); + }; } diff --git a/test/class.js b/test/class.js deleted file mode 100644 index 858a5bb..0000000 --- a/test/class.js +++ /dev/null @@ -1,50 +0,0 @@ -var expect = require("chai").expect; -var six = require('../lib/six'); -var compile = function (src) { return six.compile(src, { global: true }); } - -describe('classes', function() { - it("produces a valid constructor function from an empty declaration", function(){ - var src = "class A {}" - var result = compile(src) - - eval(result) - - expect(A) - .to.be.a("function") - - expect(A.name) - .to.equal("A") - - expect(A) - .to.have.length(0) - - expect((new A).constructor) - .to.equal(A) - - expect((new A).constructor.prototype) - .to.equal(A.prototype) - }) - - it("produces a valid constructor function from an empty constructor method", function(){ - var src = "class A {constructor(b){}}" - var result = compile(src) - - eval(result) - - expect(A) - .to.be.a("function") - - expect(A.name) - .to.equal("A") - - expect(A) - .to.have.length(1) - - expect((new A).constructor) - .to.equal(A) - - expect((new A).constructor.prototype) - .to.equal(A.prototype) - }) - -}); diff --git a/test/egal.js b/test/egal.js deleted file mode 100644 index b2a5764..0000000 --- a/test/egal.js +++ /dev/null @@ -1,39 +0,0 @@ -var expect = require("chai").expect; -var six = require('../lib/six'); -var compile = function (src) { return six.compile(src, { global: true }); } - -describe('egal operators', function() { - - it('finds two idential numeric literals to be equal', function() { - var src = "var a = 1 is 1, b = 1 isnt 1" - var result = compile(src) - eval(result) - a.should.be.true - b.should.be.false - }); - - it('finds two different numeric literals as not equal', function() { - var src = "var a = 1 is 2, b = 1 isnt 2" - var result = compile(src) - eval(result) - a.should.be.false - b.should.be.true - }); - - it('finds literal 0 as not equal to literal -0', function() { - var src = "var a = 0 is -0, b = 0 isnt -0" - var result = compile(src) - eval(result) - a.should.be.false - b.should.be.true - }); - - it('finds NaN as equal to NaN', function() { - var src = "var a = NaN is NaN, b = NaN isnt NaN" - var result = compile(src) - eval(result) - a.should.be.true - b.should.be.false - }); - -}); diff --git a/test/inc/magic.js b/test/inc/magic.js deleted file mode 100644 index 27c2f2a..0000000 --- a/test/inc/magic.js +++ /dev/null @@ -1 +0,0 @@ -exports.number = function() { return 420 } diff --git a/test/inc/mod.six b/test/inc/mod.six deleted file mode 100644 index 40db29b..0000000 --- a/test/inc/mod.six +++ /dev/null @@ -1 +0,0 @@ -exports.number = () => 420 diff --git a/test/include.six b/test/include.six deleted file mode 100644 index 0dddaaa..0000000 --- a/test/include.six +++ /dev/null @@ -1,7 +0,0 @@ -var expect = require("chai").expect; -var six = require('../lib/six'); // this require enables the .six file extension - -describe('node six file extension include', function() { - var mod = require('./inc/mod') - expect(mod.number()).to.equal(420) -}) diff --git a/test/module.js b/test/module.js deleted file mode 100644 index 42c694f..0000000 --- a/test/module.js +++ /dev/null @@ -1,76 +0,0 @@ -var expect = require("chai").expect; -var six = require('../lib/six'); -var compile = function (src) { return six.compile(src, { global: true }); } - -describe('import statement', function() { - it("imports a module function", function(){ - var src = "import number from './inc/magic'; var n = number()" - var result = compile(src) - eval(result) - expect(n).to.equal(420) - }) - - it("imports a module function using a pattern", function(){ - var src = "import {number} from './inc/magic'; var n = number()" - var result = compile(src) - eval(result) - expect(n).to.equal(420) - }) - - it("import and alias a module function", function(){ - var src = "import {number: num} from './inc/magic'; var n = num()" - var result = compile(src) - eval(result) - expect(n).to.equal(420) - }) - - it("alias a module to an identifier", function(){ - var src = "module mag = './inc/magic'; var n = mag.number()" - var result = compile(src) - eval(result) - expect(n).to.equal(420) - }) - - it("alias a module alias to a subsequent alias", function(){ - var src = "module dance = './inc/magic'; module bon = dance; var n = bon.number()" - var result = compile(src) - eval(result) - expect(n).to.equal(420) - }) - - it("export a function from a module", function(){ - var src = "export function add400(a) { return a + 400; }" - eval(six.compile(src)) - var n = exports.add400(20) - expect(n).to.equal(420) - exports = {} - }) - - it("export a variable from a module", function(){ - var src = "export var n = 420" - eval(six.compile(src)) - expect(exports.n).to.equal(420) - exports = {} - }) - - it("export variables from a module", function(){ - var src = "export var a = 420, b = 400, c = 20" - eval(six.compile(src)) - expect(exports.a).to.equal(exports.b + exports.c) - exports = {} - }) - - it("export module alias from a module", function(){ - var src = "export module mag = './inc/magic';" - eval(six.compile(src)) - expect(exports.mag.number()).to.equal(420) - exports = {} - }) - - it("export a predeclared symbol", function(){ - var src = "var lovely = 'kitten'; export lovely" - eval(six.compile(src)) - expect(exports.lovely).to.equal('kitten') - exports = {} - }) -}); diff --git a/test/objectpattern.js b/test/objectpattern.js deleted file mode 100644 index 8af810b..0000000 --- a/test/objectpattern.js +++ /dev/null @@ -1,43 +0,0 @@ -var expect = require("chai").expect; -var six = require('../lib/six'); -var compile = function (src) { return six.compile(src, { global: true }); } - -describe('destructuring ObjectPattern Assignment', function() { - - it('destructures into property accessors when the RHS is an Identifier', function() { - var src = "var a = {b:1}; var {b} = a" - var result = compile(src) - eval(result) - b.should.equal(1) - }); - - it('destructures into property accessors when the RHS is an ObjectExpression', function() { - var src = "var {a} = {a:1}" - var result = compile(src) - eval(result) - a.should.equal(1) - }); - - it('destructures into property accessors when the RHS is an ArrayExpression', function() { - var src = "var {a: length} = [1,2,3]" - var result = compile(src) - eval(result) - a.should.equal(3) - }); - - it('destructures into property accessors when the RHS is an FunctionExpression', function() { - var src = "var {a: length} = function(a,b,c){}" - var result = compile(src) - eval(result) - a.should.equal(3) - }); - - // var {x} = func() - // var {x,y} = func() - // var {x} = y = func() - // var {x} = y = z - // var x = {y} = z - // var x = {a,b} = z - // var z = {x:1, y:2}; var {x} = {y} = z - -}); diff --git a/test/objectshorthand.js b/test/objectshorthand.js deleted file mode 100644 index ddecfb4..0000000 --- a/test/objectshorthand.js +++ /dev/null @@ -1,14 +0,0 @@ -var expect = require("chai").expect; -var six = require('../lib/six'); -var compile = function (src) { return six.compile(src, { global: true }); } - -describe('shorthand properties', function() { - - it('converts shorthand properties into longhand properties', function() { - var src = "var a = 1; var o = { a, b: 2, c: 3 }" - var result = compile(src) - eval(result) - JSON.stringify(o).should.equal(JSON.stringify({ a: 1, b: 2, c: 3 })) - }); - -}); diff --git a/test/restparams.js b/test/restparams.js deleted file mode 100644 index 36e6052..0000000 --- a/test/restparams.js +++ /dev/null @@ -1,25 +0,0 @@ -var expect = require("chai").expect; -var six = require('../lib/six'); // this require enables the .six file extension -var compile = function (src) { return six.compile(src, { global: true }); } - -describe('rest parameters', function() { - it ('function declaration with only rest parameter', function(){ - var src = "function f(...b) { return b[1] }; var c = f(1, 2, 3)" - eval(compile(src)) - expect(c).to.equal(2) - }) - - it ('function declaration with subsequent rest parameter', function(){ - var src = "function f(a, ...b) { return b[1] }; var c = f(1, 2, 3)" - eval(compile(src)) - expect(c).to.equal(3) - }) - - it ('export function declaration with subsequent rest parameter', function(){ - var src = "export function f(...b) { return b[1] }" - eval(compile(src)) - expect(exports.f(1, 2, 3)).to.equal(2) - exports = {} - }) -}) -