2014-10-30 21:52:15 +00:00
/*
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 Christian < c @ ethdev . com >
2015-01-09 06:39:30 +00:00
* @ author Gav Wood < g @ ethdev . com >
2014-10-30 21:52:15 +00:00
* @ date 2014
* Full - stack compiler that converts a source code string to bytecode .
*/
2015-01-21 19:31:14 +00:00
# include <boost/algorithm/string.hpp>
2014-10-30 21:52:15 +00:00
# include <libsolidity/AST.h>
# include <libsolidity/Scanner.h>
# include <libsolidity/Parser.h>
2014-11-20 17:33:23 +00:00
# include <libsolidity/GlobalContext.h>
2014-10-30 21:52:15 +00:00
# include <libsolidity/NameAndTypeResolver.h>
2015-09-16 14:56:30 +00:00
# include <libsolidity/TypeChecker.h>
2014-10-30 21:52:15 +00:00
# include <libsolidity/Compiler.h>
# include <libsolidity/CompilerStack.h>
2014-12-03 15:40:37 +00:00
# include <libsolidity/InterfaceHandler.h>
2014-10-30 21:52:15 +00:00
2015-05-19 17:51:38 +00:00
# include <libdevcore/SHA3.h>
2015-01-13 14:59:42 +00:00
2014-10-30 21:52:15 +00:00
using namespace std ;
namespace dev
{
namespace solidity
{
2015-01-28 12:39:04 +00:00
const map < string , string > StandardSources = map < string , string > {
2015-03-09 16:48:33 +00:00
{ " coin " , R " (import " CoinReg " ;import " Config " ;import " configUser " ;contract coin is configUser{function coin(bytes3 name, uint denom) {CoinReg(Config(configAddr()).lookup(3)).register(name, denom);}}) " } ,
2015-01-28 12:39:04 +00:00
{ " Coin " , R " (contract Coin{function isApprovedFor(address _target,address _proxy)constant returns(bool _r){}function isApproved(address _proxy)constant returns(bool _r){}function sendCoinFrom(address _from,uint256 _val,address _to){}function coinBalanceOf(address _a)constant returns(uint256 _r){}function sendCoin(uint256 _val,address _to){}function coinBalance()constant returns(uint256 _r){}function approve(address _a){}}) " } ,
2015-03-09 16:48:33 +00:00
{ " CoinReg " , R " (contract CoinReg{function count()constant returns(uint256 r){}function info(uint256 i)constant returns(address addr,bytes3 name,uint256 denom){}function register(bytes3 name,uint256 denom){}function unregister(){}}) " } ,
2015-01-28 12:39:04 +00:00
{ " configUser " , R " (contract configUser{function configAddr()constant returns(address a){ return 0xc6d9d2cd449a754c494264e1809c50e34d64562b;}}) " } ,
{ " Config " , R " (contract Config{function lookup(uint256 service)constant returns(address a){}function kill(){}function unregister(uint256 id){}function register(uint256 id,address service){}}) " } ,
{ " mortal " , R " (import " owned " ;contract mortal is owned {function kill() { if (msg.sender == owner) suicide(owner); }}) " } ,
2015-03-09 16:48:33 +00:00
{ " named " , R " (import " Config " ;import " NameReg " ;import " configUser " ;contract named is configUser {function named(bytes32 name) {NameReg(Config(configAddr()).lookup(1)).register(name);}}) " } ,
{ " NameReg " , R " (contract NameReg{function register(bytes32 name){}function addressOf(bytes32 name)constant returns(address addr){}function unregister(){}function nameOf(address addr)constant returns(bytes32 name){}}) " } ,
2015-01-28 12:39:04 +00:00
{ " owned " , R " (contract owned{function owned(){owner = msg.sender;}modifier onlyowner(){if(msg.sender==owner)_}address owner;}) " } ,
{ " service " , R " (import " Config " ;import " configUser " ;contract service is configUser{function service(uint _n){Config(configAddr()).register(_n, this);}}) " } ,
2015-01-30 12:57:23 +00:00
{ " std " , R " (import " owned " ;import " mortal " ;import " Config " ;import " configUser " ;import " NameReg " ;import " named " ;) " }
2015-01-28 12:39:04 +00:00
} ;
CompilerStack : : CompilerStack ( bool _addStandardSources ) :
2015-05-19 22:27:07 +00:00
m_parseSuccessful ( false )
2015-01-28 12:39:04 +00:00
{
2015-05-19 22:27:07 +00:00
if ( _addStandardSources )
2015-02-20 17:15:34 +00:00
addSources ( StandardSources , true ) ; // add them as libraries
2015-01-28 12:39:04 +00:00
}
2015-05-19 22:27:07 +00:00
void CompilerStack : : reset ( bool _keepSources , bool _addStandardSources )
{
m_parseSuccessful = false ;
if ( _keepSources )
for ( auto sourcePair : m_sources )
sourcePair . second . reset ( ) ;
else
{
m_sources . clear ( ) ;
if ( _addStandardSources )
addSources ( StandardSources , true ) ;
}
m_globalContext . reset ( ) ;
m_sourceOrder . clear ( ) ;
m_contracts . clear ( ) ;
2015-09-21 17:43:56 +00:00
m_errors . clear ( ) ;
2015-05-19 22:27:07 +00:00
}
2015-02-20 17:15:34 +00:00
bool CompilerStack : : addSource ( string const & _name , string const & _content , bool _isLibrary )
2014-12-03 16:45:12 +00:00
{
2015-01-13 10:18:08 +00:00
bool existed = m_sources . count ( _name ) ! = 0 ;
2014-12-03 16:45:12 +00:00
reset ( true ) ;
2015-02-21 15:25:28 +00:00
m_sources [ _name ] . scanner = make_shared < Scanner > ( CharStream ( _content ) , _name ) ;
2015-02-20 17:15:34 +00:00
m_sources [ _name ] . isLibrary = _isLibrary ;
2014-12-18 13:39:16 +00:00
return existed ;
2014-12-03 16:45:12 +00:00
}
2014-11-11 16:41:48 +00:00
void CompilerStack : : setSource ( string const & _sourceCode )
2014-10-30 21:52:15 +00:00
{
2014-11-11 16:41:48 +00:00
reset ( ) ;
2015-02-21 15:25:28 +00:00
addSource ( " " , _sourceCode ) ;
2014-11-11 16:41:48 +00:00
}
2015-09-21 17:43:56 +00:00
bool CompilerStack : : parse ( )
2014-11-11 16:41:48 +00:00
{
2015-09-21 17:43:56 +00:00
m_errors . clear ( ) ;
2014-12-03 16:45:12 +00:00
for ( auto & sourcePair : m_sources )
{
sourcePair . second . scanner - > reset ( ) ;
sourcePair . second . ast = Parser ( ) . parse ( sourcePair . second . scanner ) ;
}
resolveImports ( ) ;
2014-11-20 17:33:23 +00:00
m_globalContext = make_shared < GlobalContext > ( ) ;
2015-08-31 16:44:29 +00:00
NameAndTypeResolver resolver ( m_globalContext - > declarations ( ) ) ;
2014-12-03 16:45:12 +00:00
for ( Source const * source : m_sourceOrder )
resolver . registerDeclarations ( * source - > ast ) ;
for ( Source const * source : m_sourceOrder )
2015-08-31 16:44:29 +00:00
for ( ASTPointer < ASTNode > const & node : source - > ast - > nodes ( ) )
2014-12-03 16:45:12 +00:00
if ( ContractDefinition * contract = dynamic_cast < ContractDefinition * > ( node . get ( ) ) )
{
m_globalContext - > setCurrentContract ( * contract ) ;
2015-08-31 16:44:29 +00:00
resolver . updateDeclaration ( * m_globalContext - > currentThis ( ) ) ;
resolver . updateDeclaration ( * m_globalContext - > currentSuper ( ) ) ;
2014-12-03 16:45:12 +00:00
resolver . resolveNamesAndTypes ( * contract ) ;
2015-08-31 16:44:29 +00:00
m_contracts [ contract - > name ( ) ] . contract = contract ;
2014-12-03 16:45:12 +00:00
}
2015-09-21 17:43:56 +00:00
2015-07-15 14:23:10 +00:00
InterfaceHandler interfaceHandler ;
2014-12-16 22:45:24 +00:00
for ( Source const * source : m_sourceOrder )
2015-08-31 16:44:29 +00:00
for ( ASTPointer < ASTNode > const & node : source - > ast - > nodes ( ) )
2014-12-16 22:45:24 +00:00
if ( ContractDefinition * contract = dynamic_cast < ContractDefinition * > ( node . get ( ) ) )
{
m_globalContext - > setCurrentContract ( * contract ) ;
2015-08-31 16:44:29 +00:00
resolver . updateDeclaration ( * m_globalContext - > currentThis ( ) ) ;
2015-09-16 14:56:30 +00:00
TypeChecker typeChecker ;
bool typesFine = typeChecker . checkTypeRequirements ( * contract ) ;
if ( ! typesFine )
2015-09-21 17:43:56 +00:00
m_errors + = typeChecker . errors ( ) ;
2015-07-15 14:23:10 +00:00
contract - > setDevDocumentation ( interfaceHandler . devDocumentation ( * contract ) ) ;
contract - > setUserDocumentation ( interfaceHandler . userDocumentation ( * contract ) ) ;
2015-08-31 16:44:29 +00:00
m_contracts [ contract - > name ( ) ] . contract = contract ;
2014-12-16 22:45:24 +00:00
}
2015-09-21 17:43:56 +00:00
m_parseSuccessful = m_errors . empty ( ) ;
return m_parseSuccessful ;
2014-11-11 16:41:48 +00:00
}
2015-09-21 17:43:56 +00:00
bool CompilerStack : : parse ( string const & _sourceCode )
2014-11-11 16:41:48 +00:00
{
setSource ( _sourceCode ) ;
2015-09-21 17:43:56 +00:00
return parse ( ) ;
2014-11-11 16:41:48 +00:00
}
2015-08-31 16:44:29 +00:00
vector < string > CompilerStack : : contractNames ( ) const
2014-11-11 16:41:48 +00:00
{
if ( ! m_parseSuccessful )
BOOST_THROW_EXCEPTION ( CompilerError ( ) < < errinfo_comment ( " Parsing was not successful. " ) ) ;
2014-12-03 17:52:28 +00:00
vector < string > contractNames ;
for ( auto const & contract : m_contracts )
contractNames . push_back ( contract . first ) ;
return contractNames ;
}
2015-01-29 01:34:57 +00:00
2015-09-21 17:43:56 +00:00
bool CompilerStack : : compile ( bool _optimize , unsigned _runs )
2014-12-03 17:52:28 +00:00
{
if ( ! m_parseSuccessful )
2015-09-21 17:43:56 +00:00
if ( ! parse ( ) )
return false ;
2015-09-16 14:56:30 +00:00
2015-09-10 10:01:05 +00:00
map < ContractDefinition const * , eth : : Assembly const * > compiledContracts ;
2014-12-03 16:45:12 +00:00
for ( Source const * source : m_sourceOrder )
2015-08-31 16:44:29 +00:00
for ( ASTPointer < ASTNode > const & node : source - > ast - > nodes ( ) )
2014-12-03 16:45:12 +00:00
if ( ContractDefinition * contract = dynamic_cast < ContractDefinition * > ( node . get ( ) ) )
{
2015-09-16 14:56:30 +00:00
if ( ! contract - > annotation ( ) . isFullyImplemented )
2015-03-27 14:15:34 +00:00
continue ;
2015-06-01 10:32:59 +00:00
shared_ptr < Compiler > compiler = make_shared < Compiler > ( _optimize , _runs ) ;
2015-09-10 10:01:05 +00:00
compiler - > compileContract ( * contract , compiledContracts ) ;
2015-08-31 16:44:29 +00:00
Contract & compiledContract = m_contracts . at ( contract - > name ( ) ) ;
2015-09-10 10:01:05 +00:00
compiledContract . compiler = compiler ;
compiledContract . object = compiler - > assembledObject ( ) ;
compiledContract . runtimeObject = compiler - > runtimeObject ( ) ;
compiledContracts [ compiledContract . contract ] = & compiler - > assembly ( ) ;
2015-07-31 17:23:31 +00:00
Compiler cloneCompiler ( _optimize , _runs ) ;
2015-09-10 10:01:05 +00:00
cloneCompiler . compileClone ( * contract , compiledContracts ) ;
compiledContract . cloneObject = cloneCompiler . assembledObject ( ) ;
2014-12-03 16:45:12 +00:00
}
2015-09-21 17:43:56 +00:00
return true ;
2014-11-11 16:41:48 +00:00
}
2014-10-30 21:52:15 +00:00
2015-09-21 17:43:56 +00:00
bool CompilerStack : : compile ( string const & _sourceCode , bool _optimize )
2014-11-11 16:41:48 +00:00
{
2015-09-21 17:43:56 +00:00
return parse ( _sourceCode ) & & compile ( _optimize ) ;
2014-10-30 21:52:15 +00:00
}
2015-09-11 17:35:01 +00:00
void CompilerStack : : link ( const std : : map < string , h160 > & _libraries )
{
for ( auto & contract : m_contracts )
{
contract . second . object . link ( _libraries ) ;
contract . second . runtimeObject . link ( _libraries ) ;
contract . second . cloneObject . link ( _libraries ) ;
}
}
2015-08-31 16:44:29 +00:00
eth : : AssemblyItems const * CompilerStack : : assemblyItems ( string const & _contractName ) const
2015-03-02 00:13:10 +00:00
{
2015-08-31 16:44:29 +00:00
Contract const & currentContract = contract ( _contractName ) ;
return currentContract . compiler ? & contract ( _contractName ) . compiler - > assemblyItems ( ) : nullptr ;
2015-03-02 00:13:10 +00:00
}
2015-08-31 16:44:29 +00:00
eth : : AssemblyItems const * CompilerStack : : runtimeAssemblyItems ( string const & _contractName ) const
2015-03-02 00:13:10 +00:00
{
2015-08-31 16:44:29 +00:00
Contract const & currentContract = contract ( _contractName ) ;
return currentContract . compiler ? & contract ( _contractName ) . compiler - > runtimeAssemblyItems ( ) : nullptr ;
2015-03-02 00:13:10 +00:00
}
2015-09-10 10:01:05 +00:00
eth : : LinkerObject const & CompilerStack : : object ( string const & _contractName ) const
2014-11-11 16:41:48 +00:00
{
2015-09-10 10:01:05 +00:00
return contract ( _contractName ) . object ;
2014-11-11 16:41:48 +00:00
}
2015-09-10 10:01:05 +00:00
eth : : LinkerObject const & CompilerStack : : runtimeObject ( string const & _contractName ) const
2015-01-13 14:59:42 +00:00
{
2015-09-10 10:01:05 +00:00
return contract ( _contractName ) . runtimeObject ;
2015-01-13 14:59:42 +00:00
}
2015-09-10 10:01:05 +00:00
eth : : LinkerObject const & CompilerStack : : cloneObject ( string const & _contractName ) const
2015-07-31 17:23:31 +00:00
{
2015-09-10 10:01:05 +00:00
return contract ( _contractName ) . cloneObject ;
2015-07-31 17:23:31 +00:00
}
2015-08-31 16:44:29 +00:00
dev : : h256 CompilerStack : : contractCodeHash ( string const & _contractName ) const
2015-01-13 14:59:42 +00:00
{
2015-09-10 10:01:05 +00:00
auto const & obj = runtimeObject ( _contractName ) ;
if ( obj . bytecode . empty ( ) | | ! obj . linkReferences . empty ( ) )
return dev : : h256 ( ) ;
else
return dev : : sha3 ( obj . bytecode ) ;
2015-01-13 14:59:42 +00:00
}
2015-01-28 07:50:53 +00:00
Json : : Value CompilerStack : : streamAssembly ( ostream & _outStream , string const & _contractName , StringMap _sourceCodes , bool _inJsonFormat ) const
2014-11-11 16:41:48 +00:00
{
2015-08-31 16:44:29 +00:00
Contract const & currentContract = contract ( _contractName ) ;
if ( currentContract . compiler )
return currentContract . compiler - > streamAssembly ( _outStream , _sourceCodes , _inJsonFormat ) ;
2015-04-02 13:10:35 +00:00
else
2015-01-28 07:50:53 +00:00
{
2015-04-02 13:10:35 +00:00
_outStream < < " Contract not fully implemented " < < endl ;
2015-01-28 07:50:53 +00:00
return Json : : Value ( ) ;
}
2014-12-03 16:45:12 +00:00
}
2015-08-31 16:44:29 +00:00
string const & CompilerStack : : interface ( string const & _contractName ) const
2014-12-03 16:45:12 +00:00
{
2015-08-31 16:44:29 +00:00
return metadata ( _contractName , DocumentationType : : ABIInterface ) ;
2014-12-05 14:27:07 +00:00
}
2015-08-31 16:44:29 +00:00
string const & CompilerStack : : solidityInterface ( string const & _contractName ) const
2015-01-08 23:22:06 +00:00
{
2015-08-31 16:44:29 +00:00
return metadata ( _contractName , DocumentationType : : ABISolidityInterface ) ;
2015-01-08 23:22:06 +00:00
}
2015-08-31 16:44:29 +00:00
string const & CompilerStack : : metadata ( string const & _contractName , DocumentationType _type ) const
2014-12-01 16:03:04 +00:00
{
if ( ! m_parseSuccessful )
BOOST_THROW_EXCEPTION ( CompilerError ( ) < < errinfo_comment ( " Parsing was not successful. " ) ) ;
2014-12-01 17:01:42 +00:00
2015-08-31 16:44:29 +00:00
Contract const & currentContract = contract ( _contractName ) ;
2014-12-03 12:50:04 +00:00
2014-12-06 01:39:58 +00:00
std : : unique_ptr < string const > * doc ;
2015-07-15 14:23:10 +00:00
// checks wheather we already have the documentation
2014-12-03 15:40:37 +00:00
switch ( _type )
2014-11-11 16:41:48 +00:00
{
2015-02-09 13:12:36 +00:00
case DocumentationType : : NatspecUser :
2015-08-31 16:44:29 +00:00
doc = & currentContract . userDocumentation ;
2014-12-05 14:27:07 +00:00
break ;
2015-02-09 13:12:36 +00:00
case DocumentationType : : NatspecDev :
2015-08-31 16:44:29 +00:00
doc = & currentContract . devDocumentation ;
2014-12-05 14:27:07 +00:00
break ;
2015-02-09 13:12:36 +00:00
case DocumentationType : : ABIInterface :
2015-08-31 16:44:29 +00:00
doc = & currentContract . interface ;
2014-12-05 14:27:07 +00:00
break ;
2015-02-09 13:12:36 +00:00
case DocumentationType : : ABISolidityInterface :
2015-08-31 16:44:29 +00:00
doc = & currentContract . solidityInterface ;
2015-01-08 23:22:06 +00:00
break ;
2014-12-05 14:27:07 +00:00
default :
BOOST_THROW_EXCEPTION ( InternalCompilerError ( ) < < errinfo_comment ( " Illegal documentation type. " ) ) ;
2014-11-11 16:41:48 +00:00
}
2015-06-19 13:40:09 +00:00
2015-07-15 14:23:10 +00:00
// caches the result
2014-12-05 14:27:07 +00:00
if ( ! * doc )
2015-08-31 16:44:29 +00:00
doc - > reset ( new string ( currentContract . interfaceHandler - > documentation ( * currentContract . contract , _type ) ) ) ;
2015-06-19 13:40:09 +00:00
2014-12-05 14:27:07 +00:00
return * ( * doc ) ;
2014-12-03 16:45:12 +00:00
}
2015-08-31 16:44:29 +00:00
Scanner const & CompilerStack : : scanner ( string const & _sourceName ) const
2014-12-03 16:45:12 +00:00
{
2015-08-31 16:44:29 +00:00
return * source ( _sourceName ) . scanner ;
2014-12-03 16:45:12 +00:00
}
2015-09-08 12:30:21 +00:00
SourceUnit const & CompilerStack : : ast ( string const & _sourceName ) const
2014-12-03 16:45:12 +00:00
{
2015-08-31 16:44:29 +00:00
return * source ( _sourceName ) . ast ;
2014-11-11 16:41:48 +00:00
}
2015-08-31 16:44:29 +00:00
ContractDefinition const & CompilerStack : : contractDefinition ( string const & _contractName ) const
2014-12-18 13:39:16 +00:00
{
2015-08-31 16:44:29 +00:00
return * contract ( _contractName ) . contract ;
2014-12-18 13:39:16 +00:00
}
2015-08-31 16:44:29 +00:00
size_t CompilerStack : : functionEntryPoint (
2015-05-26 09:27:59 +00:00
std : : string const & _contractName ,
FunctionDefinition const & _function
) const
{
2015-08-31 16:44:29 +00:00
shared_ptr < Compiler > const & compiler = contract ( _contractName ) . compiler ;
2015-05-26 09:27:59 +00:00
if ( ! compiler )
return 0 ;
2015-08-31 16:44:29 +00:00
eth : : AssemblyItem tag = compiler - > functionEntryLabel ( _function ) ;
2015-05-26 09:27:59 +00:00
if ( tag . type ( ) = = eth : : UndefinedItem )
return 0 ;
2015-08-31 16:44:29 +00:00
eth : : AssemblyItems const & items = compiler - > runtimeAssemblyItems ( ) ;
2015-05-26 09:27:59 +00:00
for ( size_t i = 0 ; i < items . size ( ) ; + + i )
if ( items . at ( i ) . type ( ) = = eth : : Tag & & items . at ( i ) . data ( ) = = tag . data ( ) )
return i ;
return 0 ;
}
2015-05-07 15:22:24 +00:00
tuple < int , int , int , int > CompilerStack : : positionFromSourceLocation ( SourceLocation const & _sourceLocation ) const
2015-05-07 11:32:26 +00:00
{
2015-05-07 15:22:24 +00:00
int startLine ;
int startColumn ;
int endLine ;
int endColumn ;
2015-08-31 16:44:29 +00:00
tie ( startLine , startColumn ) = scanner ( * _sourceLocation . sourceName ) . translatePositionToLineColumn ( _sourceLocation . start ) ;
tie ( endLine , endColumn ) = scanner ( * _sourceLocation . sourceName ) . translatePositionToLineColumn ( _sourceLocation . end ) ;
2015-05-07 15:22:24 +00:00
return make_tuple ( + + startLine , + + startColumn , + + endLine , + + endColumn ) ;
2015-05-07 11:32:26 +00:00
}
2014-12-03 16:45:12 +00:00
void CompilerStack : : resolveImports ( )
{
// topological sorting (depth first search) of the import graph, cutting potential cycles
vector < Source const * > sourceOrder ;
set < Source const * > sourcesSeen ;
function < void ( Source const * ) > toposort = [ & ] ( Source const * _source )
{
if ( sourcesSeen . count ( _source ) )
return ;
sourcesSeen . insert ( _source ) ;
2015-08-31 16:44:29 +00:00
for ( ASTPointer < ASTNode > const & node : _source - > ast - > nodes ( ) )
2014-12-03 16:45:12 +00:00
if ( ImportDirective const * import = dynamic_cast < ImportDirective * > ( node . get ( ) ) )
{
2015-08-31 16:44:29 +00:00
string const & id = import - > identifier ( ) ;
2014-12-05 14:35:05 +00:00
if ( ! m_sources . count ( id ) )
2015-09-01 09:19:02 +00:00
BOOST_THROW_EXCEPTION (
ParserError ( )
< < errinfo_sourceLocation ( import - > location ( ) )
< < errinfo_comment ( " Source not found. " )
) ;
2014-12-05 14:35:05 +00:00
toposort ( & m_sources [ id ] ) ;
2014-12-03 16:45:12 +00:00
}
sourceOrder . push_back ( _source ) ;
} ;
for ( auto const & sourcePair : m_sources )
2015-02-20 17:15:34 +00:00
if ( ! sourcePair . second . isLibrary )
toposort ( & sourcePair . second ) ;
2014-11-11 16:41:48 +00:00
2014-12-03 16:45:12 +00:00
swap ( m_sourceOrder , sourceOrder ) ;
}
2014-11-11 16:41:48 +00:00
2015-02-15 00:00:09 +00:00
std : : string CompilerStack : : defaultContractName ( ) const
{
2015-08-31 16:44:29 +00:00
return contract ( " " ) . contract - > name ( ) ;
2015-02-15 00:00:09 +00:00
}
2015-08-31 16:44:29 +00:00
CompilerStack : : Contract const & CompilerStack : : contract ( string const & _contractName ) const
2014-12-03 16:45:12 +00:00
{
if ( m_contracts . empty ( ) )
BOOST_THROW_EXCEPTION ( CompilerError ( ) < < errinfo_comment ( " No compiled contracts found. " ) ) ;
2014-12-17 17:33:55 +00:00
string contractName = _contractName ;
2014-12-03 16:45:12 +00:00
if ( _contractName . empty ( ) )
2015-01-28 13:16:15 +00:00
// try to find some user-supplied contract
for ( auto const & it : m_sources )
if ( ! StandardSources . count ( it . first ) )
2015-08-31 16:44:29 +00:00
for ( ASTPointer < ASTNode > const & node : it . second . ast - > nodes ( ) )
2015-01-28 13:16:15 +00:00
if ( auto contract = dynamic_cast < ContractDefinition const * > ( node . get ( ) ) )
2015-08-31 16:44:29 +00:00
contractName = contract - > name ( ) ;
2014-12-17 17:33:55 +00:00
auto it = m_contracts . find ( contractName ) ;
2014-12-03 16:45:12 +00:00
if ( it = = m_contracts . end ( ) )
BOOST_THROW_EXCEPTION ( CompilerError ( ) < < errinfo_comment ( " Contract " + _contractName + " not found. " ) ) ;
return it - > second ;
}
2015-08-31 16:44:29 +00:00
CompilerStack : : Source const & CompilerStack : : source ( string const & _sourceName ) const
2014-12-03 16:45:12 +00:00
{
auto it = m_sources . find ( _sourceName ) ;
if ( it = = m_sources . end ( ) )
BOOST_THROW_EXCEPTION ( CompilerError ( ) < < errinfo_comment ( " Given source file not found. " ) ) ;
return it - > second ;
}
2014-11-11 16:41:48 +00:00
2014-12-05 14:27:07 +00:00
CompilerStack : : Contract : : Contract ( ) : interfaceHandler ( make_shared < InterfaceHandler > ( ) ) { }
2014-11-11 16:41:48 +00:00
2014-10-30 21:52:15 +00:00
}
}