Basic logging in Solidity (though no tests yet).

This commit is contained in:
Gav Wood 2015-01-09 00:22:06 +01:00
parent d18fa27b6a
commit ffce12b7ee
7 changed files with 134 additions and 19 deletions

View File

@ -143,6 +143,11 @@ string const& CompilerStack::getInterface(string const& _contractName) const
return getJsonDocumentation(_contractName, DocumentationType::ABI_INTERFACE);
}
string const& CompilerStack::getSolidityInterface(string const& _contractName) const
{
return getJsonDocumentation(_contractName, DocumentationType::ABI_SOLIDITY_INTERFACE);
}
string const& CompilerStack::getJsonDocumentation(string const& _contractName, DocumentationType _type) const
{
if (!m_parseSuccessful)
@ -162,6 +167,9 @@ string const& CompilerStack::getJsonDocumentation(string const& _contractName, D
case DocumentationType::ABI_INTERFACE:
doc = &contract.interface;
break;
case DocumentationType::ABI_SOLIDITY_INTERFACE:
doc = &contract.solidityInterface;
break;
default:
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Illegal documentation type."));
}

View File

@ -43,7 +43,8 @@ enum class DocumentationType: uint8_t
{
NATSPEC_USER = 1,
NATSPEC_DEV,
ABI_INTERFACE
ABI_INTERFACE,
ABI_SOLIDITY_INTERFACE
};
/**
@ -81,6 +82,9 @@ public:
/// Returns a string representing the contract interface in JSON.
/// Prerequisite: Successful call to parse or compile.
std::string const& getInterface(std::string const& _contractName = "") const;
/// Returns a string representing the contract interface in JSON.
/// Prerequisite: Successful call to parse or compile.
std::string const& getSolidityInterface(std::string const& _contractName = "") const;
/// Returns a string representing the contract's documentation in JSON.
/// Prerequisite: Successful call to parse or compile.
/// @param type The type of the documentation to get.
@ -118,6 +122,7 @@ private:
bytes bytecode;
std::shared_ptr<InterfaceHandler> interfaceHandler;
mutable std::unique_ptr<std::string const> interface;
mutable std::unique_ptr<std::string const> solidityInterface;
mutable std::unique_ptr<std::string const> userDocumentation;
mutable std::unique_ptr<std::string const> devDocumentation;

View File

@ -256,6 +256,61 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
CompilerUtils(m_context).storeInMemory(0);
m_context << u256(32) << u256(0) << eth::Instruction::SHA3;
break;
case Location::LOG0:
arguments.front()->accept(*this);
appendTypeConversion(*arguments.front()->getType(), *function.getParameterTypes().front(), true);
// @todo move this once we actually use memory
CompilerUtils(m_context).storeInMemory(0);
m_context << u256(32) << u256(0) << eth::Instruction::LOG0;
break;
case Location::LOG1:
arguments[1]->accept(*this);
arguments[0]->accept(*this);
appendTypeConversion(*arguments[1]->getType(), *function.getParameterTypes()[1], true);
appendTypeConversion(*arguments[0]->getType(), *function.getParameterTypes()[0], true);
// @todo move this once we actually use memory
CompilerUtils(m_context).storeInMemory(0);
m_context << u256(32) << u256(0) << eth::Instruction::LOG1;
break;
case Location::LOG2:
arguments[2]->accept(*this);
arguments[1]->accept(*this);
arguments[0]->accept(*this);
appendTypeConversion(*arguments[2]->getType(), *function.getParameterTypes()[2], true);
appendTypeConversion(*arguments[1]->getType(), *function.getParameterTypes()[1], true);
appendTypeConversion(*arguments[0]->getType(), *function.getParameterTypes()[0], true);
// @todo move this once we actually use memory
CompilerUtils(m_context).storeInMemory(0);
m_context << u256(32) << u256(0) << eth::Instruction::LOG2;
break;
case Location::LOG3:
arguments[3]->accept(*this);
arguments[2]->accept(*this);
arguments[1]->accept(*this);
arguments[0]->accept(*this);
appendTypeConversion(*arguments[3]->getType(), *function.getParameterTypes()[3], true);
appendTypeConversion(*arguments[2]->getType(), *function.getParameterTypes()[2], true);
appendTypeConversion(*arguments[1]->getType(), *function.getParameterTypes()[1], true);
appendTypeConversion(*arguments[0]->getType(), *function.getParameterTypes()[0], true);
// @todo move this once we actually use memory
CompilerUtils(m_context).storeInMemory(0);
m_context << u256(32) << u256(0) << eth::Instruction::LOG3;
break;
case Location::LOG4:
arguments[4]->accept(*this);
arguments[3]->accept(*this);
arguments[2]->accept(*this);
arguments[1]->accept(*this);
arguments[0]->accept(*this);
appendTypeConversion(*arguments[4]->getType(), *function.getParameterTypes()[4], true);
appendTypeConversion(*arguments[3]->getType(), *function.getParameterTypes()[3], true);
appendTypeConversion(*arguments[2]->getType(), *function.getParameterTypes()[2], true);
appendTypeConversion(*arguments[1]->getType(), *function.getParameterTypes()[1], true);
appendTypeConversion(*arguments[0]->getType(), *function.getParameterTypes()[0], true);
// @todo move this once we actually use memory
CompilerUtils(m_context).storeInMemory(0);
m_context << u256(32) << u256(0) << eth::Instruction::LOG4;
break;
case Location::ECRECOVER:
case Location::SHA256:
case Location::RIPEMD160:

View File

@ -33,33 +33,54 @@ namespace solidity
{
GlobalContext::GlobalContext():
// TODO: make this cleaner.
m_magicVariables(vector<shared_ptr<MagicVariableDeclaration const>>{make_shared<MagicVariableDeclaration>("block", make_shared<MagicType>(MagicType::Kind::BLOCK)),
make_shared<MagicVariableDeclaration>("msg", make_shared<MagicType>(MagicType::Kind::MSG)),
make_shared<MagicVariableDeclaration>("tx", make_shared<MagicType>(MagicType::Kind::TX)),
make_shared<MagicVariableDeclaration>("suicide",
make_shared<MagicVariableDeclaration>("msg", make_shared<MagicType>(MagicType::Kind::MSG)),
make_shared<MagicVariableDeclaration>("tx", make_shared<MagicType>(MagicType::Kind::TX)),
make_shared<MagicVariableDeclaration>("suicide",
make_shared<FunctionType>(TypePointers({std::make_shared<IntegerType>(0,
IntegerType::Modifier::ADDRESS)}),
TypePointers(),
FunctionType::Location::SUICIDE)),
make_shared<MagicVariableDeclaration>("sha3",
TypePointers(),
FunctionType::Location::SUICIDE)),
make_shared<MagicVariableDeclaration>("sha3",
make_shared<FunctionType>(TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
FunctionType::Location::SHA3)),
make_shared<MagicVariableDeclaration>("sha256",
TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
FunctionType::Location::SHA3)),
make_shared<MagicVariableDeclaration>("log0",
make_shared<FunctionType>(TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
FunctionType::Location::SHA256)),
make_shared<MagicVariableDeclaration>("ecrecover",
TypePointers(),
FunctionType::Location::LOG0)),
make_shared<MagicVariableDeclaration>("log1",
make_shared<FunctionType>(TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH), std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
TypePointers(),
FunctionType::Location::LOG1)),
make_shared<MagicVariableDeclaration>("log2",
make_shared<FunctionType>(TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH), std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH), std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
TypePointers(),
FunctionType::Location::LOG2)),
make_shared<MagicVariableDeclaration>("log3",
make_shared<FunctionType>(TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH), std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH), std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH), std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
TypePointers(),
FunctionType::Location::LOG3)),
make_shared<MagicVariableDeclaration>("log4",
make_shared<FunctionType>(TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH), std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH), std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH), std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH), std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
TypePointers(),
FunctionType::Location::LOG4)),
make_shared<MagicVariableDeclaration>("sha256",
make_shared<FunctionType>(TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
FunctionType::Location::SHA256)),
make_shared<MagicVariableDeclaration>("ecrecover",
make_shared<FunctionType>(TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH),
std::make_shared<IntegerType>(8, IntegerType::Modifier::HASH),
std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH),
std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
TypePointers({std::make_shared<IntegerType>(0, IntegerType::Modifier::ADDRESS)}),
FunctionType::Location::ECRECOVER)),
make_shared<MagicVariableDeclaration>("ripemd160",
TypePointers({std::make_shared<IntegerType>(0, IntegerType::Modifier::ADDRESS)}),
FunctionType::Location::ECRECOVER)),
make_shared<MagicVariableDeclaration>("ripemd160",
make_shared<FunctionType>(TypePointers({std::make_shared<IntegerType>(256, IntegerType::Modifier::HASH)}),
TypePointers({std::make_shared<IntegerType>(160, IntegerType::Modifier::HASH)}),
FunctionType::Location::RIPEMD160))})
TypePointers({std::make_shared<IntegerType>(160, IntegerType::Modifier::HASH)}),
FunctionType::Location::RIPEMD160))})
{
}

View File

@ -2,6 +2,7 @@
#include <libsolidity/InterfaceHandler.h>
#include <libsolidity/AST.h>
#include <libsolidity/CompilerStack.h>
using namespace std;
namespace dev
{
@ -26,6 +27,8 @@ std::unique_ptr<std::string> InterfaceHandler::getDocumentation(ContractDefiniti
return getDevDocumentation(_contractDef);
case DocumentationType::ABI_INTERFACE:
return getABIInterface(_contractDef);
case DocumentationType::ABI_SOLIDITY_INTERFACE:
return getABISolidityInterface(_contractDef);
}
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown documentation type"));
@ -64,6 +67,28 @@ std::unique_ptr<std::string> InterfaceHandler::getABIInterface(ContractDefinitio
return std::unique_ptr<std::string>(new std::string(m_writer.write(methods)));
}
unique_ptr<string> InterfaceHandler::getABISolidityInterface(ContractDefinition const& _contractDef)
{
string ret = "contract " + _contractDef.getName() + "{";
for (FunctionDefinition const* f: _contractDef.getInterfaceFunctions())
{
auto populateParameters = [](vector<ASTPointer<VariableDeclaration>> const& _vars)
{
string r = "";
for (ASTPointer<VariableDeclaration> const& var: _vars)
r += (r.size() ? "," : "(") + var->getType()->toString() + " " + var->getName();
return r.size() ? r + ")" : "()";
};
ret += "function " + f->getName() + populateParameters(f->getParameters()) + (f->isDeclaredConst() ? "constant " : "");
if (f->getReturnParameters().size())
ret += "returns" + populateParameters(f->getReturnParameters());
else if (ret.back() == ' ')
ret.pop_back();
ret += "{}";
}
return unique_ptr<string>(new string(ret + "}"));
}
std::unique_ptr<std::string> InterfaceHandler::getUserDocumentation(ContractDefinition const& _contractDef)
{
Json::Value doc;

View File

@ -74,6 +74,7 @@ public:
/// @return A unique pointer contained string with the json
/// representation of the contract's ABI Interface
std::unique_ptr<std::string> getABIInterface(ContractDefinition const& _contractDef);
std::unique_ptr<std::string> getABISolidityInterface(ContractDefinition const& _contractDef);
/// Get the User documentation of the contract
/// @param _contractDef The contract definition
/// @return A unique pointer contained string with the json

View File

@ -318,7 +318,7 @@ public:
/// INTERNAL: jump tag, EXTERNAL: contract address + function index,
/// BARE: contract address (non-abi contract call)
/// OTHERS: special virtual function, nothing on the stack
enum class Location { INTERNAL, EXTERNAL, SEND, SHA3, SUICIDE, ECRECOVER, SHA256, RIPEMD160, BARE };
enum class Location { INTERNAL, EXTERNAL, SEND, SHA3, SUICIDE, ECRECOVER, SHA256, RIPEMD160, LOG0, LOG1, LOG2, LOG3, LOG4, BARE };
virtual Category getCategory() const override { return Category::FUNCTION; }
explicit FunctionType(FunctionDefinition const& _function, bool _isInternal = true);