build tree without while loop

pull/7/head
yann300 8 years ago
parent 1d56742b15
commit b989f1a453
  1. 121
      src/util/internalCallTree.js

@ -8,6 +8,7 @@ var util = require('../helpers/util')
/** /**
* Tree representing internal jump into function. * Tree representing internal jump into function.
* Trigger `callTreeReady` event when tree is ready * Trigger `callTreeReady` event when tree is ready
* Trigger `callTreeBuildFailed` event when tree fails to build
*/ */
class InternalCallTree { class InternalCallTree {
/** /**
@ -30,9 +31,14 @@ class InternalCallTree {
if (!this.solidityProxy.loaded()) { if (!this.solidityProxy.loaded()) {
console.log('compilation result not loaded. Cannot build internal call tree') console.log('compilation result not loaded. Cannot build internal call tree')
} else { } else {
buildTree(this, 0, '', trace) buildTree(this, 0, '', (error) => {
if (!error) {
this.event.trigger('callTreeReady', [this.scopes, this.scopeStarts])
} else {
this.event.trigger('callTreeBuildFailed', [error])
}
})
} }
this.event.trigger('callTreeReady', [this.scopes, this.scopeStarts])
}) })
} }
@ -76,60 +82,79 @@ class InternalCallTree {
} }
} }
/** /**
* build tree (called recursively) * build tree (called recursively)
* *
* @param {Object} tree - instance of InternalCallTree * @param {Object} tree - instance of InternalCallTree
* @param {Int} step - index on the vm trace * @param {Int} step - index on the vm trace
* @param {String} scopeId - deepness of the current scope * @param {String} scopeId - deepness of the current scope
* @param {Object} trace - vm trace * @param {Function} cb - callback
*/ */
function buildTree (tree, step, scopeId, trace) { function buildTree (tree, step, scopeId, cb) {
let subScope = 1 let subScope = 1
tree.scopeStarts[step] = scopeId tree.scopeStarts[step] = scopeId
tree.scopes[scopeId] = { firstStep: step } tree.scopes[scopeId] = { firstStep: step, locals: {} }
while (step < trace.length) { visitStep(tree, step, scopeId, subScope, function (error, result) {
var sourceLocation cb(error, result)
extractSourceLocation(tree, step, (error, src) => { })
if (error) { }
console.log(error)
} else { /**
sourceLocation = src * visit a step (called recursively)
} *
}) * @param {Object} tree - instance of InternalCallTree
if (sourceLocation.jump === 'i') { * @param {Int} step - index on the vm trace
step = buildTree(tree, step + 1, scopeId === '' ? subScope.toString() : scopeId + '.' + subScope, trace) * @param {String} scopeId - deepness of the current scope
subScope++ * @param {Int} subScope - index of the next scope from current scope
} else if (sourceLocation.jump === 'o') { * @param {Function} cb - callback
tree.scopes[scopeId].lastStep = step */
return step + 1 function visitStep (tree, step, scopeId, subScope, cb) {
extractSourceLocation(tree, step, (error, sourceLocation) => {
if (error) {
console.log(error)
} else { } else {
if (tree.includeLocalVariables) { if (sourceLocation.jump === 'i') {
var variableDeclaration = resolveVariableDeclaration(tree, step, sourceLocation) buildTree(tree, step + 1, scopeId === '' ? subScope.toString() : scopeId + '.' + subScope, function (error, outStep) {
if (variableDeclaration) { if (!error) {
if (!tree.scopes[scopeId].locals) { visitStep(tree, outStep, scopeId, subScope + 1, cb)
tree.scopes[scopeId].locals = {} } else {
cb('error computing jump')
} }
tree.traceManager.getStackAt(step, (error, stack) => { })
if (!error) { return
tree.solidityProxy.contractNameAt(step, (error, contractName) => { // cached } else if (sourceLocation.jump === 'o') {
if (!error) { tree.scopes[scopeId].lastStep = step
var states = tree.solidityProxy.extractStatesDefinitions() cb(null, step + 1)
tree.scopes[scopeId].locals[variableDeclaration.attributes.name] = { return
name: variableDeclaration.attributes.name, } else {
type: decodeInfo.parseType(variableDeclaration.attributes.type, states, contractName), if (tree.includeLocalVariables) {
stackHeight: stack.length var variableDeclaration = resolveVariableDeclaration(tree, step, sourceLocation)
if (variableDeclaration) {
tree.traceManager.getStackAt(step, (error, stack) => {
if (!error) {
tree.solidityProxy.contractNameAt(step, (error, contractName) => { // cached
if (!error) {
var states = tree.solidityProxy.extractStatesDefinitions()
tree.scopes[scopeId].locals[variableDeclaration.attributes.name] = {
name: variableDeclaration.attributes.name,
type: decodeInfo.parseType(variableDeclaration.attributes.type, states, contractName),
stackHeight: stack.length
}
} }
} })
}) }
} })
}) }
} }
step++
}
if (tree.traceManager.inRange(step)) {
visitStep(tree, step, scopeId, subScope, cb)
} else {
cb(null, step)
} }
step++
} }
} })
} }
function extractSourceLocation (tree, step, cb) { function extractSourceLocation (tree, step, cb) {

Loading…
Cancel
Save