Merge pull request #81 from yann300/astCrawler

Ast Crawler
pull/7/head
yann300 8 years ago committed by GitHub
commit d304a2e3e1
  1. 4
      src/index.js
  2. 41
      src/util/astWalker.js
  3. 61
      test/astwalker.js
  4. 23
      test/resources/ast.js
  5. 2
      test/tests.js

@ -5,6 +5,7 @@ var BasicPanel = require('./ui/BasicPanel')
var TraceManager = require('./trace/traceManager')
var CodeManager = require('./code/codeManager')
var SourceMappingDecoder = require('./util/sourceMappingDecoder')
var AstWalker = require('./util/astWalker')
if (typeof (module) !== 'undefined' && typeof (module.exports) !== 'undefined') {
module.exports = modules()
@ -24,7 +25,8 @@ function modules () {
BasicPanel: BasicPanel
},
util: {
SourceMappingDecoder: SourceMappingDecoder
SourceMappingDecoder: SourceMappingDecoder,
AstWalker: AstWalker
}
}
}

@ -0,0 +1,41 @@
'use strict'
/**
* Crawl the given AST through the function walk(ast, callback)
*/
function AstWalker () {
}
/**
* visit all the AST nodes
*
* @param {Object} ast - AST node
* @param {Object or Function} callback - if (Function) the function will be called for every node.
* - if (Object) callback[<Node Type>] will be called for
* every node of type <Node Type>. callback["*"] will be called fo all other nodes.
* in each case, if the callback returns false it does not descend into children.
* If no callback for the current type, children are visited.
*/
AstWalker.prototype.walk = function (ast, callback) {
if (callback instanceof Function) {
callback = {'*': callback}
}
if (!('*' in callback)) {
callback['*'] = function () { return true }
}
if (manageCallBack(ast, callback) && ast.children && ast.children.length > 0) {
for (var k in ast.children) {
var child = ast.children[k]
this.walk(child, callback)
}
}
}
function manageCallBack (node, callback) {
if (node.name in callback) {
return callback[node.name](node)
} else {
return callback['*'](node)
}
}
module.exports = AstWalker

@ -0,0 +1,61 @@
'use strict'
var tape = require('tape')
var AstWalker = require('../src/util/astWalker')
var node = require('./resources/ast')
tape('ASTWalker', function (t) {
t.test('ASTWalker.walk', function (st) {
st.plan(24)
var astwalker = new AstWalker()
astwalker.walk(node.ast.AST, function (node) {
if (node.name === 'ContractDefinition') {
checkContract(st, node)
}
if (node.name === 'FunctionDefinition') {
checkSetFunction(st, node)
}
return true
})
var callback = {}
callback.FunctionDefinition = function (node) {
st.equal(node.name, 'FunctionDefinition')
st.equal(node.attributes.name === 'set' || node.attributes.name === 'get', true)
return true
}
astwalker.walk(node.ast.AST, callback)
})
})
function checkContract (st, node) {
st.equal(node.attributes.name, 'test')
st.equal(node.children[0].attributes.name, 'x')
st.equal(node.children[0].attributes.type, 'int256')
st.equal(node.children[1].attributes.name, 'y')
st.equal(node.children[1].attributes.type, 'int256')
st.equal(node.children[2].name, 'FunctionDefinition')
st.equal(node.children[2].attributes.constant, false)
st.equal(node.children[2].attributes.name, 'set')
st.equal(node.children[2].attributes.public, true)
}
function checkSetFunction (st, node) {
if (node.attributes.name === 'set') {
st.equal(node.children[0].name, 'ParameterList')
st.equal(node.children[1].name, 'ParameterList')
st.equal(node.children[2].name, 'Block')
st.equal(node.children[2].children[1].name, 'ExpressionStatement')
checkExpressionStatement(st, node.children[2].children[0])
}
}
function checkExpressionStatement (st, node) {
st.equal(node.children[0].name, 'Assignment')
st.equal(node.children[0].attributes.operator, '=')
st.equal(node.children[0].attributes.type, 'int256')
st.equal(node.children[0].children[0].name, 'Identifier')
st.equal(node.children[0].children[0].attributes.value, 'x')
st.equal(node.children[0].children[1].name, 'Identifier')
st.equal(node.children[0].children[1].attributes.value, '_x')
}

@ -0,0 +1,23 @@
var node = {}
node.ast = {"AST":{"children":[{"attributes":{"fullyImplemented":true,"isLibrary":false,"linearizedBaseContracts":[5640396],"name":"test"},"children":[{"attributes":{"name":"x","type":"int256"},"children":[{"attributes":{"name":"int"},"id":5657860,"name":"ElementaryTypeName","src":"21:3:11"}],"id":5658100,"name":"VariableDeclaration","src":"21:5:11"},{"attributes":{"name":"y","type":"int256"},"children":[{"attributes":{"name":"int"},"id":5658180,"name":"ElementaryTypeName","src":"38:3:11"}],"id":5658268,"name":"VariableDeclaration","src":"38:5:11"},{"attributes":{"constant":false,"name":"set","public":true},"children":[{"children":[{"attributes":{"name":"_x","type":"int256"},"children":[{"attributes":{"name":"int"},"id":5658404,"name":"ElementaryTypeName","src":"68:3:11"}],"id":5658492,"name":"VariableDeclaration","src":"68:6:11"}],"id":5658572,"name":"ParameterList","src":"67:8:11"},{"children":[{"attributes":{"name":"_r","type":"int256"},"children":[{"attributes":{"name":"int"},"id":5658628,"name":"ElementaryTypeName","src":"85:3:11"}],"id":5658716,"name":"VariableDeclaration","src":"85:6:11"}],"id":5658796,"name":"ParameterList","src":"84:8:11"},{"children":[{"children":[{"attributes":{"operator":"=","type":"int256"},"children":[{"attributes":{"type":"int256","value":"x"},"id":5658900,"name":"Identifier","src":"108:1:11"},{"attributes":{"type":"int256","value":"_x"},"id":5658980,"name":"Identifier","src":"112:2:11"}],"id":5657492,"name":"Assignment","src":"108:6:11"}],"id":5659028,"name":"ExpressionStatement","src":"108:6:11"},{"children":[{"attributes":{"operator":"=","type":"int256"},"children":[{"attributes":{"type":"int256","value":"y"},"id":5659116,"name":"Identifier","src":"125:1:11"},{"attributes":{"string":null,"type":"int_const 10","value":"10"},"id":5659196,"name":"Literal","src":"129:2:11"}],"id":5659252,"name":"Assignment","src":"125:6:11"}],"id":5659316,"name":"ExpressionStatement","src":"125:6:11"},{"children":[{"attributes":{"operator":"=","type":"int256"},"children":[{"attributes":{"type":"int256","value":"_r"},"id":5659428,"name":"Identifier","src":"141:2:11"},{"attributes":{"type":"int256","value":"x"},"id":5639308,"name":"Identifier","src":"146:1:11"}],"id":5639356,"name":"Assignment","src":"141:6:11"}],"id":5639420,"name":"ExpressionStatement","src":"141:6:11"}],"id":5639516,"name":"Block","src":"97:57:11"}],"id":5639612,"name":"FunctionDefinition","src":"55:99:11"},{"attributes":{"constant":false,"name":"get","public":true},"children":[{"children":[],"id":5639764,"name":"ParameterList","src":"179:2:11"},{"children":[{"attributes":{"name":"x","type":"uint256"},"children":[{"attributes":{"name":"uint"},"id":5639820,"name":"ElementaryTypeName","src":"191:4:11"}],"id":5639908,"name":"VariableDeclaration","src":"191:6:11"},{"attributes":{"name":"y","type":"uint256"},"children":[{"attributes":{"name":"uint"},"id":5639988,"name":"ElementaryTypeName","src":"199:4:11"}],"id":5640076,"name":"VariableDeclaration","src":"199:6:11"}],"id":5640156,"name":"ParameterList","src":"190:16:11"},{"children":[],"id":5640212,"name":"Block","src":"212:17:11"}],"id":5640276,"name":"FunctionDefinition","src":"167:62:11"}],"id":5640396,"name":"ContractDefinition","src":"0:231:11"}],"name":"SourceUnit"}}
node.source = `contract test {
int x;
int y;
function set(int _x) returns (int _r)
{
x = _x;
y = 10;
_r = x;
}
function get() returns (uint x, uint y)
{
}
}`
module.exports = node

@ -3,3 +3,5 @@ require('./index.js')
require('./traceManager.js')
require('./codeManager.js')
require('./util.js')
require('./astwalker.js')

Loading…
Cancel
Save