Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

add other assignment operator support

  • Loading branch information...
commit 6aa629d8b91ec5a134d87cc4fb4200f56742f5f8 1 parent 066ef86
@pissang authored
View
107 dfatool.js
@@ -816,28 +816,20 @@ Scope.prototype.initialize = function(){
return false;
case "VariableDeclarator":
if( node["init"]){
- var dfNode = scope.assign(node["id"], node["init"], scope.offsetLoc(node.loc.end) );
+ // in the case "var a = b = c;"
+ if( node["init"].type == "AssignmentExpression"){
+ processChainedAssignment( node["init"], currentBranch, scope.offsetLoc(node.loc.start) );
+ var dfNode = scope.assign(node["id"], node["init"]["left"], scope.offsetLoc(node.loc.end) );
+ }else{
+ var dfNode = scope.assign(node["id"], node["init"], scope.offsetLoc(node.loc.end) );
+ }
if( currentBranch && dfNode ){
dfNode.conditionalStatement = currentBranch;
}
- return false;
}
- break;
+ return false;
case "AssignmentExpression":
- // support the chained assign statement like "module.q = module.Q = module.dom.q";
- // will be convert to module.Q = module.dom.q; module.q = module.dom.q
- var leftNodes = [node.left],
- rightMost = node.right;
- while( rightMost.type == "AssignmentExpression" ){
- leftNodes.unshift(rightMost.left);
- rightMost = rightMost.right;
- }
- leftNodes.forEach(function(leftNode){
- var dfNode = scope.assign( leftNode, rightMost, scope.offsetLoc(node.loc.end) );
- if( currentBranch && dfNode ){
- dfNode.conditionalStatement = currentBranch;
- }
- })
+ processChainedAssignment( node, currentBranch, scope.offsetLoc(node.loc.start) );
return false;
case "ExpressionStatement":
// if the statement is a single call expression
@@ -900,6 +892,39 @@ Scope.prototype.initialize = function(){
} )
}
+ function processChainedAssignment( node, currentBranch, baseLoc ){
+ // support the chained assign statement like "module.q = module.Q = module.dom.q";
+ // will be convert to module.Q = module.dom.q; module.q = module.Q
+ var nodes = [],
+ operators = [],
+ current = node;
+ while( current.type == "AssignmentExpression" ){
+ nodes.unshift(current.left);
+ operators.unshift(current.operator);
+ current = current.right;
+ }
+ nodes.unshift(current);
+ // location of each assign item need to be reverted;
+ // like a = b = c, statment b=c need to be put in the left most, and then a = b;
+ // TODO: here simple revert still has some problem, for example fooooooo = a = b;
+ // the location of a is behind the statement of a = b, so value of fooooooo is still
+ // equal to previous value of a;
+ var loc = baseLoc;
+ for(var i = 0; i < nodes.length-1; i++){
+ var rightNode = nodes[i],
+ leftNode = nodes[i+1],
+ operator = operators[i];
+ loc += scope.offsetLoc(rightNode.loc.end) - scope.offsetLoc(leftNode.loc.start);
+ var dfNode = scope.assign( leftNode, rightNode, loc);
+ if( dfNode ){
+ dfNode.operator = operator;
+ if( currentBranch){
+ dfNode.conditionalStatement = currentBranch;
+ }
+ }
+ }
+ }
+
initializeInBranch( this.ast, null );
}
// spread the expression of each value to a fix point
@@ -1209,7 +1234,28 @@ Variable.merge = function(nodes){
if( ! node.accessPath ){// reaching definition
var value = node.value;
// create a new value with derived ast
- ret = new Snapshot( value );
+ if( node.operator == "="){
+ ret = new Snapshot( value );
+ // consider the compute assign operator
+ // += -= /= *= %=....
+ }else if(node.operator.substr(1) == "="){
+ var snapshot = new Snapshot( value);
+ if( snapshot.type == "literal"
+ && ret.type == "literal"){
+ try{
+ eval( "ret.ast.value "+node.operator+" snapshot.ast.value");
+ }catch(e){
+ log("Unkonwn operator "+node.operator);
+ }
+ ret.update(ret.ast);
+ }else{ // convert to binary expression
+ var bexp = TEMPLATE_BINARY_EXPRESSION(node.operator.substr(0, 1), ret.ast, snapshot.ast);
+ bexp.loc = snapshot.ast.loc;
+ snapshot.update( bexp );
+ ret = snapshot;
+ }
+ }
+
}else{ //assign an property
if(ret){
var value = node.value;
@@ -1261,7 +1307,8 @@ var AssignStatement = function(accessPath, rhs, scope){
this.attachValue( new Value(rhs, this.scope) );
}
this.loc = 0;
-
+ // operator canbe =, +=, -=, *=, /=, %=
+ this.operator = "=";
// the value is assigend in a conditional statement
// {ConditionalStatement}
this.conditionalStatement = null;
@@ -1290,6 +1337,7 @@ AssignStatement.prototype.attachValue = function(value, keepName /*optional*/){
// @read-only
keepName = isUndefined( keepName ) ? false : keepName;
if( ! keepName ){
+ // PENDING: distinguish the property name with variable name??
if( this.accessPath ){
this.accessPath = Value.prototype.solveAccessPath( this.accessPath );
var last = this.accessPath[ this.accessPath.length-1 ];
@@ -1495,7 +1543,6 @@ Value.prototype.update = function(ast){
default:
break;
}
- // set buildin
}
// add a prefix to avoid confict with native property like toString
@@ -1780,7 +1827,6 @@ var Snapshot = function( value ){
Value.call( this, value.getDerivedAst(), value.scope );
this.name = value.name;
-
}
Snapshot.prototype = Value.prototype;
@@ -2411,8 +2457,8 @@ ConditionalTree.prototype.findNode = function( conditionalStatement ){
return child;
}, this.root);
}
-ConditionalTree.prototype.buildAST = function(){
- return this.root.buildAST( this.variable.name );
+ConditionalTree.prototype.buildAST = function( name ){
+ return this.root.buildAST( name || this.variable.name );
}
ConditionalTree.Node = function( statement ){
@@ -2476,7 +2522,7 @@ ConditionalTree.Node.prototype.build = function( statement ){
ConditionalTree.Node.prototype.buildAST = function( varName ){
var consequent = TEMPLATE_BLOCK();
this.consequent.forEach( function( node ){
- consequent.body.push( node(buildAST) );
+ consequent.body.push( buildAST(node) );
} );
if( this.alternate.length ){
var alternate = TEMPLATE_BLOCK();
@@ -2704,6 +2750,19 @@ function asLibrary(variable){
//=========================================
// exports method
//=========================================
+exports.TEMPLATE_BLOCK = TEMPLATE_BLOCK
+exports.TEMPLATE_IDENTIFIER = TEMPLATE_IDENTIFIER
+exports.TEMPLATE_FUNCTION_DECLARATION = TEMPLATE_FUNCTION_DECLARATION
+exports.TEMPLATE_ASSIGNMENT_EXPRESSION = TEMPLATE_ASSIGNMENT_EXPRESSION
+exports.TEMPLATE_EXPRESSION_STATEMENT = TEMPLATE_EXPRESSION_STATEMENT
+exports.TEMPLATE_VARIABLE_DECLARATOR = TEMPLATE_VARIABLE_DECLARATOR
+exports.TEMPLATE_OBJECT_EXPRESSION = TEMPLATE_OBJECT_EXPRESSION
+exports.TEMPLATE_LITERAL_EXPRESSION = TEMPLATE_LITERAL_EXPRESSION
+exports.TEMPLATE_ARRAY_EXPRESSION = TEMPLATE_ARRAY_EXPRESSION
+exports.TEMPLATE_BINARY_EXPRESSION = TEMPLATE_BINARY_EXPRESSION
+exports.TEMPLATE_UNARY_EXPRESSION = TEMPLATE_UNARY_EXPRESSION
+exports.TEMPLATE_IF_STATEMENT = TEMPLATE_IF_STATEMENT
+exports.TEMPLATE_MEMBER_EXPRESSION = TEMPLATE_MEMBER_EXPRESSION
exports.walk = walk;
exports.buildScope = buildScope;
View
12 tests/cases/assign_operator.js
@@ -0,0 +1,12 @@
+var origin = 10;
+var sum = origin;
+var minus = origin;
+var product = origin;
+var quotient = origin;
+var remainder = origin;
+
+sum += 10;
+minus -= 10;
+product *= 10;
+quotient /= 10;
+remainder %= 10;
View
5 tests/cases/chained_assign.js
@@ -0,0 +1,5 @@
+var foo = 10;
+var bar = foo = 20;
+
+var something;
+something = foo = 30;
View
37 tests/outline.js
@@ -0,0 +1,37 @@
+var esprima = require('esprima');
+var dfatool = require('../dfatool');
+var fs = require('fs');
+var util = require('util');
+var codegen = require('escodegen');
+
+var argv = process.argv.slice(2);
+var fileName = argv[0];
+
+if( ! fileName){
+ console.error("Input scripts needed, 'node outline.js cases/array.js'");
+ return;
+}
+fs.readFile(fileName, 'utf-8', function(err, data){
+
+ var ast = esprima.parse(data, {
+ loc : true
+ });
+ var globalScope = dfatool.globalScope
+ dfatool.buildScope(ast, globalScope);
+
+ globalScope.initialize();
+ globalScope.derivation()
+
+ var outline = {};
+ for(var name in globalScope._defines){
+ var variable = globalScope._defines[name];
+ var value = variable.inference();
+ if( value ){
+ outline[variable.name] = value.toJSON();
+ }
+ }
+
+ console.log(util.inspect(outline, false, null));
+
+ dfatool.flushlog("log.txt");
+})
Please sign in to comment.
Something went wrong with that request. Please try again.