Add a method of dumping the AST
This commit is contained in:
parent
8430123e9d
commit
51e944b7da
|
|
@ -76,6 +76,7 @@ You need to pass an argument to this option to specify the name that your module
|
|||
.describe("name-cache", "File to hold mangled names mappings")
|
||||
.describe("pure-funcs", "List of functions that can be safely removed if their return value is not used")
|
||||
.describe("dump-spidermonkey-ast", "Dump SpiderMonkey AST to stdout.")
|
||||
.describe("dump-ast", "Dump the AST instead of generating output")
|
||||
|
||||
.alias("p", "prefix")
|
||||
.alias("o", "output")
|
||||
|
|
@ -130,6 +131,7 @@ You need to pass an argument to this option to specify the name that your module
|
|||
.boolean("bare-returns")
|
||||
.boolean("keep-fnames")
|
||||
.boolean("reserve-domprops")
|
||||
.boolean("dump-ast")
|
||||
|
||||
.wrap(80)
|
||||
|
||||
|
|
@ -476,7 +478,8 @@ async.eachLimit(files, 1, function (file, cb) {
|
|||
print(JSON.stringify(TOPLEVEL.to_mozilla_ast(), null, 2));
|
||||
} else {
|
||||
time_it("generate", function(){
|
||||
TOPLEVEL.print(output);
|
||||
if (ARGS.dump_ast) output.print(TOPLEVEL.dump());
|
||||
else TOPLEVEL.print(output);
|
||||
});
|
||||
|
||||
output = output.get();
|
||||
|
|
|
|||
35
lib/ast.js
35
lib/ast.js
|
|
@ -47,11 +47,24 @@ function DEFNODE(type, props, methods, base) {
|
|||
if (arguments.length < 4) base = AST_Node;
|
||||
if (!props) props = [];
|
||||
else props = props.split(/\s+/);
|
||||
var dump_props = [];
|
||||
props = props.map(function(prop){
|
||||
if (/!$/.test(prop)) {
|
||||
prop = prop.slice(0, -1);
|
||||
} else {
|
||||
dump_props.push(prop);
|
||||
}
|
||||
return prop;
|
||||
});
|
||||
var self_props = props;
|
||||
if (base && base.PROPS)
|
||||
props = props.concat(base.PROPS);
|
||||
var code = "return function AST_" + type + "(props){ if (props) { ";
|
||||
for (var i = props.length; --i >= 0;) {
|
||||
if (base) {
|
||||
if (base.PROPS) props = props.concat(base.PROPS);
|
||||
if (base.DUMP_PROPS) dump_props = dump_props.concat(base.DUMP_PROPS);
|
||||
}
|
||||
var code = "return function AST_" + type + "(props){";
|
||||
if (type) { code += "this._class = 'AST_" + type + "';"; }
|
||||
code += " if (props) { ";
|
||||
for (var i = 0; i < props.length; ++i) {
|
||||
code += "this." + props[i] + " = props." + props[i] + ";";
|
||||
}
|
||||
var proto = base && new base;
|
||||
|
|
@ -66,6 +79,7 @@ function DEFNODE(type, props, methods, base) {
|
|||
if (base) base.SUBCLASSES.push(ctor);
|
||||
ctor.prototype.CTOR = ctor;
|
||||
ctor.PROPS = props || null;
|
||||
ctor.DUMP_PROPS = dump_props.sort();
|
||||
ctor.SELF_PROPS = self_props;
|
||||
ctor.SUBCLASSES = [];
|
||||
if (type) {
|
||||
|
|
@ -88,7 +102,7 @@ function DEFNODE(type, props, methods, base) {
|
|||
var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos nlb comments_before file raw", {
|
||||
}, null);
|
||||
|
||||
var AST_Node = DEFNODE("Node", "start end", {
|
||||
var AST_Node = DEFNODE("Node", "start! end!", {
|
||||
clone: function() {
|
||||
return new this.CTOR(this);
|
||||
},
|
||||
|
|
@ -102,6 +116,9 @@ var AST_Node = DEFNODE("Node", "start end", {
|
|||
},
|
||||
walk: function(visitor) {
|
||||
return this._walk(visitor); // not sure the indirection will be any help
|
||||
},
|
||||
dump: function () {
|
||||
return JSON.stringify(dump_internal(this), null, 2);
|
||||
}
|
||||
}, null);
|
||||
|
||||
|
|
@ -121,7 +138,7 @@ var AST_Debugger = DEFNODE("Debugger", null, {
|
|||
$documentation: "Represents a debugger statement",
|
||||
}, AST_Statement);
|
||||
|
||||
var AST_Directive = DEFNODE("Directive", "value scope quote", {
|
||||
var AST_Directive = DEFNODE("Directive", "value scope! quote", {
|
||||
$documentation: "Represents a directive, like \"use strict\";",
|
||||
$propdoc: {
|
||||
value: "[string] The value of this directive as a plain string (it's not an AST_String!)",
|
||||
|
|
@ -278,7 +295,7 @@ var AST_With = DEFNODE("With", "expression", {
|
|||
|
||||
/* -----[ scope and functions ]----- */
|
||||
|
||||
var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", {
|
||||
var AST_Scope = DEFNODE("Scope", "directives variables! functions! uses_with! uses_eval! parent_scope! enclosed! cname!", {
|
||||
$documentation: "Base class for all statements introducing a lexical scope",
|
||||
$propdoc: {
|
||||
directives: "[string*/S] an array of directives declared in this scope",
|
||||
|
|
@ -292,7 +309,7 @@ var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_
|
|||
},
|
||||
}, AST_Block);
|
||||
|
||||
var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
||||
var AST_Toplevel = DEFNODE("Toplevel", "globals!", {
|
||||
$documentation: "The toplevel scope",
|
||||
$propdoc: {
|
||||
globals: "[Object/S] a map of name -> SymbolDef for all undeclared names",
|
||||
|
|
@ -789,7 +806,7 @@ var AST_ObjectGetter = DEFNODE("ObjectGetter", null, {
|
|||
$documentation: "An object getter property",
|
||||
}, AST_ObjectProperty);
|
||||
|
||||
var AST_Symbol = DEFNODE("Symbol", "scope name thedef", {
|
||||
var AST_Symbol = DEFNODE("Symbol", "scope! name thedef!", {
|
||||
$propdoc: {
|
||||
name: "[string] name of this symbol",
|
||||
scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)",
|
||||
|
|
|
|||
21
lib/utils.js
21
lib/utils.js
|
|
@ -214,6 +214,27 @@ function set_intersection(a, b) {
|
|||
});
|
||||
};
|
||||
|
||||
function dump_internal(val) {
|
||||
if (val) {
|
||||
if (typeof val.map == 'function') {
|
||||
return val.filter(function (x) {
|
||||
return x != null;
|
||||
}).map(dump_internal);
|
||||
}
|
||||
|
||||
if (val.CTOR) {
|
||||
var out = {_class: val._class};
|
||||
val.CTOR.DUMP_PROPS.forEach(function(prop){
|
||||
if (val[prop] != null) {
|
||||
out[prop] = dump_internal(val[prop]);
|
||||
}
|
||||
});
|
||||
return out;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
};
|
||||
|
||||
// this function is taken from Acorn [1], written by Marijn Haverbeke
|
||||
// [1] https://github.com/marijnh/acorn
|
||||
function makePredicate(words) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user