Add generating scope constraints

This commit is contained in:
Pavol Bielik 2015-01-25 00:11:19 +01:00
parent 23f79f2a10
commit b0412a6ae8
3 changed files with 106 additions and 5 deletions

View File

@ -15,9 +15,10 @@ var ARGS = yargs
.describe("skip_minified", "Whether to skip processing minified files")
.describe("features", "Comma separated list of features: \n" +
"ASTREL - relations in AST, \n" +
"FNAMES - function names to internal calls")
"FNAMES - function names to internal calls,\n" +
"FSCOPE - add variable scope constraints.")
.demand(1)
.default('features', 'ASTREL,FNAMES')
.default('features', 'ASTREL,FNAMES,FSCOPE')
.boolean("print_ast")
.boolean("skip_minified")
.boolean("json_formatting")
@ -45,8 +46,8 @@ if (ARGS.features === true) {
var features = ARGS.features.split(",");
for (var i = 0; i < features.length; i++) {
if (features[i] != "FNAMES" && features[i] != "ASTREL") {
sys.error("WARNING: ignoring not suppored feature '" + features[i] + "'.");
if (features[i] != "FNAMES" && features[i] != "ASTREL" && features[i] != "FSCOPE") {
sys.error("WARNING: ignoring not supported feature '" + features[i] + "'.");
};
};

View File

@ -89,6 +89,10 @@ function extractFeatures(code, file, print_ast, features, skip_minified) {
generateFnamesFeatures(toplevel, feature_outputter);
}
if (features.indexOf("FSCOPE") != -1) {
generateFscopeConstraints(toplevel, feature_outputter);
}
feature_outputter.closeArray();
feature_outputter.dumpSymbols();
feature_outputter.closeElem();
@ -247,6 +251,37 @@ function addFeatures(lhss, lhs_label, rhs, rhs_label, feature_outputter){
}
}
function addScopeConstraints(node, toplevel, feature_outputter){
feature_outputter.beginScope();
var name = nodeToString(node);
if (name != null)
feature_outputter.addToScope(name);
for (var i = 0; i < node.enclosed.length; i++){
feature_outputter.addToScope(nodeToString(node.enclosed[i].orig[0]));
}
node.variables.each(function(symbol){
feature_outputter.addToScope(nodeToString(symbol.orig[0]));
});
toplevel.globals.each(function(symbol){
feature_outputter.addToScope(nodeToString(symbol.orig[0]));
});
feature_outputter.endScope();
}
function generateFscopeConstraints(toplevel, feature_outputter){
addScopeConstraints(toplevel, toplevel, feature_outputter);
toplevel.walk(new TreeWalker(function(node) {
if (node instanceof AST_Defun || node instanceof AST_Lambda) {
addScopeConstraints(node, toplevel, feature_outputter);
}
}));
}
function generateFnamesFeatures(toplevel, feature_outputter){
var outer_funcs = [];
@ -321,6 +356,7 @@ function FeatureJsonOutputter() {
this.output = "";
this.depth = 0;
this.pairs = {};
this.cur_scope = {};
}
FeatureJsonOutputter.prototype.indent = function() {
@ -428,6 +464,35 @@ FeatureJsonOutputter.prototype.dumpSymbols = function(){
this.closeArray();
};
FeatureJsonOutputter.prototype.beginScope = function(){
this.cur_scope = {};
};
FeatureJsonOutputter.prototype.addToScope = function(a){
var a_id = this.string_map.getId(a);
this.cur_scope[a_id] = true;
};
FeatureJsonOutputter.prototype.endScope = function(){
//{"cn":"!=","n":[14,366,370,372,108,40,356]}
var keys = Object.keys(this.cur_scope);
if (keys.length <= 1) {
return;
}
this.openElem();
this.output += '"cn":"!=", "n":[';
this.output += keys[0];
for(var i = 1,length = keys.length; i < length; i++ ) {
this.output += ',';
this.output += keys[i];
}
this.output += "]";
this.closeElem();
};
/* -----[ StringMap ]----- */
function StringMap(nice_names) {

View File

@ -244,3 +244,38 @@ func_return: {
}'
}
}
func_scopes: {
options = {
features : "FNAMES, FSCOPE"
};
input: {
function foo(x,b){
var a = x + y + 1;
(function(r) {
return r + x;
})(2);
}
}
expect: {
'{
"query":[
{"a": 0, "b": 1, "f2": "FNPAR"},
{"a": 0, "b": 2, "f2": "FNPAR"},
{"a": 0, "b": 3, "f2": "FNDECL"},
{"cn":"!=", "n":[0,4]},
{"cn":"!=", "n":[0,1,2,3,4]},
{"cn":"!=", "n":[1,4,5]}
],
"assign":[
{"v": 0, "giv": "foo"},
{"v": 1, "inf": "x"},
{"v": 2, "inf": "b"},
{"v": 3, "inf": "a"},
{"v": 4, "giv": "y"},
{"v": 5, "inf": "r"}
]
}'
}
}