subtly
10 years ago
147 changed files with 5908 additions and 1658 deletions
@ -0,0 +1 @@ |
|||
/build/ |
@ -0,0 +1,34 @@ |
|||
#include "interface.h" |
|||
#include <cstdio> |
|||
#include "ExecutionEngine.h" |
|||
|
|||
extern "C" |
|||
{ |
|||
|
|||
evmjit_result evmjit_run(void* _data, void* _env) |
|||
{ |
|||
using namespace dev::eth::jit; |
|||
|
|||
auto data = static_cast<RuntimeData*>(_data); |
|||
|
|||
ExecutionEngine engine; |
|||
|
|||
auto codePtr = data->code; |
|||
auto codeSize = data->elems[RuntimeData::CodeSize].a; |
|||
bytes bytecode; |
|||
bytecode.insert(bytecode.end(), codePtr, codePtr + codeSize); |
|||
|
|||
auto returnCode = engine.run(bytecode, data, static_cast<Env*>(_env)); |
|||
evmjit_result result = {static_cast<int32_t>(returnCode), 0, nullptr}; |
|||
if (returnCode == ReturnCode::Return && !engine.returnData.empty()) |
|||
{ |
|||
// TODO: Optimized returning data. Allocating memory on client side by callback function might be a good idea
|
|||
result.returnDataSize = engine.returnData.size(); |
|||
result.returnData = std::malloc(result.returnDataSize); |
|||
std::memcpy(result.returnData, engine.returnData.data(), result.returnDataSize); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
} |
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,8 +1,11 @@ |
|||
var web3 = require('./lib/web3'); |
|||
var ProviderManager = require('./lib/providermanager'); |
|||
web3.provider = new ProviderManager(); |
|||
web3.filter = require('./lib/filter'); |
|||
web3.providers.WebSocketProvider = require('./lib/websocket'); |
|||
web3.providers.HttpRpcProvider = require('./lib/httprpc'); |
|||
web3.providers.QtProvider = require('./lib/qt'); |
|||
web3.providers.AutoProvider = require('./lib/autoprovider'); |
|||
web3.contract = require('./lib/contract'); |
|||
web3.eth.contract = require('./lib/contract'); |
|||
|
|||
module.exports = web3; |
|||
|
@ -0,0 +1,86 @@ |
|||
/* |
|||
This file is part of ethereum.js. |
|||
|
|||
ethereum.js is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU Lesser General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
ethereum.js is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU Lesser General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Lesser General Public License |
|||
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file filter.js |
|||
* @authors: |
|||
* Jeffrey Wilcke <jeff@ethdev.com> |
|||
* Marek Kotewicz <marek@ethdev.com> |
|||
* Marian Oancea <marian@ethdev.com> |
|||
* Gav Wood <g@ethdev.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
var web3 = require('./web3'); // jshint ignore:line
|
|||
|
|||
/// should be used when we want to watch something
|
|||
/// it's using inner polling mechanism and is notified about changes
|
|||
var Filter = function(options, impl) { |
|||
this.impl = impl; |
|||
this.callbacks = []; |
|||
|
|||
var self = this; |
|||
this.promise = impl.newFilter(options); |
|||
this.promise.then(function (id) { |
|||
self.id = id; |
|||
web3.on(impl.changed, id, self.trigger.bind(self)); |
|||
web3.provider.startPolling({call: impl.changed, args: [id]}, id); |
|||
}); |
|||
}; |
|||
|
|||
/// alias for changed*
|
|||
Filter.prototype.arrived = function(callback) { |
|||
this.changed(callback); |
|||
}; |
|||
|
|||
/// gets called when there is new eth/shh message
|
|||
Filter.prototype.changed = function(callback) { |
|||
var self = this; |
|||
this.promise.then(function(id) { |
|||
self.callbacks.push(callback); |
|||
}); |
|||
}; |
|||
|
|||
/// trigger calling new message from people
|
|||
Filter.prototype.trigger = function(messages) { |
|||
for(var i = 0; i < this.callbacks.length; i++) { |
|||
this.callbacks[i].call(this, messages); |
|||
} |
|||
}; |
|||
|
|||
/// should be called to uninstall current filter
|
|||
Filter.prototype.uninstall = function() { |
|||
var self = this; |
|||
this.promise.then(function (id) { |
|||
self.impl.uninstallFilter(id); |
|||
web3.provider.stopPolling(id); |
|||
web3.off(impl.changed, id); |
|||
}); |
|||
}; |
|||
|
|||
/// should be called to manually trigger getting latest messages from the client
|
|||
Filter.prototype.messages = function() { |
|||
var self = this; |
|||
return this.promise.then(function (id) { |
|||
return self.impl.getMessages(id); |
|||
}); |
|||
}; |
|||
|
|||
/// alias for messages
|
|||
Filter.prototype.logs = function () { |
|||
return this.messages(); |
|||
}; |
|||
|
|||
module.exports = Filter; |
@ -0,0 +1,119 @@ |
|||
/* |
|||
This file is part of ethereum.js. |
|||
|
|||
ethereum.js is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU Lesser General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
ethereum.js is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU Lesser General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Lesser General Public License |
|||
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file providermanager.js |
|||
* @authors: |
|||
* Jeffrey Wilcke <jeff@ethdev.com> |
|||
* Marek Kotewicz <marek@ethdev.com> |
|||
* Marian Oancea <marian@ethdev.com> |
|||
* Gav Wood <g@ethdev.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
var web3 = require('./web3'); // jshint ignore:line
|
|||
|
|||
/** |
|||
* Provider manager object prototype |
|||
* It's responsible for passing messages to providers |
|||
* If no provider is set it's responsible for queuing requests |
|||
* It's also responsible for polling the ethereum node for incoming messages |
|||
* Default poll timeout is 12 seconds |
|||
* If we are running ethereum.js inside ethereum browser, there are backend based tools responsible for polling, |
|||
* and provider manager polling mechanism is not used |
|||
*/ |
|||
var ProviderManager = function() { |
|||
this.queued = []; |
|||
this.polls = []; |
|||
this.ready = false; |
|||
this.provider = undefined; |
|||
this.id = 1; |
|||
|
|||
var self = this; |
|||
var poll = function () { |
|||
if (self.provider && self.provider.poll) { |
|||
self.polls.forEach(function (data) { |
|||
data.data._id = self.id; |
|||
self.id++; |
|||
self.provider.poll(data.data, data.id); |
|||
}); |
|||
} |
|||
setTimeout(poll, 12000); |
|||
}; |
|||
poll(); |
|||
}; |
|||
|
|||
/// sends outgoing requests, if provider is not available, enqueue the request
|
|||
ProviderManager.prototype.send = function(data, cb) { |
|||
data._id = this.id; |
|||
if (cb) { |
|||
web3._callbacks[data._id] = cb; |
|||
} |
|||
|
|||
data.args = data.args || []; |
|||
this.id++; |
|||
|
|||
if(this.provider !== undefined) { |
|||
this.provider.send(data); |
|||
} else { |
|||
console.warn("provider is not set"); |
|||
this.queued.push(data); |
|||
} |
|||
}; |
|||
|
|||
/// setups provider, which will be used for sending messages
|
|||
ProviderManager.prototype.set = function(provider) { |
|||
if(this.provider !== undefined && this.provider.unload !== undefined) { |
|||
this.provider.unload(); |
|||
} |
|||
|
|||
this.provider = provider; |
|||
this.ready = true; |
|||
}; |
|||
|
|||
/// resends queued messages
|
|||
ProviderManager.prototype.sendQueued = function() { |
|||
for(var i = 0; this.queued.length; i++) { |
|||
// Resend
|
|||
this.send(this.queued[i]); |
|||
} |
|||
}; |
|||
|
|||
/// @returns true if the provider i properly set
|
|||
ProviderManager.prototype.installed = function() { |
|||
return this.provider !== undefined; |
|||
}; |
|||
|
|||
/// this method is only used, when we do not have native qt bindings and have to do polling on our own
|
|||
/// should be callled, on start watching for eth/shh changes
|
|||
ProviderManager.prototype.startPolling = function (data, pollId) { |
|||
if (!this.provider || !this.provider.poll) { |
|||
return; |
|||
} |
|||
this.polls.push({data: data, id: pollId}); |
|||
}; |
|||
|
|||
/// should be called to stop polling for certain watch changes
|
|||
ProviderManager.prototype.stopPolling = function (pollId) { |
|||
for (var i = this.polls.length; i--;) { |
|||
var poll = this.polls[i]; |
|||
if (poll.id === pollId) { |
|||
this.polls.splice(i, 1); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
module.exports = ProviderManager; |
|||
|
@ -1,37 +1,827 @@ |
|||
var assert = require('assert'); |
|||
var BigNumber = require('bignumber.js'); |
|||
var abi = require('../lib/abi.js'); |
|||
var clone = function (object) { return JSON.parse(JSON.stringify(object)); }; |
|||
|
|||
var description = [{ |
|||
"name": "test", |
|||
"inputs": [{ |
|||
"name": "a", |
|||
"type": "uint256" |
|||
} |
|||
], |
|||
"outputs": [ |
|||
{ |
|||
"name": "d", |
|||
"type": "uint256" |
|||
} |
|||
] |
|||
}]; |
|||
|
|||
describe('abi', function() { |
|||
describe('inputParser', function() { |
|||
it('should parse ...', function() { |
|||
|
|||
var desc = [{ |
|||
"name": "multiply", |
|||
"inputs": [ |
|||
{ |
|||
"name": "a", |
|||
"type": "uint256" |
|||
} |
|||
], |
|||
"outputs": [ |
|||
{ |
|||
"name": "d", |
|||
"type": "uint256" |
|||
} |
|||
] |
|||
it('should parse input uint', function() { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].inputs = [ |
|||
{ type: "uint" } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.inputParser(d); |
|||
|
|||
// then
|
|||
assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); |
|||
assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); |
|||
assert.equal( |
|||
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), |
|||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" |
|||
); |
|||
assert.equal( |
|||
parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), |
|||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" |
|||
); |
|||
assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); |
|||
assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); |
|||
assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); |
|||
assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); |
|||
|
|||
|
|||
}); |
|||
|
|||
it('should parse input uint128', function() { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].inputs = [ |
|||
{ type: "uint128" } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.inputParser(d); |
|||
|
|||
// then
|
|||
assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); |
|||
assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); |
|||
assert.equal( |
|||
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), |
|||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" |
|||
); |
|||
assert.equal( |
|||
parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), |
|||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" |
|||
); |
|||
assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); |
|||
assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); |
|||
assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); |
|||
assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); |
|||
|
|||
}); |
|||
|
|||
it('should parse input uint256', function() { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].inputs = [ |
|||
{ type: "uint256" } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.inputParser(d); |
|||
|
|||
// then
|
|||
assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); |
|||
assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); |
|||
assert.equal( |
|||
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), |
|||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" |
|||
); |
|||
assert.equal( |
|||
parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), |
|||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" |
|||
); |
|||
assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); |
|||
assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); |
|||
assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); |
|||
assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); |
|||
|
|||
}); |
|||
|
|||
it('should parse input int', function() { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].inputs = [ |
|||
{ type: "int" } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.inputParser(d); |
|||
|
|||
// then
|
|||
assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); |
|||
assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); |
|||
assert.equal(parser.test(-1), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); |
|||
assert.equal(parser.test(-2), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); |
|||
assert.equal(parser.test(-16), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0"); |
|||
assert.equal( |
|||
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), |
|||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" |
|||
); |
|||
assert.equal( |
|||
parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), |
|||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" |
|||
); |
|||
assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); |
|||
assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); |
|||
assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); |
|||
assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); |
|||
}); |
|||
|
|||
it('should parse input int128', function() { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].inputs = [ |
|||
{ type: "int128" } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.inputParser(d); |
|||
|
|||
// then
|
|||
assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); |
|||
assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); |
|||
assert.equal(parser.test(-1), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); |
|||
assert.equal(parser.test(-2), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); |
|||
assert.equal(parser.test(-16), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0"); |
|||
assert.equal( |
|||
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), |
|||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" |
|||
); |
|||
assert.equal( |
|||
parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), |
|||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" |
|||
); |
|||
assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); |
|||
assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); |
|||
assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); |
|||
assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); |
|||
|
|||
}); |
|||
|
|||
it('should parse input int256', function() { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].inputs = [ |
|||
{ type: "int256" } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.inputParser(d); |
|||
|
|||
// then
|
|||
assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); |
|||
assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); |
|||
assert.equal(parser.test(-1), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); |
|||
assert.equal(parser.test(-2), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); |
|||
assert.equal(parser.test(-16), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0"); |
|||
assert.equal( |
|||
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), |
|||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" |
|||
); |
|||
assert.equal( |
|||
parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), |
|||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" |
|||
); |
|||
assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); |
|||
assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); |
|||
assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); |
|||
assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); |
|||
|
|||
}); |
|||
|
|||
it('should parse input bool', function() { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].inputs = [ |
|||
{ type: 'bool' } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.inputParser(d); |
|||
|
|||
// then
|
|||
assert.equal(parser.test(true), "0000000000000000000000000000000000000000000000000000000000000001"); |
|||
assert.equal(parser.test(false), "0000000000000000000000000000000000000000000000000000000000000000"); |
|||
|
|||
}); |
|||
|
|||
it('should parse input hash', function() { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].inputs = [ |
|||
{ type: "hash" } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.inputParser(d); |
|||
|
|||
// then
|
|||
assert.equal(parser.test("0x407d73d8a49eeb85d32cf465507dd71d507100c1"), "000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"); |
|||
|
|||
}); |
|||
|
|||
it('should parse input hash256', function() { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].inputs = [ |
|||
{ type: "hash256" } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.inputParser(d); |
|||
|
|||
// then
|
|||
assert.equal(parser.test("0x407d73d8a49eeb85d32cf465507dd71d507100c1"), "000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"); |
|||
|
|||
}); |
|||
|
|||
|
|||
it('should parse input hash160', function() { |
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].inputs = [ |
|||
{ type: "hash160" } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.inputParser(d); |
|||
|
|||
// then
|
|||
assert.equal(parser.test("0x407d73d8a49eeb85d32cf465507dd71d507100c1"), "000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"); |
|||
}); |
|||
|
|||
it('should parse input address', function () { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].inputs = [ |
|||
{ type: "address" } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.inputParser(d) |
|||
|
|||
// then
|
|||
assert.equal(parser.test("0x407d73d8a49eeb85d32cf465507dd71d507100c1"), "000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"); |
|||
|
|||
}); |
|||
|
|||
it('should parse input string', function () { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].inputs = [ |
|||
{ type: "string" } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.inputParser(d); |
|||
|
|||
// then
|
|||
assert.equal( |
|||
parser.test('hello'), |
|||
"000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000" |
|||
); |
|||
assert.equal( |
|||
parser.test('world'), |
|||
"0000000000000000000000000000000000000000000000000000000000000005776f726c64000000000000000000000000000000000000000000000000000000" |
|||
); |
|||
}); |
|||
|
|||
it('should use proper method name', function () { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
d[0].name = 'helloworld'; |
|||
d[0].inputs = [ |
|||
{ type: "int" } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.inputParser(d); |
|||
|
|||
// then
|
|||
assert.equal(parser.helloworld(1), "0000000000000000000000000000000000000000000000000000000000000001"); |
|||
|
|||
}); |
|||
|
|||
it('should parse multiple methods', function () { |
|||
|
|||
// given
|
|||
var d = [{ |
|||
name: "test", |
|||
inputs: [{ type: "int" }], |
|||
outputs: [{ type: "int" }] |
|||
},{ |
|||
name: "test2", |
|||
inputs: [{ type: "string" }], |
|||
outputs: [{ type: "string" }] |
|||
}]; |
|||
|
|||
var iParser = abi.inputParser(desc); |
|||
assert.equal(iParser.multiply(1), "0x000000000000000000000000000000000000000000000000000000000000000001"); |
|||
// when
|
|||
var parser = abi.inputParser(d); |
|||
|
|||
//then
|
|||
assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); |
|||
assert.equal( |
|||
parser.test2('hello'), |
|||
"000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000" |
|||
); |
|||
|
|||
}); |
|||
}); |
|||
|
|||
it('should parse input array of ints', function () { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].inputs = [ |
|||
{ type: "int[]" } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.inputParser(d); |
|||
|
|||
// then
|
|||
assert.equal( |
|||
parser.test([5, 6]), |
|||
"0000000000000000000000000000000000000000000000000000000000000002" + |
|||
"0000000000000000000000000000000000000000000000000000000000000005" + |
|||
"0000000000000000000000000000000000000000000000000000000000000006" |
|||
); |
|||
}); |
|||
|
|||
it('should parse input real', function () { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].inputs = [ |
|||
{ type: 'real' } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.inputParser(d); |
|||
|
|||
// then
|
|||
assert.equal(parser.test([1]), "0000000000000000000000000000000100000000000000000000000000000000"); |
|||
assert.equal(parser.test([2.125]), "0000000000000000000000000000000220000000000000000000000000000000"); |
|||
assert.equal(parser.test([8.5]), "0000000000000000000000000000000880000000000000000000000000000000"); |
|||
assert.equal(parser.test([-1]), "ffffffffffffffffffffffffffffffff00000000000000000000000000000000"); |
|||
|
|||
}); |
|||
|
|||
it('should parse input ureal', function () { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].inputs = [ |
|||
{ type: 'ureal' } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.inputParser(d); |
|||
|
|||
// then
|
|||
assert.equal(parser.test([1]), "0000000000000000000000000000000100000000000000000000000000000000"); |
|||
assert.equal(parser.test([2.125]), "0000000000000000000000000000000220000000000000000000000000000000"); |
|||
assert.equal(parser.test([8.5]), "0000000000000000000000000000000880000000000000000000000000000000"); |
|||
|
|||
}); |
|||
|
|||
}); |
|||
|
|||
describe('outputParser', function() { |
|||
it('parse ...', function() { |
|||
it('should parse output string', function() { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].outputs = [ |
|||
{ type: "string" } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.outputParser(d); |
|||
|
|||
// then
|
|||
assert.equal( |
|||
parser.test("0x" + |
|||
"0000000000000000000000000000000000000000000000000000000000000005" + |
|||
"68656c6c6f000000000000000000000000000000000000000000000000000000")[0], |
|||
'hello' |
|||
); |
|||
assert.equal( |
|||
parser.test("0x" + |
|||
"0000000000000000000000000000000000000000000000000000000000000005" + |
|||
"776f726c64000000000000000000000000000000000000000000000000000000")[0], |
|||
'world' |
|||
); |
|||
|
|||
}); |
|||
|
|||
it('should parse output uint', function() { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].outputs = [ |
|||
{ type: 'uint' } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.outputParser(d); |
|||
|
|||
// then
|
|||
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); |
|||
assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); |
|||
assert.equal( |
|||
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10), |
|||
new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).toString(10) |
|||
); |
|||
assert.equal( |
|||
parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10), |
|||
new BigNumber("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", 16).toString(10) |
|||
); |
|||
}); |
|||
|
|||
it('should parse output uint256', function() { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].outputs = [ |
|||
{ type: 'uint256' } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.outputParser(d); |
|||
|
|||
// then
|
|||
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); |
|||
assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); |
|||
assert.equal( |
|||
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10), |
|||
new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).toString(10) |
|||
); |
|||
assert.equal( |
|||
parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10), |
|||
new BigNumber("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", 16).toString(10) |
|||
); |
|||
}); |
|||
|
|||
it('should parse output uint128', function() { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].outputs = [ |
|||
{ type: 'uint128' } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.outputParser(d); |
|||
|
|||
// then
|
|||
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); |
|||
assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); |
|||
assert.equal( |
|||
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10), |
|||
new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).toString(10) |
|||
); |
|||
assert.equal( |
|||
parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10), |
|||
new BigNumber("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", 16).toString(10) |
|||
); |
|||
}); |
|||
|
|||
it('should parse output int', function() { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].outputs = [ |
|||
{ type: 'int' } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.outputParser(d); |
|||
|
|||
// then
|
|||
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); |
|||
assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); |
|||
assert.equal(parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0], -1); |
|||
assert.equal(parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0], -16); |
|||
}); |
|||
|
|||
it('should parse output int256', function() { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].outputs = [ |
|||
{ type: 'int256' } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.outputParser(d); |
|||
|
|||
// then
|
|||
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); |
|||
assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); |
|||
assert.equal(parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0], -1); |
|||
assert.equal(parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0], -16); |
|||
}); |
|||
|
|||
it('should parse output int128', function() { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].outputs = [ |
|||
{ type: 'int128' } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.outputParser(d); |
|||
|
|||
// then
|
|||
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); |
|||
assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10); |
|||
assert.equal(parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0], -1); |
|||
assert.equal(parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0], -16); |
|||
}); |
|||
|
|||
it('should parse output hash', function() { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].outputs = [ |
|||
{ type: 'hash' } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.outputParser(d); |
|||
|
|||
// then
|
|||
assert.equal( |
|||
parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], |
|||
"0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1" |
|||
); |
|||
}); |
|||
|
|||
it('should parse output hash256', function() { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].outputs = [ |
|||
{ type: 'hash256' } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.outputParser(d); |
|||
|
|||
// then
|
|||
assert.equal( |
|||
parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], |
|||
"0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1" |
|||
); |
|||
}); |
|||
|
|||
it('should parse output hash160', function() { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].outputs = [ |
|||
{ type: 'hash160' } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.outputParser(d); |
|||
|
|||
// then
|
|||
assert.equal( |
|||
parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], |
|||
"0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1" |
|||
); |
|||
// TODO shouldnt' the expected hash be shorter?
|
|||
}); |
|||
|
|||
it('should parse output address', function() { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].outputs = [ |
|||
{ type: 'address' } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.outputParser(d); |
|||
|
|||
// then
|
|||
assert.equal( |
|||
parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], |
|||
"0x407d73d8a49eeb85d32cf465507dd71d507100c1" |
|||
); |
|||
}); |
|||
|
|||
it('should parse output bool', function() { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].outputs = [ |
|||
{ type: 'bool' } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.outputParser(d); |
|||
|
|||
// then
|
|||
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], true); |
|||
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000000")[0], false); |
|||
|
|||
|
|||
}); |
|||
|
|||
it('should parse output real', function() { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].outputs = [ |
|||
{ type: 'real' } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.outputParser(d); |
|||
|
|||
// then
|
|||
assert.equal(parser.test("0x0000000000000000000000000000000100000000000000000000000000000000")[0], 1); |
|||
assert.equal(parser.test("0x0000000000000000000000000000000220000000000000000000000000000000")[0], 2.125); |
|||
assert.equal(parser.test("0x0000000000000000000000000000000880000000000000000000000000000000")[0], 8.5); |
|||
assert.equal(parser.test("0xffffffffffffffffffffffffffffffff00000000000000000000000000000000")[0], -1); |
|||
|
|||
}); |
|||
|
|||
it('should parse output ureal', function() { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].outputs = [ |
|||
{ type: 'ureal' } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.outputParser(d); |
|||
|
|||
// then
|
|||
assert.equal(parser.test("0x0000000000000000000000000000000100000000000000000000000000000000")[0], 1); |
|||
assert.equal(parser.test("0x0000000000000000000000000000000220000000000000000000000000000000")[0], 2.125); |
|||
assert.equal(parser.test("0x0000000000000000000000000000000880000000000000000000000000000000")[0], 8.5); |
|||
|
|||
}); |
|||
|
|||
|
|||
it('should parse multiple output strings', function() { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
|
|||
d[0].outputs = [ |
|||
{ type: "string" }, |
|||
{ type: "string" } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.outputParser(d); |
|||
|
|||
// then
|
|||
assert.equal( |
|||
parser.test("0x" + |
|||
"0000000000000000000000000000000000000000000000000000000000000005" + |
|||
"0000000000000000000000000000000000000000000000000000000000000005" + |
|||
"68656c6c6f000000000000000000000000000000000000000000000000000000" + |
|||
"776f726c64000000000000000000000000000000000000000000000000000000")[0], |
|||
'hello' |
|||
); |
|||
assert.equal( |
|||
parser.test("0x" + |
|||
"0000000000000000000000000000000000000000000000000000000000000005" + |
|||
"0000000000000000000000000000000000000000000000000000000000000005" + |
|||
"68656c6c6f000000000000000000000000000000000000000000000000000000" + |
|||
"776f726c64000000000000000000000000000000000000000000000000000000")[1], |
|||
'world' |
|||
); |
|||
|
|||
}); |
|||
|
|||
it('should use proper method name', function () { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
d[0].name = 'helloworld'; |
|||
d[0].outputs = [ |
|||
{ type: "int" } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.outputParser(d); |
|||
|
|||
// then
|
|||
assert.equal(parser.helloworld("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1); |
|||
|
|||
}); |
|||
|
|||
|
|||
it('should parse multiple methods', function () { |
|||
|
|||
// given
|
|||
var d = [{ |
|||
name: "test", |
|||
inputs: [{ type: "int" }], |
|||
outputs: [{ type: "int" }] |
|||
},{ |
|||
name: "test2", |
|||
inputs: [{ type: "string" }], |
|||
outputs: [{ type: "string" }] |
|||
}]; |
|||
|
|||
// when
|
|||
var parser = abi.outputParser(d); |
|||
|
|||
//then
|
|||
assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], 1); |
|||
assert.equal(parser.test2("0x" + |
|||
"0000000000000000000000000000000000000000000000000000000000000005" + |
|||
"68656c6c6f000000000000000000000000000000000000000000000000000000")[0], |
|||
"hello" |
|||
); |
|||
|
|||
}); |
|||
|
|||
it('should parse output array', function () { |
|||
|
|||
// given
|
|||
var d = clone(description); |
|||
d[0].outputs = [ |
|||
{ type: 'int[]' } |
|||
]; |
|||
|
|||
// when
|
|||
var parser = abi.outputParser(d); |
|||
|
|||
// then
|
|||
assert.equal(parser.test("0x" + |
|||
"0000000000000000000000000000000000000000000000000000000000000002" + |
|||
"0000000000000000000000000000000000000000000000000000000000000005" + |
|||
"0000000000000000000000000000000000000000000000000000000000000006")[0][0], |
|||
5 |
|||
); |
|||
assert.equal(parser.test("0x" + |
|||
"0000000000000000000000000000000000000000000000000000000000000002" + |
|||
"0000000000000000000000000000000000000000000000000000000000000005" + |
|||
"0000000000000000000000000000000000000000000000000000000000000006")[0][1], |
|||
6 |
|||
); |
|||
|
|||
}); |
|||
|
|||
}); |
|||
}); |
|||
|
|||
|
@ -1,2 +1,2 @@ |
|||
--reporter Spec |
|||
--reporter spec |
|||
|
|||
|
@ -0,0 +1,471 @@ |
|||
/*
|
|||
This file is part of cpp-ethereum. |
|||
|
|||
cpp-ethereum is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
cpp-ethereum is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/**
|
|||
* @author Lefteris <lefteris@ethdev.com> |
|||
* @date 2015 |
|||
* Converts the AST into json format |
|||
*/ |
|||
|
|||
#include <libsolidity/ASTJsonConverter.h> |
|||
#include <libsolidity/AST.h> |
|||
|
|||
using namespace std; |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace solidity |
|||
{ |
|||
|
|||
void ASTJsonConverter::addKeyValue(Json::Value& _obj, string const& _key, string const& _val) |
|||
{ |
|||
// special handling for booleans
|
|||
if (_key == "const" || _key == "public" || _key == "local" || |
|||
_key == "lvalue" || _key == "local_lvalue" || _key == "prefix") |
|||
_obj[_key] = (_val == "1") ? true : false; |
|||
else |
|||
// else simply add it as a string
|
|||
_obj[_key] = _val; |
|||
} |
|||
|
|||
void ASTJsonConverter::addJsonNode(string const& _nodeName, |
|||
initializer_list<pair<string const, string const>> _list, |
|||
bool _hasChildren = false) |
|||
{ |
|||
Json::Value node; |
|||
|
|||
node["name"] = _nodeName; |
|||
if (_list.size() != 0) |
|||
{ |
|||
Json::Value attrs; |
|||
for (auto& e: _list) |
|||
addKeyValue(attrs, e.first, e.second); |
|||
node["attributes"] = attrs; |
|||
} |
|||
|
|||
m_jsonNodePtrs.top()->append(node); |
|||
|
|||
if (_hasChildren) |
|||
{ |
|||
Json::Value& addedNode = (*m_jsonNodePtrs.top())[m_jsonNodePtrs.top()->size() - 1]; |
|||
Json::Value children(Json::arrayValue); |
|||
addedNode["children"] = children; |
|||
m_jsonNodePtrs.push(&addedNode["children"]); |
|||
} |
|||
} |
|||
|
|||
ASTJsonConverter::ASTJsonConverter(ASTNode const& _ast): m_ast(&_ast) |
|||
{ |
|||
Json::Value children(Json::arrayValue); |
|||
|
|||
m_astJson["name"] = "root"; |
|||
m_astJson["children"] = children; |
|||
m_jsonNodePtrs.push(&m_astJson["children"]); |
|||
} |
|||
|
|||
void ASTJsonConverter::print(ostream& _stream) |
|||
{ |
|||
m_ast->accept(*this); |
|||
_stream << m_astJson; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(ImportDirective const& _node) |
|||
{ |
|||
addJsonNode("Import", { make_pair("file", _node.getIdentifier())}); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(ContractDefinition const& _node) |
|||
{ |
|||
addJsonNode("Contract", { make_pair("name", _node.getName()) }, true); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(StructDefinition const& _node) |
|||
{ |
|||
addJsonNode("Struct", { make_pair("name", _node.getName()) }, true); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(ParameterList const&) |
|||
{ |
|||
addJsonNode("ParameterList", {}, true); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(FunctionDefinition const& _node) |
|||
{ |
|||
addJsonNode("Function", |
|||
{ make_pair("name", _node.getName()), |
|||
make_pair("public", boost::lexical_cast<std::string>(_node.isPublic())), |
|||
make_pair("const", boost::lexical_cast<std::string>(_node.isDeclaredConst())) }, |
|||
true); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(VariableDeclaration const& _node) |
|||
{ |
|||
addJsonNode("VariableDeclaration", |
|||
{ make_pair("name", _node.getName()), |
|||
make_pair("local", boost::lexical_cast<std::string>(_node.isLocalVariable()))}, |
|||
true); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(TypeName const&) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(ElementaryTypeName const& _node) |
|||
{ |
|||
addJsonNode("ElementaryTypeName", { make_pair("name", Token::toString(_node.getTypeName())) }); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(UserDefinedTypeName const& _node) |
|||
{ |
|||
addJsonNode("UserDefinedTypeName", { make_pair("name", _node.getName()) }); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(Mapping const&) |
|||
{ |
|||
addJsonNode("Mapping", {}, true); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(Statement const&) |
|||
{ |
|||
addJsonNode("Statement", {}, true); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(Block const&) |
|||
{ |
|||
addJsonNode("Block", {}, true); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(IfStatement const&) |
|||
{ |
|||
addJsonNode("IfStatement", {}, true); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(BreakableStatement const&) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(WhileStatement const&) |
|||
{ |
|||
addJsonNode("WhileStatement", {}, true); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(ForStatement const&) |
|||
{ |
|||
addJsonNode("ForStatement", {}, true); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(Continue const&) |
|||
{ |
|||
addJsonNode("Continue", {}); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(Break const&) |
|||
{ |
|||
addJsonNode("Break", {}); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(Return const&) |
|||
{ |
|||
addJsonNode("Return", {}, true);; |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(VariableDefinition const&) |
|||
{ |
|||
addJsonNode("VariableDefinition", {}, true); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(ExpressionStatement const&) |
|||
{ |
|||
addJsonNode("ExpressionStatement", {}, true); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(Expression const& _node) |
|||
{ |
|||
addJsonNode("Expression", |
|||
{ make_pair("type", getType(_node)), |
|||
make_pair("lvalue", boost::lexical_cast<std::string>(_node.isLValue())), |
|||
make_pair("local_lvalue", boost::lexical_cast<std::string>(_node.isLocalLValue())) }, |
|||
true); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(Assignment const& _node) |
|||
{ |
|||
addJsonNode("Assignment", |
|||
{ make_pair("operator", Token::toString(_node.getAssignmentOperator())), |
|||
make_pair("type", getType(_node)) }, |
|||
true); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(UnaryOperation const& _node) |
|||
{ |
|||
addJsonNode("UnaryOperation", |
|||
{ make_pair("prefix", boost::lexical_cast<std::string>(_node.isPrefixOperation())), |
|||
make_pair("operator", Token::toString(_node.getOperator())), |
|||
make_pair("type", getType(_node)) }, |
|||
true); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(BinaryOperation const& _node) |
|||
{ |
|||
addJsonNode("BinaryOperation", |
|||
{ make_pair("operator", Token::toString(_node.getOperator())), |
|||
make_pair("type", getType(_node))}, |
|||
true); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(FunctionCall const& _node) |
|||
{ |
|||
addJsonNode("FunctionCall", |
|||
{ make_pair("type_conversion", boost::lexical_cast<std::string>(_node.isTypeConversion())), |
|||
make_pair("type", getType(_node)) }, |
|||
true); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(NewExpression const& _node) |
|||
{ |
|||
addJsonNode("NewExpression", { make_pair("type", getType(_node)) }, true); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(MemberAccess const& _node) |
|||
{ |
|||
addJsonNode("MemberAccess", |
|||
{ make_pair("member_name", _node.getMemberName()), |
|||
make_pair("type", getType(_node)) }, |
|||
true); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(IndexAccess const& _node) |
|||
{ |
|||
addJsonNode("IndexAccess", { make_pair("type", getType(_node)) }, true); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(PrimaryExpression const&) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(Identifier const& _node) |
|||
{ |
|||
addJsonNode("Identifier", |
|||
{ make_pair("value", _node.getName()), make_pair("type", getType(_node)) }); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(ElementaryTypeNameExpression const& _node) |
|||
{ |
|||
addJsonNode("ElementaryTypenameExpression", |
|||
{ make_pair("value", Token::toString(_node.getTypeToken())), make_pair("type", getType(_node)) }); |
|||
return true; |
|||
} |
|||
|
|||
bool ASTJsonConverter::visit(Literal const& _node) |
|||
{ |
|||
char const* tokenString = Token::toString(_node.getToken()); |
|||
addJsonNode("Literal", |
|||
{ make_pair("string", (tokenString) ? tokenString : "null"), |
|||
make_pair("value", _node.getValue()), |
|||
make_pair("type", getType(_node)) }); |
|||
return true; |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(ImportDirective const&) |
|||
{ |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(ContractDefinition const&) |
|||
{ |
|||
goUp(); |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(StructDefinition const&) |
|||
{ |
|||
goUp(); |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(ParameterList const&) |
|||
{ |
|||
goUp(); |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(FunctionDefinition const&) |
|||
{ |
|||
goUp(); |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(VariableDeclaration const&) |
|||
{ |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(TypeName const&) |
|||
{ |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(ElementaryTypeName const&) |
|||
{ |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(UserDefinedTypeName const&) |
|||
{ |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(Mapping const&) |
|||
{ |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(Statement const&) |
|||
{ |
|||
goUp(); |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(Block const&) |
|||
{ |
|||
goUp(); |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(IfStatement const&) |
|||
{ |
|||
goUp(); |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(BreakableStatement const&) |
|||
{ |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(WhileStatement const&) |
|||
{ |
|||
goUp(); |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(ForStatement const&) |
|||
{ |
|||
goUp(); |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(Continue const&) |
|||
{ |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(Break const&) |
|||
{ |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(Return const&) |
|||
{ |
|||
goUp(); |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(VariableDefinition const&) |
|||
{ |
|||
goUp(); |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(ExpressionStatement const&) |
|||
{ |
|||
goUp(); |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(Expression const&) |
|||
{ |
|||
goUp(); |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(Assignment const&) |
|||
{ |
|||
goUp(); |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(UnaryOperation const&) |
|||
{ |
|||
goUp(); |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(BinaryOperation const&) |
|||
{ |
|||
goUp(); |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(FunctionCall const&) |
|||
{ |
|||
goUp(); |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(NewExpression const&) |
|||
{ |
|||
goUp(); |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(MemberAccess const&) |
|||
{ |
|||
goUp(); |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(IndexAccess const&) |
|||
{ |
|||
goUp(); |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(PrimaryExpression const&) |
|||
{ |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(Identifier const&) |
|||
{ |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(ElementaryTypeNameExpression const&) |
|||
{ |
|||
} |
|||
|
|||
void ASTJsonConverter::endVisit(Literal const&) |
|||
{ |
|||
} |
|||
|
|||
string ASTJsonConverter::getType(Expression const& _expression) |
|||
{ |
|||
return (_expression.getType()) ? _expression.getType()->toString() : "Unknown"; |
|||
} |
|||
|
|||
} |
|||
} |
@ -0,0 +1,135 @@ |
|||
/*
|
|||
This file is part of cpp-ethereum. |
|||
|
|||
cpp-ethereum is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
cpp-ethereum is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/**
|
|||
* @author Lefteris <lefteris@ethdev.com> |
|||
* @date 2015 |
|||
* Converts the AST into json format |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <ostream> |
|||
#include <stack> |
|||
#include <libsolidity/ASTVisitor.h> |
|||
#include <libsolidity/Exceptions.h> |
|||
#include <libsolidity/Utils.h> |
|||
#include <jsoncpp/json/json.h> |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace solidity |
|||
{ |
|||
|
|||
/**
|
|||
* Converter of the AST into JSON format |
|||
*/ |
|||
class ASTJsonConverter: public ASTConstVisitor |
|||
{ |
|||
public: |
|||
/// Create a converter to JSON for the given abstract syntax tree.
|
|||
ASTJsonConverter(ASTNode const& _ast); |
|||
/// Output the json representation of the AST to _stream.
|
|||
void print(std::ostream& _stream); |
|||
|
|||
bool visit(ImportDirective const& _node) override; |
|||
bool visit(ContractDefinition const& _node) override; |
|||
bool visit(StructDefinition const& _node) override; |
|||
bool visit(ParameterList const& _node) override; |
|||
bool visit(FunctionDefinition const& _node) override; |
|||
bool visit(VariableDeclaration const& _node) override; |
|||
bool visit(TypeName const& _node) override; |
|||
bool visit(ElementaryTypeName const& _node) override; |
|||
bool visit(UserDefinedTypeName const& _node) override; |
|||
bool visit(Mapping const& _node) override; |
|||
bool visit(Statement const& _node) override; |
|||
bool visit(Block const& _node) override; |
|||
bool visit(IfStatement const& _node) override; |
|||
bool visit(BreakableStatement const& _node) override; |
|||
bool visit(WhileStatement const& _node) override; |
|||
bool visit(ForStatement const& _node) override; |
|||
bool visit(Continue const& _node) override; |
|||
bool visit(Break const& _node) override; |
|||
bool visit(Return const& _node) override; |
|||
bool visit(VariableDefinition const& _node) override; |
|||
bool visit(ExpressionStatement const& _node) override; |
|||
bool visit(Expression const& _node) override; |
|||
bool visit(Assignment const& _node) override; |
|||
bool visit(UnaryOperation const& _node) override; |
|||
bool visit(BinaryOperation const& _node) override; |
|||
bool visit(FunctionCall const& _node) override; |
|||
bool visit(NewExpression const& _node) override; |
|||
bool visit(MemberAccess const& _node) override; |
|||
bool visit(IndexAccess const& _node) override; |
|||
bool visit(PrimaryExpression const& _node) override; |
|||
bool visit(Identifier const& _node) override; |
|||
bool visit(ElementaryTypeNameExpression const& _node) override; |
|||
bool visit(Literal const& _node) override; |
|||
|
|||
void endVisit(ImportDirective const&) override; |
|||
void endVisit(ContractDefinition const&) override; |
|||
void endVisit(StructDefinition const&) override; |
|||
void endVisit(ParameterList const&) override; |
|||
void endVisit(FunctionDefinition const&) override; |
|||
void endVisit(VariableDeclaration const&) override; |
|||
void endVisit(TypeName const&) override; |
|||
void endVisit(ElementaryTypeName const&) override; |
|||
void endVisit(UserDefinedTypeName const&) override; |
|||
void endVisit(Mapping const&) override; |
|||
void endVisit(Statement const&) override; |
|||
void endVisit(Block const&) override; |
|||
void endVisit(IfStatement const&) override; |
|||
void endVisit(BreakableStatement const&) override; |
|||
void endVisit(WhileStatement const&) override; |
|||
void endVisit(ForStatement const&) override; |
|||
void endVisit(Continue const&) override; |
|||
void endVisit(Break const&) override; |
|||
void endVisit(Return const&) override; |
|||
void endVisit(VariableDefinition const&) override; |
|||
void endVisit(ExpressionStatement const&) override; |
|||
void endVisit(Expression const&) override; |
|||
void endVisit(Assignment const&) override; |
|||
void endVisit(UnaryOperation const&) override; |
|||
void endVisit(BinaryOperation const&) override; |
|||
void endVisit(FunctionCall const&) override; |
|||
void endVisit(NewExpression const&) override; |
|||
void endVisit(MemberAccess const&) override; |
|||
void endVisit(IndexAccess const&) override; |
|||
void endVisit(PrimaryExpression const&) override; |
|||
void endVisit(Identifier const&) override; |
|||
void endVisit(ElementaryTypeNameExpression const&) override; |
|||
void endVisit(Literal const&) override; |
|||
|
|||
private: |
|||
void addKeyValue(Json::Value& _obj, std::string const& _key, std::string const& _val); |
|||
void addJsonNode(std::string const& _nodeName, |
|||
std::initializer_list<std::pair<std::string const, std::string const>> _list, |
|||
bool _hasChildren); |
|||
std::string getType(Expression const& _expression); |
|||
inline void goUp() |
|||
{ |
|||
solAssert(!m_jsonNodePtrs.empty(), "Uneven json nodes stack. Internal error."); |
|||
m_jsonNodePtrs.pop(); |
|||
}; |
|||
|
|||
Json::Value m_astJson; |
|||
std::stack<Json::Value*> m_jsonNodePtrs; |
|||
std::string m_source; |
|||
ASTNode const* m_ast; |
|||
}; |
|||
|
|||
} |
|||
} |
@ -0,0 +1,31 @@ |
|||
/*
|
|||
This file is part of cpp-ethereum. |
|||
|
|||
cpp-ethereum is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
cpp-ethereum is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file Exceptions.cpp
|
|||
* @author Arkadiy Paronyan arkadiy@ethdev.com |
|||
* @date 2015 |
|||
* Ethereum IDE client. |
|||
*/ |
|||
|
|||
#include <ostream> |
|||
#include <QQmlError> |
|||
#include "Exceptions.h" |
|||
|
|||
std::ostream& operator<<(std::ostream& _out, QQmlError const& _error) |
|||
{ |
|||
_out << _error.toString().toStdString(); |
|||
return _out; |
|||
} |
@ -0,0 +1,45 @@ |
|||
/*
|
|||
This file is part of cpp-ethereum. |
|||
|
|||
cpp-ethereum is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
cpp-ethereum is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file Exceptions.h
|
|||
* @author Arkadiy Paronyan arkadiy@ethdev.com |
|||
* @date 2015 |
|||
* Ethereum IDE client. |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <iosfwd> |
|||
#include <libdevcore/Exceptions.h> |
|||
|
|||
class QTextDocument; |
|||
class QQmlError; |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace mix |
|||
{ |
|||
|
|||
struct QmlLoadException: virtual Exception {}; |
|||
struct FileIoException: virtual Exception {}; |
|||
|
|||
typedef boost::error_info<struct tagQmlError, QQmlError> QmlErrorInfo; |
|||
typedef boost::error_info<struct tagFileError, std::string> FileError; |
|||
|
|||
} |
|||
} |
|||
|
|||
std::ostream& operator<<(std::ostream& _out, QQmlError const& _error); |
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue