mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge branch 'develop' of github.com:ethereum/cpp-ethereum into develop
Conflicts: test/SolidityEndToEndTest.cpp test/SolidityNameAndTypeResolution.cpp test/SolidityParser.cpp
This commit is contained in:
commit
8e84dc27a7
14
AST.cpp
14
AST.cpp
@ -285,6 +285,20 @@ void ModifierInvocation::checkTypeRequirements()
|
|||||||
BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in modifier invocation."));
|
BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in modifier invocation."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EventDefinition::checkTypeRequirements()
|
||||||
|
{
|
||||||
|
int numIndexed = 0;
|
||||||
|
for (ASTPointer<VariableDeclaration> const& var: getParameters())
|
||||||
|
{
|
||||||
|
if (var->isIndexed())
|
||||||
|
numIndexed++;
|
||||||
|
if (!var->getType()->canLiveOutsideStorage())
|
||||||
|
BOOST_THROW_EXCEPTION(var->createTypeError("Type is required to live outside storage."));
|
||||||
|
}
|
||||||
|
if (numIndexed > 3)
|
||||||
|
BOOST_THROW_EXCEPTION(createTypeError("More than 3 indexed arguments for event."));
|
||||||
|
}
|
||||||
|
|
||||||
void Block::checkTypeRequirements()
|
void Block::checkTypeRequirements()
|
||||||
{
|
{
|
||||||
for (shared_ptr<Statement> const& statement: m_statements)
|
for (shared_ptr<Statement> const& statement: m_statements)
|
||||||
|
49
AST.h
49
AST.h
@ -202,13 +202,15 @@ public:
|
|||||||
std::vector<ASTPointer<StructDefinition>> const& _definedStructs,
|
std::vector<ASTPointer<StructDefinition>> const& _definedStructs,
|
||||||
std::vector<ASTPointer<VariableDeclaration>> const& _stateVariables,
|
std::vector<ASTPointer<VariableDeclaration>> const& _stateVariables,
|
||||||
std::vector<ASTPointer<FunctionDefinition>> const& _definedFunctions,
|
std::vector<ASTPointer<FunctionDefinition>> const& _definedFunctions,
|
||||||
std::vector<ASTPointer<ModifierDefinition>> const& _functionModifiers):
|
std::vector<ASTPointer<ModifierDefinition>> const& _functionModifiers,
|
||||||
|
std::vector<ASTPointer<EventDefinition>> const& _events):
|
||||||
Declaration(_location, _name), Documented(_documentation),
|
Declaration(_location, _name), Documented(_documentation),
|
||||||
m_baseContracts(_baseContracts),
|
m_baseContracts(_baseContracts),
|
||||||
m_definedStructs(_definedStructs),
|
m_definedStructs(_definedStructs),
|
||||||
m_stateVariables(_stateVariables),
|
m_stateVariables(_stateVariables),
|
||||||
m_definedFunctions(_definedFunctions),
|
m_definedFunctions(_definedFunctions),
|
||||||
m_functionModifiers(_functionModifiers)
|
m_functionModifiers(_functionModifiers),
|
||||||
|
m_events(_events)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual void accept(ASTVisitor& _visitor) override;
|
virtual void accept(ASTVisitor& _visitor) override;
|
||||||
@ -219,6 +221,7 @@ public:
|
|||||||
std::vector<ASTPointer<VariableDeclaration>> const& getStateVariables() const { return m_stateVariables; }
|
std::vector<ASTPointer<VariableDeclaration>> const& getStateVariables() const { return m_stateVariables; }
|
||||||
std::vector<ASTPointer<ModifierDefinition>> const& getFunctionModifiers() const { return m_functionModifiers; }
|
std::vector<ASTPointer<ModifierDefinition>> const& getFunctionModifiers() const { return m_functionModifiers; }
|
||||||
std::vector<ASTPointer<FunctionDefinition>> const& getDefinedFunctions() const { return m_definedFunctions; }
|
std::vector<ASTPointer<FunctionDefinition>> const& getDefinedFunctions() const { return m_definedFunctions; }
|
||||||
|
std::vector<ASTPointer<EventDefinition>> const& getEvents() const { return m_events; }
|
||||||
|
|
||||||
virtual TypePointer getType(ContractDefinition const* m_currentContract) const override;
|
virtual TypePointer getType(ContractDefinition const* m_currentContract) const override;
|
||||||
|
|
||||||
@ -250,6 +253,7 @@ private:
|
|||||||
std::vector<ASTPointer<VariableDeclaration>> m_stateVariables;
|
std::vector<ASTPointer<VariableDeclaration>> m_stateVariables;
|
||||||
std::vector<ASTPointer<FunctionDefinition>> m_definedFunctions;
|
std::vector<ASTPointer<FunctionDefinition>> m_definedFunctions;
|
||||||
std::vector<ASTPointer<ModifierDefinition>> m_functionModifiers;
|
std::vector<ASTPointer<ModifierDefinition>> m_functionModifiers;
|
||||||
|
std::vector<ASTPointer<EventDefinition>> m_events;
|
||||||
|
|
||||||
std::vector<ContractDefinition const*> m_linearizedBaseContracts;
|
std::vector<ContractDefinition const*> m_linearizedBaseContracts;
|
||||||
mutable std::unique_ptr<std::vector<std::pair<FixedHash<4>, FunctionTypePointer>>> m_interfaceFunctionList;
|
mutable std::unique_ptr<std::vector<std::pair<FixedHash<4>, FunctionTypePointer>>> m_interfaceFunctionList;
|
||||||
@ -382,8 +386,10 @@ class VariableDeclaration: public Declaration
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VariableDeclaration(Location const& _location, ASTPointer<TypeName> const& _type,
|
VariableDeclaration(Location const& _location, ASTPointer<TypeName> const& _type,
|
||||||
ASTPointer<ASTString> const& _name, bool _isPublic, bool _isStateVar = false):
|
ASTPointer<ASTString> const& _name, bool _isPublic, bool _isStateVar = false,
|
||||||
Declaration(_location, _name), m_typeName(_type), m_isPublic(_isPublic), m_isStateVariable(_isStateVar) {}
|
bool _isIndexed = false):
|
||||||
|
Declaration(_location, _name), m_typeName(_type),
|
||||||
|
m_isPublic(_isPublic), m_isStateVariable(_isStateVar), m_isIndexed(_isIndexed) {}
|
||||||
virtual void accept(ASTVisitor& _visitor) override;
|
virtual void accept(ASTVisitor& _visitor) override;
|
||||||
virtual void accept(ASTConstVisitor& _visitor) const override;
|
virtual void accept(ASTConstVisitor& _visitor) const override;
|
||||||
|
|
||||||
@ -398,12 +404,13 @@ public:
|
|||||||
bool isLocalVariable() const { return !!dynamic_cast<FunctionDefinition const*>(getScope()); }
|
bool isLocalVariable() const { return !!dynamic_cast<FunctionDefinition const*>(getScope()); }
|
||||||
bool isPublic() const { return m_isPublic; }
|
bool isPublic() const { return m_isPublic; }
|
||||||
bool isStateVariable() const { return m_isStateVariable; }
|
bool isStateVariable() const { return m_isStateVariable; }
|
||||||
|
bool isIndexed() const { return m_isIndexed; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ASTPointer<TypeName> m_typeName; ///< can be empty ("var")
|
ASTPointer<TypeName> m_typeName; ///< can be empty ("var")
|
||||||
bool m_isPublic; ///< Whether there is an accessor for it or not
|
bool m_isPublic; ///< Whether there is an accessor for it or not
|
||||||
bool m_isStateVariable; ///< Whether or not this is a contract state variable
|
bool m_isStateVariable; ///< Whether or not this is a contract state variable
|
||||||
|
bool m_isIndexed; ///< Whether this is an indexed variable (used by events).
|
||||||
|
|
||||||
std::shared_ptr<Type const> m_type; ///< derived type, initially empty
|
std::shared_ptr<Type const> m_type; ///< derived type, initially empty
|
||||||
};
|
};
|
||||||
@ -431,7 +438,6 @@ public:
|
|||||||
|
|
||||||
virtual TypePointer getType(ContractDefinition const* = nullptr) const override;
|
virtual TypePointer getType(ContractDefinition const* = nullptr) const override;
|
||||||
|
|
||||||
|
|
||||||
void checkTypeRequirements();
|
void checkTypeRequirements();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -462,6 +468,37 @@ private:
|
|||||||
std::vector<ASTPointer<Expression>> m_arguments;
|
std::vector<ASTPointer<Expression>> m_arguments;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Definition of a (loggable) event.
|
||||||
|
*/
|
||||||
|
class EventDefinition: public Declaration, public Documented
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EventDefinition(Location const& _location,
|
||||||
|
ASTPointer<ASTString> const& _name,
|
||||||
|
ASTPointer<ASTString> const& _documentation,
|
||||||
|
ASTPointer<ParameterList> const& _parameters):
|
||||||
|
Declaration(_location, _name), Documented(_documentation), m_parameters(_parameters) {}
|
||||||
|
|
||||||
|
virtual void accept(ASTVisitor& _visitor) override;
|
||||||
|
virtual void accept(ASTConstVisitor& _visitor) const override;
|
||||||
|
|
||||||
|
std::vector<ASTPointer<VariableDeclaration>> const& getParameters() const { return m_parameters->getParameters(); }
|
||||||
|
ParameterList const& getParameterList() const { return *m_parameters; }
|
||||||
|
Block const& getBody() const { return *m_body; }
|
||||||
|
|
||||||
|
virtual TypePointer getType(ContractDefinition const* = nullptr) const override
|
||||||
|
{
|
||||||
|
return std::make_shared<FunctionType>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkTypeRequirements();
|
||||||
|
|
||||||
|
private:
|
||||||
|
ASTPointer<ParameterList> m_parameters;
|
||||||
|
ASTPointer<Block> m_body;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pseudo AST node that is used as declaration for "this", "msg", "tx", "block" and the global
|
* Pseudo AST node that is used as declaration for "this", "msg", "tx", "block" and the global
|
||||||
* functions when such an identifier is encountered. Will never have a valid location in the source code.
|
* functions when such an identifier is encountered. Will never have a valid location in the source code.
|
||||||
|
@ -45,6 +45,7 @@ class FunctionDefinition;
|
|||||||
class VariableDeclaration;
|
class VariableDeclaration;
|
||||||
class ModifierDefinition;
|
class ModifierDefinition;
|
||||||
class ModifierInvocation;
|
class ModifierInvocation;
|
||||||
|
class EventDefinition;
|
||||||
class MagicVariableDeclaration;
|
class MagicVariableDeclaration;
|
||||||
class TypeName;
|
class TypeName;
|
||||||
class ElementaryTypeName;
|
class ElementaryTypeName;
|
||||||
|
@ -108,6 +108,13 @@ bool ASTPrinter::visit(ModifierInvocation const& _node)
|
|||||||
return goDeeper();
|
return goDeeper();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ASTPrinter::visit(EventDefinition const& _node)
|
||||||
|
{
|
||||||
|
writeLine("EventDefinition \"" + _node.getName() + "\"");
|
||||||
|
printSourcePart(_node);
|
||||||
|
return goDeeper();
|
||||||
|
}
|
||||||
|
|
||||||
bool ASTPrinter::visit(TypeName const& _node)
|
bool ASTPrinter::visit(TypeName const& _node)
|
||||||
{
|
{
|
||||||
writeLine("TypeName");
|
writeLine("TypeName");
|
||||||
@ -365,6 +372,11 @@ void ASTPrinter::endVisit(ModifierInvocation const&)
|
|||||||
m_indentation--;
|
m_indentation--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ASTPrinter::endVisit(EventDefinition const&)
|
||||||
|
{
|
||||||
|
m_indentation--;
|
||||||
|
}
|
||||||
|
|
||||||
void ASTPrinter::endVisit(TypeName const&)
|
void ASTPrinter::endVisit(TypeName const&)
|
||||||
{
|
{
|
||||||
m_indentation--;
|
m_indentation--;
|
||||||
|
@ -51,6 +51,7 @@ public:
|
|||||||
bool visit(VariableDeclaration const& _node) override;
|
bool visit(VariableDeclaration const& _node) override;
|
||||||
bool visit(ModifierDefinition const& _node) override;
|
bool visit(ModifierDefinition const& _node) override;
|
||||||
bool visit(ModifierInvocation const& _node) override;
|
bool visit(ModifierInvocation const& _node) override;
|
||||||
|
bool visit(EventDefinition const& _node) override;
|
||||||
bool visit(TypeName const& _node) override;
|
bool visit(TypeName const& _node) override;
|
||||||
bool visit(ElementaryTypeName const& _node) override;
|
bool visit(ElementaryTypeName const& _node) override;
|
||||||
bool visit(UserDefinedTypeName const& _node) override;
|
bool visit(UserDefinedTypeName const& _node) override;
|
||||||
@ -89,6 +90,7 @@ public:
|
|||||||
void endVisit(VariableDeclaration const&) override;
|
void endVisit(VariableDeclaration const&) override;
|
||||||
void endVisit(ModifierDefinition const&) override;
|
void endVisit(ModifierDefinition const&) override;
|
||||||
void endVisit(ModifierInvocation const&) override;
|
void endVisit(ModifierInvocation const&) override;
|
||||||
|
void endVisit(EventDefinition const&) override;
|
||||||
void endVisit(TypeName const&) override;
|
void endVisit(TypeName const&) override;
|
||||||
void endVisit(ElementaryTypeName const&) override;
|
void endVisit(ElementaryTypeName const&) override;
|
||||||
void endVisit(UserDefinedTypeName const&) override;
|
void endVisit(UserDefinedTypeName const&) override;
|
||||||
|
@ -52,6 +52,7 @@ public:
|
|||||||
virtual bool visit(VariableDeclaration&) { return true; }
|
virtual bool visit(VariableDeclaration&) { return true; }
|
||||||
virtual bool visit(ModifierDefinition&) { return true; }
|
virtual bool visit(ModifierDefinition&) { return true; }
|
||||||
virtual bool visit(ModifierInvocation&) { return true; }
|
virtual bool visit(ModifierInvocation&) { return true; }
|
||||||
|
virtual bool visit(EventDefinition&) { return true; }
|
||||||
virtual bool visit(TypeName&) { return true; }
|
virtual bool visit(TypeName&) { return true; }
|
||||||
virtual bool visit(ElementaryTypeName&) { return true; }
|
virtual bool visit(ElementaryTypeName&) { return true; }
|
||||||
virtual bool visit(UserDefinedTypeName&) { return true; }
|
virtual bool visit(UserDefinedTypeName&) { return true; }
|
||||||
@ -92,6 +93,7 @@ public:
|
|||||||
virtual void endVisit(VariableDeclaration&) { }
|
virtual void endVisit(VariableDeclaration&) { }
|
||||||
virtual void endVisit(ModifierDefinition&) { }
|
virtual void endVisit(ModifierDefinition&) { }
|
||||||
virtual void endVisit(ModifierInvocation&) { }
|
virtual void endVisit(ModifierInvocation&) { }
|
||||||
|
virtual void endVisit(EventDefinition&) { }
|
||||||
virtual void endVisit(TypeName&) { }
|
virtual void endVisit(TypeName&) { }
|
||||||
virtual void endVisit(ElementaryTypeName&) { }
|
virtual void endVisit(ElementaryTypeName&) { }
|
||||||
virtual void endVisit(UserDefinedTypeName&) { }
|
virtual void endVisit(UserDefinedTypeName&) { }
|
||||||
@ -136,6 +138,7 @@ public:
|
|||||||
virtual bool visit(VariableDeclaration const&) { return true; }
|
virtual bool visit(VariableDeclaration const&) { return true; }
|
||||||
virtual bool visit(ModifierDefinition const&) { return true; }
|
virtual bool visit(ModifierDefinition const&) { return true; }
|
||||||
virtual bool visit(ModifierInvocation const&) { return true; }
|
virtual bool visit(ModifierInvocation const&) { return true; }
|
||||||
|
virtual bool visit(EventDefinition const&) { return true; }
|
||||||
virtual bool visit(TypeName const&) { return true; }
|
virtual bool visit(TypeName const&) { return true; }
|
||||||
virtual bool visit(ElementaryTypeName const&) { return true; }
|
virtual bool visit(ElementaryTypeName const&) { return true; }
|
||||||
virtual bool visit(UserDefinedTypeName const&) { return true; }
|
virtual bool visit(UserDefinedTypeName const&) { return true; }
|
||||||
@ -176,6 +179,7 @@ public:
|
|||||||
virtual void endVisit(VariableDeclaration const&) { }
|
virtual void endVisit(VariableDeclaration const&) { }
|
||||||
virtual void endVisit(ModifierDefinition const&) { }
|
virtual void endVisit(ModifierDefinition const&) { }
|
||||||
virtual void endVisit(ModifierInvocation const&) { }
|
virtual void endVisit(ModifierInvocation const&) { }
|
||||||
|
virtual void endVisit(EventDefinition const&) { }
|
||||||
virtual void endVisit(TypeName const&) { }
|
virtual void endVisit(TypeName const&) { }
|
||||||
virtual void endVisit(ElementaryTypeName const&) { }
|
virtual void endVisit(ElementaryTypeName const&) { }
|
||||||
virtual void endVisit(UserDefinedTypeName const&) { }
|
virtual void endVisit(UserDefinedTypeName const&) { }
|
||||||
|
20
AST_accept.h
20
AST_accept.h
@ -64,8 +64,9 @@ void ContractDefinition::accept(ASTVisitor& _visitor)
|
|||||||
listAccept(m_baseContracts, _visitor);
|
listAccept(m_baseContracts, _visitor);
|
||||||
listAccept(m_definedStructs, _visitor);
|
listAccept(m_definedStructs, _visitor);
|
||||||
listAccept(m_stateVariables, _visitor);
|
listAccept(m_stateVariables, _visitor);
|
||||||
listAccept(m_definedFunctions, _visitor);
|
listAccept(m_events, _visitor);
|
||||||
listAccept(m_functionModifiers, _visitor);
|
listAccept(m_functionModifiers, _visitor);
|
||||||
|
listAccept(m_definedFunctions, _visitor);
|
||||||
}
|
}
|
||||||
_visitor.endVisit(*this);
|
_visitor.endVisit(*this);
|
||||||
}
|
}
|
||||||
@ -77,8 +78,9 @@ void ContractDefinition::accept(ASTConstVisitor& _visitor) const
|
|||||||
listAccept(m_baseContracts, _visitor);
|
listAccept(m_baseContracts, _visitor);
|
||||||
listAccept(m_definedStructs, _visitor);
|
listAccept(m_definedStructs, _visitor);
|
||||||
listAccept(m_stateVariables, _visitor);
|
listAccept(m_stateVariables, _visitor);
|
||||||
listAccept(m_definedFunctions, _visitor);
|
listAccept(m_events, _visitor);
|
||||||
listAccept(m_functionModifiers, _visitor);
|
listAccept(m_functionModifiers, _visitor);
|
||||||
|
listAccept(m_definedFunctions, _visitor);
|
||||||
}
|
}
|
||||||
_visitor.endVisit(*this);
|
_visitor.endVisit(*this);
|
||||||
}
|
}
|
||||||
@ -219,6 +221,20 @@ void ModifierInvocation::accept(ASTConstVisitor& _visitor) const
|
|||||||
_visitor.endVisit(*this);
|
_visitor.endVisit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EventDefinition::accept(ASTVisitor& _visitor)
|
||||||
|
{
|
||||||
|
if (_visitor.visit(*this))
|
||||||
|
m_parameters->accept(_visitor);
|
||||||
|
_visitor.endVisit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventDefinition::accept(ASTConstVisitor& _visitor) const
|
||||||
|
{
|
||||||
|
if (_visitor.visit(*this))
|
||||||
|
m_parameters->accept(_visitor);
|
||||||
|
_visitor.endVisit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
void TypeName::accept(ASTVisitor& _visitor)
|
void TypeName::accept(ASTVisitor& _visitor)
|
||||||
{
|
{
|
||||||
_visitor.visit(*this);
|
_visitor.visit(*this);
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <libdevcore/Common.h>
|
#include <libdevcore/Common.h>
|
||||||
|
#include <libdevcrypto/SHA3.h>
|
||||||
#include <libsolidity/AST.h>
|
#include <libsolidity/AST.h>
|
||||||
#include <libsolidity/ExpressionCompiler.h>
|
#include <libsolidity/ExpressionCompiler.h>
|
||||||
#include <libsolidity/CompilerContext.h>
|
#include <libsolidity/CompilerContext.h>
|
||||||
@ -304,10 +305,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
|||||||
m_context << eth::Instruction::SUICIDE;
|
m_context << eth::Instruction::SUICIDE;
|
||||||
break;
|
break;
|
||||||
case Location::SHA3:
|
case Location::SHA3:
|
||||||
arguments.front()->accept(*this);
|
appendExpressionCopyToMemory(*function.getParameterTypes().front(), *arguments.front());
|
||||||
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::SHA3;
|
m_context << u256(32) << u256(0) << eth::Instruction::SHA3;
|
||||||
break;
|
break;
|
||||||
case Location::LOG0:
|
case Location::LOG0:
|
||||||
@ -317,14 +315,41 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
|||||||
case Location::LOG4:
|
case Location::LOG4:
|
||||||
{
|
{
|
||||||
unsigned logNumber = int(function.getLocation()) - int(Location::LOG0);
|
unsigned logNumber = int(function.getLocation()) - int(Location::LOG0);
|
||||||
for (int arg = logNumber; arg >= 0; --arg)
|
for (unsigned arg = logNumber; arg > 0; --arg)
|
||||||
{
|
{
|
||||||
arguments[arg]->accept(*this);
|
arguments[arg]->accept(*this);
|
||||||
appendTypeConversion(*arguments[arg]->getType(), *function.getParameterTypes()[arg], true);
|
appendTypeConversion(*arguments[arg]->getType(), *function.getParameterTypes()[arg], true);
|
||||||
}
|
}
|
||||||
// @todo move this once we actually use memory
|
unsigned length = appendExpressionCopyToMemory(*function.getParameterTypes().front(),
|
||||||
CompilerUtils(m_context).storeInMemory(0);
|
*arguments.front());
|
||||||
m_context << u256(32) << u256(0) << eth::logInstruction(logNumber);
|
solAssert(length == 32, "Log data should be 32 bytes long (for now).");
|
||||||
|
m_context << u256(length) << u256(0) << eth::logInstruction(logNumber);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Location::EVENT:
|
||||||
|
{
|
||||||
|
_functionCall.getExpression().accept(*this);
|
||||||
|
auto const& event = dynamic_cast<EventDefinition const&>(function.getDeclaration());
|
||||||
|
// Copy all non-indexed arguments to memory (data)
|
||||||
|
unsigned numIndexed = 0;
|
||||||
|
unsigned memLength = 0;
|
||||||
|
for (unsigned arg = 0; arg < arguments.size(); ++arg)
|
||||||
|
if (!event.getParameters()[arg]->isIndexed())
|
||||||
|
memLength += appendExpressionCopyToMemory(*function.getParameterTypes()[arg],
|
||||||
|
*arguments[arg], memLength);
|
||||||
|
// All indexed arguments go to the stack
|
||||||
|
for (unsigned arg = arguments.size(); arg > 0; --arg)
|
||||||
|
if (event.getParameters()[arg - 1]->isIndexed())
|
||||||
|
{
|
||||||
|
++numIndexed;
|
||||||
|
arguments[arg - 1]->accept(*this);
|
||||||
|
appendTypeConversion(*arguments[arg - 1]->getType(),
|
||||||
|
*function.getParameterTypes()[arg - 1], true);
|
||||||
|
}
|
||||||
|
m_context << u256(h256::Arith(dev::sha3(function.getCanonicalSignature(event.getName()))));
|
||||||
|
++numIndexed;
|
||||||
|
solAssert(numIndexed <= 4, "Too many indexed arguments.");
|
||||||
|
m_context << u256(memLength) << u256(0) << eth::logInstruction(numIndexed);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Location::BLOCKHASH:
|
case Location::BLOCKHASH:
|
||||||
@ -459,14 +484,13 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess)
|
|||||||
bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
|
bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
|
||||||
{
|
{
|
||||||
_indexAccess.getBaseExpression().accept(*this);
|
_indexAccess.getBaseExpression().accept(*this);
|
||||||
_indexAccess.getIndexExpression().accept(*this);
|
|
||||||
appendTypeConversion(*_indexAccess.getIndexExpression().getType(),
|
TypePointer const& keyType = dynamic_cast<MappingType const&>(*_indexAccess.getBaseExpression().getType()).getKeyType();
|
||||||
*dynamic_cast<MappingType const&>(*_indexAccess.getBaseExpression().getType()).getKeyType(),
|
unsigned length = appendExpressionCopyToMemory(*keyType, _indexAccess.getIndexExpression());
|
||||||
true);
|
solAssert(length == 32, "Mapping key has to take 32 bytes in memory (for now).");
|
||||||
// @todo move this once we actually use memory
|
// @todo move this once we actually use memory
|
||||||
CompilerUtils(m_context).storeInMemory(0);
|
length += CompilerUtils(m_context).storeInMemory(length);
|
||||||
CompilerUtils(m_context).storeInMemory(32);
|
m_context << u256(length) << u256(0) << eth::Instruction::SHA3;
|
||||||
m_context << u256(64) << u256(0) << eth::Instruction::SHA3;
|
|
||||||
|
|
||||||
m_currentLValue = LValue(m_context, LValue::STORAGE, *_indexAccess.getType());
|
m_currentLValue = LValue(m_context, LValue::STORAGE, *_indexAccess.getType());
|
||||||
m_currentLValue.retrieveValueIfLValueNotRequested(_indexAccess);
|
m_currentLValue.retrieveValueIfLValueNotRequested(_indexAccess);
|
||||||
@ -495,6 +519,10 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier)
|
|||||||
{
|
{
|
||||||
// no-op
|
// no-op
|
||||||
}
|
}
|
||||||
|
else if (dynamic_cast<EventDefinition const*>(declaration))
|
||||||
|
{
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Identifier type not expected in expression context."));
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Identifier type not expected in expression context."));
|
||||||
@ -791,22 +819,25 @@ unsigned ExpressionCompiler::appendArgumentCopyToMemory(TypePointers const& _typ
|
|||||||
{
|
{
|
||||||
unsigned length = 0;
|
unsigned length = 0;
|
||||||
for (unsigned i = 0; i < _arguments.size(); ++i)
|
for (unsigned i = 0; i < _arguments.size(); ++i)
|
||||||
{
|
length += appendExpressionCopyToMemory(*_types[i], *_arguments[i], _memoryOffset + length);
|
||||||
_arguments[i]->accept(*this);
|
|
||||||
appendTypeConversion(*_arguments[i]->getType(), *_types[i], true);
|
|
||||||
unsigned const c_numBytes = _types[i]->getCalldataEncodedSize();
|
|
||||||
if (c_numBytes == 0 || c_numBytes > 32)
|
|
||||||
BOOST_THROW_EXCEPTION(CompilerError()
|
|
||||||
<< errinfo_sourceLocation(_arguments[i]->getLocation())
|
|
||||||
<< errinfo_comment("Type " + _types[i]->toString() + " not yet supported."));
|
|
||||||
bool const c_leftAligned = _types[i]->getCategory() == Type::Category::STRING;
|
|
||||||
bool const c_padToWords = true;
|
|
||||||
length += CompilerUtils(m_context).storeInMemory(_memoryOffset + length, c_numBytes,
|
|
||||||
c_leftAligned, c_padToWords);
|
|
||||||
}
|
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType,
|
||||||
|
Expression const& _expression, unsigned _memoryOffset)
|
||||||
|
{
|
||||||
|
_expression.accept(*this);
|
||||||
|
appendTypeConversion(*_expression.getType(), _expectedType, true);
|
||||||
|
unsigned const c_numBytes = CompilerUtils::getPaddedSize(_expectedType.getCalldataEncodedSize());
|
||||||
|
if (c_numBytes == 0 || c_numBytes > 32)
|
||||||
|
BOOST_THROW_EXCEPTION(CompilerError()
|
||||||
|
<< errinfo_sourceLocation(_expression.getLocation())
|
||||||
|
<< errinfo_comment("Type " + _expectedType.toString() + " not yet supported."));
|
||||||
|
bool const c_leftAligned = _expectedType.getCategory() == Type::Category::STRING;
|
||||||
|
bool const c_padToWords = true;
|
||||||
|
return CompilerUtils(m_context).storeInMemory(_memoryOffset, c_numBytes, c_leftAligned, c_padToWords);
|
||||||
|
}
|
||||||
|
|
||||||
void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& _varDecl)
|
void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& _varDecl)
|
||||||
{
|
{
|
||||||
m_currentLValue.fromStateVariable(_varDecl, _varDecl.getType());
|
m_currentLValue.fromStateVariable(_varDecl, _varDecl.getType());
|
||||||
|
@ -94,8 +94,13 @@ private:
|
|||||||
bool bare = false);
|
bool bare = false);
|
||||||
/// Appends code that copies the given arguments to memory (with optional offset).
|
/// Appends code that copies the given arguments to memory (with optional offset).
|
||||||
/// @returns the number of bytes copied to memory
|
/// @returns the number of bytes copied to memory
|
||||||
unsigned appendArgumentCopyToMemory(TypePointers const& _functionType, std::vector<ASTPointer<Expression const>> const& _arguments,
|
unsigned appendArgumentCopyToMemory(TypePointers const& _types,
|
||||||
|
std::vector<ASTPointer<Expression const>> const& _arguments,
|
||||||
unsigned _memoryOffset = 0);
|
unsigned _memoryOffset = 0);
|
||||||
|
/// Appends code that evaluates a single expression and copies it to memory (with optional offset).
|
||||||
|
/// @returns the number of bytes copied to memory
|
||||||
|
unsigned appendExpressionCopyToMemory(Type const& _expectedType, Expression const& _expression,
|
||||||
|
unsigned _memoryOffset = 0);
|
||||||
|
|
||||||
/// Appends code for a State Variable accessor function
|
/// Appends code for a State Variable accessor function
|
||||||
void appendStateVariableAccessor(VariableDeclaration const& _varDecl);
|
void appendStateVariableAccessor(VariableDeclaration const& _varDecl);
|
||||||
|
@ -60,6 +60,8 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
|
|||||||
ReferencesResolver resolver(*structDef, *this, &_contract, nullptr);
|
ReferencesResolver resolver(*structDef, *this, &_contract, nullptr);
|
||||||
for (ASTPointer<VariableDeclaration> const& variable: _contract.getStateVariables())
|
for (ASTPointer<VariableDeclaration> const& variable: _contract.getStateVariables())
|
||||||
ReferencesResolver resolver(*variable, *this, &_contract, nullptr);
|
ReferencesResolver resolver(*variable, *this, &_contract, nullptr);
|
||||||
|
for (ASTPointer<EventDefinition> const& event: _contract.getEvents())
|
||||||
|
ReferencesResolver resolver(*event, *this, &_contract, nullptr);
|
||||||
for (ASTPointer<ModifierDefinition> const& modifier: _contract.getFunctionModifiers())
|
for (ASTPointer<ModifierDefinition> const& modifier: _contract.getFunctionModifiers())
|
||||||
{
|
{
|
||||||
m_currentScope = &m_scopes[modifier.get()];
|
m_currentScope = &m_scopes[modifier.get()];
|
||||||
@ -259,6 +261,12 @@ bool DeclarationRegistrationHelper::visit(VariableDeclaration& _declaration)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DeclarationRegistrationHelper::visit(EventDefinition& _event)
|
||||||
|
{
|
||||||
|
registerDeclaration(_event, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void DeclarationRegistrationHelper::enterNewSubScope(Declaration const& _declaration)
|
void DeclarationRegistrationHelper::enterNewSubScope(Declaration const& _declaration)
|
||||||
{
|
{
|
||||||
map<ASTNode const*, DeclarationContainer>::iterator iter;
|
map<ASTNode const*, DeclarationContainer>::iterator iter;
|
||||||
|
@ -104,6 +104,7 @@ private:
|
|||||||
void endVisit(ModifierDefinition& _modifier);
|
void endVisit(ModifierDefinition& _modifier);
|
||||||
void endVisit(VariableDefinition& _variableDefinition);
|
void endVisit(VariableDefinition& _variableDefinition);
|
||||||
bool visit(VariableDeclaration& _declaration);
|
bool visit(VariableDeclaration& _declaration);
|
||||||
|
bool visit(EventDefinition& _event);
|
||||||
|
|
||||||
void enterNewSubScope(Declaration const& _declaration);
|
void enterNewSubScope(Declaration const& _declaration);
|
||||||
void closeCurrentScope();
|
void closeCurrentScope();
|
||||||
|
59
Parser.cpp
59
Parser.cpp
@ -122,6 +122,7 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
|
|||||||
vector<ASTPointer<VariableDeclaration>> stateVariables;
|
vector<ASTPointer<VariableDeclaration>> stateVariables;
|
||||||
vector<ASTPointer<FunctionDefinition>> functions;
|
vector<ASTPointer<FunctionDefinition>> functions;
|
||||||
vector<ASTPointer<ModifierDefinition>> modifiers;
|
vector<ASTPointer<ModifierDefinition>> modifiers;
|
||||||
|
vector<ASTPointer<EventDefinition>> events;
|
||||||
if (m_scanner->getCurrentToken() == Token::IS)
|
if (m_scanner->getCurrentToken() == Token::IS)
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -149,19 +150,23 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
|
|||||||
else if (currentToken == Token::IDENTIFIER || currentToken == Token::MAPPING ||
|
else if (currentToken == Token::IDENTIFIER || currentToken == Token::MAPPING ||
|
||||||
Token::isElementaryTypeName(currentToken))
|
Token::isElementaryTypeName(currentToken))
|
||||||
{
|
{
|
||||||
bool const allowVar = false;
|
VarDeclParserOptions options;
|
||||||
stateVariables.push_back(parseVariableDeclaration(allowVar, visibilityIsPublic, true));
|
options.isPublic = visibilityIsPublic;
|
||||||
|
options.isStateVariable = true;
|
||||||
|
stateVariables.push_back(parseVariableDeclaration(options));
|
||||||
expectToken(Token::SEMICOLON);
|
expectToken(Token::SEMICOLON);
|
||||||
}
|
}
|
||||||
else if (currentToken == Token::MODIFIER)
|
else if (currentToken == Token::MODIFIER)
|
||||||
modifiers.push_back(parseModifierDefinition());
|
modifiers.push_back(parseModifierDefinition());
|
||||||
|
else if (currentToken == Token::EVENT)
|
||||||
|
events.push_back(parseEventDefinition());
|
||||||
else
|
else
|
||||||
BOOST_THROW_EXCEPTION(createParserError("Function, variable, struct or modifier declaration expected."));
|
BOOST_THROW_EXCEPTION(createParserError("Function, variable, struct or modifier declaration expected."));
|
||||||
}
|
}
|
||||||
nodeFactory.markEndPosition();
|
nodeFactory.markEndPosition();
|
||||||
expectToken(Token::RBRACE);
|
expectToken(Token::RBRACE);
|
||||||
return nodeFactory.createNode<ContractDefinition>(name, docString, baseContracts, structs,
|
return nodeFactory.createNode<ContractDefinition>(name, docString, baseContracts, structs,
|
||||||
stateVariables, functions, modifiers);
|
stateVariables, functions, modifiers, events);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTPointer<InheritanceSpecifier> Parser::parseInheritanceSpecifier()
|
ASTPointer<InheritanceSpecifier> Parser::parseInheritanceSpecifier()
|
||||||
@ -240,8 +245,7 @@ ASTPointer<StructDefinition> Parser::parseStructDefinition()
|
|||||||
expectToken(Token::LBRACE);
|
expectToken(Token::LBRACE);
|
||||||
while (m_scanner->getCurrentToken() != Token::RBRACE)
|
while (m_scanner->getCurrentToken() != Token::RBRACE)
|
||||||
{
|
{
|
||||||
bool const allowVar = false;
|
members.push_back(parseVariableDeclaration());
|
||||||
members.push_back(parseVariableDeclaration(allowVar));
|
|
||||||
expectToken(Token::SEMICOLON);
|
expectToken(Token::SEMICOLON);
|
||||||
}
|
}
|
||||||
nodeFactory.markEndPosition();
|
nodeFactory.markEndPosition();
|
||||||
@ -249,12 +253,20 @@ ASTPointer<StructDefinition> Parser::parseStructDefinition()
|
|||||||
return nodeFactory.createNode<StructDefinition>(name, members);
|
return nodeFactory.createNode<StructDefinition>(name, members);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(bool _allowVar, bool _isPublic, bool _isStateVariable)
|
ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(VarDeclParserOptions const& _options)
|
||||||
{
|
{
|
||||||
ASTNodeFactory nodeFactory(*this);
|
ASTNodeFactory nodeFactory(*this);
|
||||||
ASTPointer<TypeName> type = parseTypeName(_allowVar);
|
ASTPointer<TypeName> type = parseTypeName(_options.allowVar);
|
||||||
|
bool isIndexed = false;
|
||||||
|
if (_options.allowIndexed && m_scanner->getCurrentToken() == Token::INDEXED)
|
||||||
|
{
|
||||||
|
isIndexed = true;
|
||||||
|
m_scanner->next();
|
||||||
|
}
|
||||||
nodeFactory.markEndPosition();
|
nodeFactory.markEndPosition();
|
||||||
return nodeFactory.createNode<VariableDeclaration>(type, expectIdentifierToken(), _isPublic, _isStateVariable);
|
return nodeFactory.createNode<VariableDeclaration>(type, expectIdentifierToken(),
|
||||||
|
_options.isPublic, _options.isStateVariable,
|
||||||
|
isIndexed);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTPointer<ModifierDefinition> Parser::parseModifierDefinition()
|
ASTPointer<ModifierDefinition> Parser::parseModifierDefinition()
|
||||||
@ -284,6 +296,23 @@ ASTPointer<ModifierDefinition> Parser::parseModifierDefinition()
|
|||||||
return nodeFactory.createNode<ModifierDefinition>(name, docstring, parameters, block);
|
return nodeFactory.createNode<ModifierDefinition>(name, docstring, parameters, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASTPointer<EventDefinition> Parser::parseEventDefinition()
|
||||||
|
{
|
||||||
|
ASTNodeFactory nodeFactory(*this);
|
||||||
|
ASTPointer<ASTString> docstring;
|
||||||
|
if (m_scanner->getCurrentCommentLiteral() != "")
|
||||||
|
docstring = make_shared<ASTString>(m_scanner->getCurrentCommentLiteral());
|
||||||
|
|
||||||
|
expectToken(Token::EVENT);
|
||||||
|
ASTPointer<ASTString> name(expectIdentifierToken());
|
||||||
|
ASTPointer<ParameterList> parameters;
|
||||||
|
if (m_scanner->getCurrentToken() == Token::LPAREN)
|
||||||
|
parameters = parseParameterList(true, true);
|
||||||
|
nodeFactory.markEndPosition();
|
||||||
|
expectToken(Token::SEMICOLON);
|
||||||
|
return nodeFactory.createNode<EventDefinition>(name, docstring, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
ASTPointer<ModifierInvocation> Parser::parseModifierInvocation()
|
ASTPointer<ModifierInvocation> Parser::parseModifierInvocation()
|
||||||
{
|
{
|
||||||
ASTNodeFactory nodeFactory(*this);
|
ASTNodeFactory nodeFactory(*this);
|
||||||
@ -356,19 +385,20 @@ ASTPointer<Mapping> Parser::parseMapping()
|
|||||||
return nodeFactory.createNode<Mapping>(keyType, valueType);
|
return nodeFactory.createNode<Mapping>(keyType, valueType);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTPointer<ParameterList> Parser::parseParameterList(bool _allowEmpty)
|
ASTPointer<ParameterList> Parser::parseParameterList(bool _allowEmpty, bool _allowIndexed)
|
||||||
{
|
{
|
||||||
ASTNodeFactory nodeFactory(*this);
|
ASTNodeFactory nodeFactory(*this);
|
||||||
vector<ASTPointer<VariableDeclaration>> parameters;
|
vector<ASTPointer<VariableDeclaration>> parameters;
|
||||||
|
VarDeclParserOptions options;
|
||||||
|
options.allowIndexed = _allowIndexed;
|
||||||
expectToken(Token::LPAREN);
|
expectToken(Token::LPAREN);
|
||||||
if (!_allowEmpty || m_scanner->getCurrentToken() != Token::RPAREN)
|
if (!_allowEmpty || m_scanner->getCurrentToken() != Token::RPAREN)
|
||||||
{
|
{
|
||||||
bool const allowVar = false;
|
parameters.push_back(parseVariableDeclaration(options));
|
||||||
parameters.push_back(parseVariableDeclaration(allowVar));
|
|
||||||
while (m_scanner->getCurrentToken() != Token::RPAREN)
|
while (m_scanner->getCurrentToken() != Token::RPAREN)
|
||||||
{
|
{
|
||||||
expectToken(Token::COMMA);
|
expectToken(Token::COMMA);
|
||||||
parameters.push_back(parseVariableDeclaration(allowVar));
|
parameters.push_back(parseVariableDeclaration(options));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nodeFactory.markEndPosition();
|
nodeFactory.markEndPosition();
|
||||||
@ -510,8 +540,9 @@ ASTPointer<Statement> Parser::parseVarDefOrExprStmt()
|
|||||||
ASTPointer<VariableDefinition> Parser::parseVariableDefinition()
|
ASTPointer<VariableDefinition> Parser::parseVariableDefinition()
|
||||||
{
|
{
|
||||||
ASTNodeFactory nodeFactory(*this);
|
ASTNodeFactory nodeFactory(*this);
|
||||||
bool const allowVar = true;
|
VarDeclParserOptions options;
|
||||||
ASTPointer<VariableDeclaration> variable = parseVariableDeclaration(allowVar);
|
options.allowVar = true;
|
||||||
|
ASTPointer<VariableDeclaration> variable = parseVariableDeclaration(options);
|
||||||
ASTPointer<Expression> value;
|
ASTPointer<Expression> value;
|
||||||
if (m_scanner->getCurrentToken() == Token::ASSIGN)
|
if (m_scanner->getCurrentToken() == Token::ASSIGN)
|
||||||
{
|
{
|
||||||
|
13
Parser.h
13
Parser.h
@ -45,6 +45,14 @@ private:
|
|||||||
/// End position of the current token
|
/// End position of the current token
|
||||||
int getEndPosition() const;
|
int getEndPosition() const;
|
||||||
|
|
||||||
|
struct VarDeclParserOptions {
|
||||||
|
VarDeclParserOptions() {}
|
||||||
|
bool allowVar = false;
|
||||||
|
bool isPublic = false;
|
||||||
|
bool isStateVariable = false;
|
||||||
|
bool allowIndexed = false;
|
||||||
|
};
|
||||||
|
|
||||||
///@{
|
///@{
|
||||||
///@name Parsing functions for the AST nodes
|
///@name Parsing functions for the AST nodes
|
||||||
ASTPointer<ImportDirective> parseImportDirective();
|
ASTPointer<ImportDirective> parseImportDirective();
|
||||||
@ -52,13 +60,14 @@ private:
|
|||||||
ASTPointer<InheritanceSpecifier> parseInheritanceSpecifier();
|
ASTPointer<InheritanceSpecifier> parseInheritanceSpecifier();
|
||||||
ASTPointer<FunctionDefinition> parseFunctionDefinition(bool _isPublic, ASTString const* _contractName);
|
ASTPointer<FunctionDefinition> parseFunctionDefinition(bool _isPublic, ASTString const* _contractName);
|
||||||
ASTPointer<StructDefinition> parseStructDefinition();
|
ASTPointer<StructDefinition> parseStructDefinition();
|
||||||
ASTPointer<VariableDeclaration> parseVariableDeclaration(bool _allowVar, bool _isPublic = false, bool _isStateVar = false);
|
ASTPointer<VariableDeclaration> parseVariableDeclaration(VarDeclParserOptions const& _options = VarDeclParserOptions());
|
||||||
ASTPointer<ModifierDefinition> parseModifierDefinition();
|
ASTPointer<ModifierDefinition> parseModifierDefinition();
|
||||||
|
ASTPointer<EventDefinition> parseEventDefinition();
|
||||||
ASTPointer<ModifierInvocation> parseModifierInvocation();
|
ASTPointer<ModifierInvocation> parseModifierInvocation();
|
||||||
ASTPointer<Identifier> parseIdentifier();
|
ASTPointer<Identifier> parseIdentifier();
|
||||||
ASTPointer<TypeName> parseTypeName(bool _allowVar);
|
ASTPointer<TypeName> parseTypeName(bool _allowVar);
|
||||||
ASTPointer<Mapping> parseMapping();
|
ASTPointer<Mapping> parseMapping();
|
||||||
ASTPointer<ParameterList> parseParameterList(bool _allowEmpty = true);
|
ASTPointer<ParameterList> parseParameterList(bool _allowEmpty = true, bool _allowIndexed = false);
|
||||||
ASTPointer<Block> parseBlock();
|
ASTPointer<Block> parseBlock();
|
||||||
ASTPointer<Statement> parseStatement();
|
ASTPointer<Statement> parseStatement();
|
||||||
ASTPointer<IfStatement> parseIfStatement();
|
ASTPointer<IfStatement> parseIfStatement();
|
||||||
|
2
Token.h
2
Token.h
@ -153,7 +153,9 @@ namespace solidity
|
|||||||
K(DEFAULT, "default", 0) \
|
K(DEFAULT, "default", 0) \
|
||||||
K(DO, "do", 0) \
|
K(DO, "do", 0) \
|
||||||
K(ELSE, "else", 0) \
|
K(ELSE, "else", 0) \
|
||||||
|
K(EVENT, "event", 0) \
|
||||||
K(IS, "is", 0) \
|
K(IS, "is", 0) \
|
||||||
|
K(INDEXED, "indexed", 0) \
|
||||||
K(FOR, "for", 0) \
|
K(FOR, "for", 0) \
|
||||||
K(FUNCTION, "function", 0) \
|
K(FUNCTION, "function", 0) \
|
||||||
K(IF, "if", 0) \
|
K(IF, "if", 0) \
|
||||||
|
16
Types.cpp
16
Types.cpp
@ -633,6 +633,22 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl):
|
|||||||
swap(retParamNames, m_returnParameterNames);
|
swap(retParamNames, m_returnParameterNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FunctionType::FunctionType(const EventDefinition& _event):
|
||||||
|
m_location(Location::EVENT), m_declaration(&_event)
|
||||||
|
{
|
||||||
|
TypePointers params;
|
||||||
|
vector<string> paramNames;
|
||||||
|
params.reserve(_event.getParameters().size());
|
||||||
|
paramNames.reserve(_event.getParameters().size());
|
||||||
|
for (ASTPointer<VariableDeclaration> const& var: _event.getParameters())
|
||||||
|
{
|
||||||
|
paramNames.push_back(var->getName());
|
||||||
|
params.push_back(var->getType());
|
||||||
|
}
|
||||||
|
swap(params, m_parameterTypes);
|
||||||
|
swap(paramNames, m_parameterNames);
|
||||||
|
}
|
||||||
|
|
||||||
bool FunctionType::operator==(Type const& _other) const
|
bool FunctionType::operator==(Type const& _other) const
|
||||||
{
|
{
|
||||||
if (_other.getCategory() != getCategory())
|
if (_other.getCategory() != getCategory())
|
||||||
|
4
Types.h
4
Types.h
@ -350,16 +350,18 @@ public:
|
|||||||
/// INTERNAL: jump tag, EXTERNAL: contract address + function identifier,
|
/// INTERNAL: jump tag, EXTERNAL: contract address + function identifier,
|
||||||
/// BARE: contract address (non-abi contract call)
|
/// BARE: contract address (non-abi contract call)
|
||||||
/// OTHERS: special virtual function, nothing on the stack
|
/// OTHERS: special virtual function, nothing on the stack
|
||||||
|
/// @todo This documentation is outdated, and Location should rather be named "Type"
|
||||||
enum class Location { INTERNAL, EXTERNAL, CREATION, SEND,
|
enum class Location { INTERNAL, EXTERNAL, CREATION, SEND,
|
||||||
SHA3, SUICIDE,
|
SHA3, SUICIDE,
|
||||||
ECRECOVER, SHA256, RIPEMD160,
|
ECRECOVER, SHA256, RIPEMD160,
|
||||||
LOG0, LOG1, LOG2, LOG3, LOG4,
|
LOG0, LOG1, LOG2, LOG3, LOG4, EVENT,
|
||||||
SET_GAS, SET_VALUE, BLOCKHASH,
|
SET_GAS, SET_VALUE, BLOCKHASH,
|
||||||
BARE };
|
BARE };
|
||||||
|
|
||||||
virtual Category getCategory() const override { return Category::FUNCTION; }
|
virtual Category getCategory() const override { return Category::FUNCTION; }
|
||||||
explicit FunctionType(FunctionDefinition const& _function, bool _isInternal = true);
|
explicit FunctionType(FunctionDefinition const& _function, bool _isInternal = true);
|
||||||
explicit FunctionType(VariableDeclaration const& _varDecl);
|
explicit FunctionType(VariableDeclaration const& _varDecl);
|
||||||
|
explicit FunctionType(EventDefinition const& _event);
|
||||||
FunctionType(strings const& _parameterTypes, strings const& _returnParameterTypes,
|
FunctionType(strings const& _parameterTypes, strings const& _returnParameterTypes,
|
||||||
Location _location = Location::INTERNAL):
|
Location _location = Location::INTERNAL):
|
||||||
FunctionType(parseElementaryTypeVector(_parameterTypes), parseElementaryTypeVector(_returnParameterTypes),
|
FunctionType(parseElementaryTypeVector(_parameterTypes), parseElementaryTypeVector(_returnParameterTypes),
|
||||||
|
Loading…
Reference in New Issue
Block a user