astify
Astify generates Abstract Syntax Trees from objects in live JS (as well as from source). Want to convert the entire global object to source? global.toAST().toSource()
. Beyond adding toAST
, astify also makes build AST (which is then convertable to code using toSource
) super simple to do. Frankenstein different pieces of objects and functions together to make new ones.
This is still experimental and unfinished.
This is a fork of the original astify, with the dependancies included and uploaded to npm.
Usage
It is currently set up for use in Node.js (will be combining for a browser build soon).
var astify = ; astify; //the toAST functions must be explicitly installed on a global objectconsole; // anything can be converted to AST
API
- astify.install(context): Install the
toAST
prototype functions on a given global object, defaulting to the main global. - anything.toAST(showHidden, identity)_: Builtins get specialized
toAST
methods. showHidden includes non-enumerable properties. identity labels an object which doesn't have a discernable name. By default a gensym is provided. - astify.parseFile(filename): creates AST from sourcecode.
- astify.createNode(type, args...): creates an AST Node from scratch.
Selectors
To select nodes you can use css-like syntax (work in progress) using node.find(selector). Some examples:
function function function var
- descending selectors, this would filter to vars that are inside 3 nested functions.function > id
- child selector requires nodes to be direct childrenvar.declarations
- select specific propertiesfunction.params.id
- select multiple propertiesfunction:scope
- select all the nodes in the current scopemethod[kind = ""][key != "constructor"].value
- selects methods (es6) with no kind (normal) where key is notEqual to constructor, then selectos its value property (a function expression).method[key = "constructor"].value:first
- selects the first method with the name "constructor" and returns its value (function expr)ident:first-child
- selects all identifiers that are first-childrenreturn:last-child
- select all return statements which are last childrencall[callee = "super"]
- select functions calls where the function name is "super"member[object=super]
- selects expressions that look like "super.prop"
Node Creation
An intro example to manually assembling nodes
var _ = astifycreateNode; // intermix explicit AST node definitions with regular functions, objects, and literalsvar myAST = ;
Which produces
console;// -->var myAST = a: 50 { var somevar = 5 { return { }; }; } { return 'stuff'; } { return thisbname; };
And the AST:
type: 'ObjectExpression' properties: type: 'Property' key: type: 'Identifier' name: 'a' value: type: 'Literal' value: 50 kind: 'init' type: 'Property' key: type: 'Identifier' name: 'b' value: type: 'FunctionExpression' params: id: null body: type: 'BlockStatement' body: type: 'VariableDeclaration' kind: 'var' declarations: type: 'VariableDeclarator' id: type: 'Identifier' name: 'somevar' init: type: 'Literal' value: 5 type: 'VariableDeclarator' id: type: 'Identifier' name: 'another' init: type: 'CallExpression' callee: type: 'FunctionExpression' params: id: null body: type: 'BlockStatement' body: type: 'ReturnStatement' argument: type: 'FunctionExpression' params: id: type: 'Identifier' name: 'another' body: type: 'BlockStatement' body: arguments: kind: 'init' type: 'Property' key: type: 'Identifier' name: 'c' value: type: 'FunctionExpression' id: type: 'Identifier' name: 'hi' params: body: type: 'BlockStatement' body: type: 'ReturnStatement' argument: type: 'Literal' value: 'stuff' kind: 'init' type: 'Property' key: type: 'Identifier' name: 'd' value: type: 'FunctionExpression' id: type: 'Identifier' name: 'd' params: body: type: 'BlockStatement' body: type: 'ReturnStatement' argument: type: 'MemberExpression' computed: false object: type: 'MemberExpression' computed: false object: type: 'Identifier' name: 'this' property: type: 'Identifier' name: 'b' property: type: 'Identifier' name: 'name' kind: 'get'
Node Types
The short name can be used to identify the when using astify.createNode
. Optional arguments are in [brackets].
- "assign" - AssignmentExpression(operator, left, right)
- "array" - ArrayExpression([elementArray])
- "block" - BlockStatement([bodyStatementsArray])
- "binary" - BinaryExpression(operator, left, right)
- "break" - BreakStatement([label])
- "call" - CallExpression(callee, [argsExpressionsArray])
- "catch" - CatchClause(param, [[bodyBlock])
- "conditional" - ConditionalExpression(test, consequentExpression, alternateExpression)
- "continue" - ContinueStatement([label])
- "dowhile" - DoWhileStatement(test, [bodyBlock])
- "debugger" - DebuggerStatement()
- "empty" - EmptyStatement()
- "expression" - ExpressionStatement(expression)
- "for" - ForStatement([init, test, update, bodyBlock])
- "forin" - ForInStatement(left, right, [bodyBlock])
- "functiondecl" - FunctionDeclaration(id, [bodyBlock, params])
- "function" - FunctionExpression([id, bodyBlock, params])
- "identifier" - Identifier(name)
- "if" - IfStatement(test, [consequentBlock, alternateBlock])
- "literal" - Literal(value)
- "labeled" - LabeledStatement(label, [bodyBlock])
- "logical" - LogicalExpression(operator, left, right)
- "member" - MemberExpression(object, property)
- "new" - NewExpression(callee, [argsArray])
- "object" - ObjectExpression([propertiesArray])
- "program" - Program([bodyBlock, comments])
- "property" - Property(kind, key, value)
- "return" - ReturnStatement([argument])
- "sequence" - SequenceExpression(expressionsArray)
- "switch" - SwitchStatement(descriminant, [casesArray])
- "case" - SwitchCase([test, consequent])
- "this" - ThisExpression()
- "throw" - ThrowStatement(argument)
- "try" - TryStatement([block, handlers, finalizer])
- "unary" - UnaryExpression(operator, argument)
- "update" - UpdateExpression(operator, argument, [isPrefix])
- "var" - VariableDeclaration(kind, [declarationsArray])
- "decl" - VariableDeclarator(id, [init])
- "while" - WhileStatement(test, [bodyBlock])
- "with" - WithStatement(object, [bodyBlock])
- "iife" - ImmediatelyInvokedFunctionExpression([func, argsArray])