UNPKG

ion

Version:

ion language ========================

330 lines (322 loc) 12.1 kB
void (function(){var _ion_compiler_traverseAst_ = function(module,exports,require){var addStatement, basicTraverse, nodes, trackVariableDeclaration, trackVariableDeclarations; basicTraverse = require('./traverse'); nodes = require('./nodes'); ({addStatement} = require("./astFunctions")); trackVariableDeclaration = function(context, node, kind, name = node.name) { var scope, variable; scope = context.scope(); if (scope == null) { return; } variable = { kind: kind, id: { type: 'Identifier', name: name }, name: name, node: node, scope: scope }; if (typeof context.variableCallback === "function") { context.variableCallback(variable, context); } return scope.variables[name] = variable; }; trackVariableDeclarations = function(context, node, kind = 'let') { var declarator, i, item, j, len, len1, ref, results, results1; if (Array.isArray(node)) { results = []; for (i = 0, len = node.length; i < len; i++) { item = node[i]; results.push(trackVariableDeclarations(context, item, kind)); } return results; } else { if (node.type === 'FunctionDeclaration') { kind = 'const'; if (node.id != null) { return trackVariableDeclarations(context, node.id, kind); } } else if (node.type === 'VariableDeclaration') { kind = node.kind; ref = node.declarations; results1 = []; for (j = 0, len1 = ref.length; j < len1; j++) { declarator = ref[j]; results1.push(trackVariableDeclarations(context, declarator.id, kind)); } return results1; } else if (node.type === "Identifier") { return trackVariableDeclaration(context, node, kind); } else if (node.type === "ObjectPattern") { return basicTraverse.traverse(node, function(child, newContext) { var name, ref1; if ((child.key != null) && (child.value != null)) { name = (ref1 = child.key.value) != null ? ref1 : child.key.name; trackVariableDeclaration(context, child, kind, name); return newContext.skip(); } }); } else if (node.type === "ArrayPattern") { return basicTraverse.traverse(node, function(child, newContext) { if (child.type === 'Identifier') { trackVariableDeclaration(context, child, kind); return newContext.skip(); } }); } } }; exports.traverse = function(program, enterCallback, exitCallback, variableCallback, previousContext) { var ourEnter, ourExit; ourEnter = function(node, context) { var nodeInfo, ref, ref1, ref2; if (context.variableCallback == null) { context.variableCallback = variableCallback; } if (context.scopeStack == null) { context.scopeStack = []; } if (context.scope == null) { context.scope = function() { return this.scopeStack[this.scopeStack.length - 1]; }; } if (context.ancestorNodes == null) { context.ancestorNodes = []; } if (context.getAncestor == null) { context.getAncestor = function(predicate) { var ancestor, i, ref; ref = this.ancestorNodes; for (i = ref.length - 1; i >= 0; i += -1) { ancestor = ref[i]; if (predicate(ancestor)) { return ancestor; } } return null; }; } if (context.rootNode == null) { context.rootNode = function() { return this.ancestorNodes[0]; }; } if (context.parentNode == null) { context.parentNode = function() { return this.ancestorNodes[this.ancestorNodes.length - 1]; }; } if (context.parentScope == null) { context.parentScope = function() { return this.scopeStack[this.scopeStack.length - 2]; }; } if (context.parentReactive == null) { context.parentReactive = function() { return this._reactiveStack[this._reactiveStack.length - 1]; }; } if (context.isParentBlock == null) { context.isParentBlock = function() { var ref, ref1, ref2; return (ref = (ref1 = nodes[(ref2 = this.parentNode()) != null ? ref2.type : void 0]) != null ? ref1.isBlock : void 0) != null ? ref : false; }; } if (context.getVariableInfo == null) { context.getVariableInfo = function(id) { return this.scope().variables[id]; }; } if (context._variableCounts == null) { context._variableCounts = (ref = previousContext != null ? previousContext._variableCounts : void 0) != null ? ref : {}; } if (context.getNewInternalIdentifier == null) { context.getNewInternalIdentifier = function(prefix = '_ref') { var count, counts, name; counts = this._variableCounts; count = counts[prefix] != null ? counts[prefix] : counts[prefix] = 1; counts[prefix]++; name = count === 1 ? prefix : prefix + count; return { type: 'Identifier', name: name }; }; } if (context.getAncestorChildOf == null) { context.getAncestorChildOf = function(ancestor) { var index, ref1; index = this.ancestorNodes.indexOf(ancestor); if (index >= 0) { return (ref1 = this.ancestorNodes[index + 1]) != null ? ref1 : this.current(); } else { return void 0; } }; } if (context.getSharedVariableId == null) { context.getSharedVariableId = function(name) { var ref1, ref2; return (ref1 = (ref2 = this.getVariableInfo(name)) != null ? ref2.id : void 0) != null ? ref1 : this.addVariable({ id: name, offset: Number.MIN_VALUE }); }; } if (context.addStatement == null) { context.addStatement = function(statement, offset, addToNode) { if (typeof statement === 'number') { [statement, offset] = [offset, statement]; } if (addToNode == null) { addToNode = this.scope().node; } trackVariableDeclarations(context, statement); return addStatement(addToNode, statement, this.getAncestorChildOf(addToNode), offset); }; } if (context.addVariable == null) { context.addVariable = function(options) { var variable; variable = this.getVariable(options); this.addStatement(variable, options.offset); return variable.declarations[0].id; }; } if (context.getVariable == null) { context.getVariable = function(options) { var variable; if (options == null) { options = {}; } if (typeof options.id === 'string') { options.id = { type: 'Identifier', name: options.id }; } if (options.id == null) { options.id = this.getNewInternalIdentifier(options.prefix); } if (options.kind == null) { options.kind = 'let'; } // handle patterns. variable = { type: "VariableDeclaration", declarations: [ { type: "VariableDeclarator", id: options.id, init: options.init } ], kind: options.kind }; return variable; }; } context.error = function(message, node) { var e, ref1, ref2, ref3, ref4, ref5, ref6, ref7, ref8; if (node == null) { node = this.current(); } // make sure node has line/column numbers or else search up stack e = new Error(message); e.line = (ref1 = node.loc) != null ? (ref2 = ref1.start) != null ? ref2.line : void 0 : void 0; e.column = ((ref3 = node.loc) != null ? (ref4 = ref3.start) != null ? ref4.column : void 0 : void 0) + 1; e.lineEnd = (ref5 = node.loc) != null ? (ref6 = ref5.end) != null ? ref6.line : void 0 : void 0; e.columnEnd = ((ref7 = node.loc) != null ? (ref8 = ref7.end) != null ? ref8.column : void 0 : void 0) + 1; return e; }; if (node.type != null) { nodeInfo = nodes[node.type]; if ((nodeInfo != null ? nodeInfo.reactive : void 0) != null) { (context._reactiveStack != null ? context._reactiveStack : context._reactiveStack = []).push(context.reactive); context.reactive = nodeInfo.reactive; } if (nodeInfo != null ? nodeInfo.newScope : void 0) { context.scopeStack.push({ variables: Object.create((ref1 = (ref2 = context.scope()) != null ? ref2.variables : void 0) != null ? ref1 : {}), node: node }); } if (Array.isArray(node.body)) { trackVariableDeclarations(context, node.body); } if (nodeInfo != null ? nodeInfo.isFunction : void 0) { trackVariableDeclarations(context, node.params, nodeInfo.paramKind); } else if (node.type === 'ForInStatement' || node.type === 'ForOfStatement') { trackVariableDeclarations(context, node.left); } else if (node.type === 'ObjectExpression') { trackVariableDeclarations(context, node.properties); } if (typeof enterCallback === "function") { enterCallback(node, context); } return context.ancestorNodes.push(node); } }; ourExit = function(node, context) { var nodeInfo; if (node.type != null) { nodeInfo = nodes[node.type]; if ((nodeInfo != null ? nodeInfo.reactive : void 0) != null) { context.reactive = context._reactiveStack.pop(); } context.ancestorNodes.pop(); if (typeof exitCallback === "function") { exitCallback(node, context); } if (nodeInfo != null ? nodeInfo.newScope : void 0) { return context.scopeStack.pop(); } } }; return basicTraverse.traverse(program, ourEnter, ourExit); }; // exports.test = -> // index = require './index' // ast = index.parse """ // var double = -> // var foo = -> 2 // var a = 1 // var b = 2 // var {e,f} = bar, [g,[h]] = baz // if a is b // var c = 3 // if c // log(c) // else // var c = 5 // var d = 4 // log(d) // """ // expected = ["enter",1,["double"],"Program","enter",2,["double"],"FunctionExpression","enter",3,["foo","a","b","e","f","g","h","double"],"BlockStatement","enter",4,["foo","a","b","e","f","g","h","double"],"FunctionExpression","enter",5,["foo","a","b","e","f","g","h","double"],"BlockStatement","exit",5,["foo","a","b","e","f","g","h","double"],"BlockStatement","exit",4,["foo","a","b","e","f","g","h","double"],"FunctionExpression","enter",4,["c","foo","a","b","e","f","g","h","double"],"BlockStatement","exit",4,["c","foo","a","b","e","f","g","h","double"],"BlockStatement","enter",4,["c","d","foo","a","b","e","f","g","h","double"],"BlockStatement","exit",4,["c","d","foo","a","b","e","f","g","h","double"],"BlockStatement","exit",3,["foo","a","b","e","f","g","h","double"],"BlockStatement","exit",2,["double"],"FunctionExpression","exit",1,["double"],"Program"] // actual = [] // enter = (node, context) -> // keys = (key for key of context.scope().variables) // if nodes[node.type]?.newScope // actual.push "enter", context.scopeStack.length, keys, node.type // exit = (node, context) -> // keys = (key for key of context.scope().variables) // if nodes[node.type]?.newScope // actual.push "exit", context.scopeStack.length, keys, node.type // exports.traverse ast, enter, exit // if JSON.stringify(actual) isnt JSON.stringify(expected) // throw new Error "#{actual} isnt #{expected}" // return } if (typeof require === 'function') { if (require.register) require.register('ion/compiler/traverseAst',_ion_compiler_traverseAst_); else _ion_compiler_traverseAst_.call(this, module, exports, require); } else { _ion_compiler_traverseAst_.call(this); } }).call(this)