mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Const AST visitor for the compiler.
This commit is contained in:
parent
41b8d7b7f1
commit
c78c330634
6
AST.h
6
AST.h
@ -245,10 +245,10 @@ public:
|
|||||||
bool isPublic() const { return m_isPublic; }
|
bool isPublic() const { return m_isPublic; }
|
||||||
bool isDeclaredConst() const { return m_isDeclaredConst; }
|
bool isDeclaredConst() const { return m_isDeclaredConst; }
|
||||||
std::vector<ASTPointer<VariableDeclaration>> const& getParameters() const { return m_parameters->getParameters(); }
|
std::vector<ASTPointer<VariableDeclaration>> const& getParameters() const { return m_parameters->getParameters(); }
|
||||||
ParameterList& getParameterList() { return *m_parameters; }
|
ParameterList const& getParameterList() const { return *m_parameters; }
|
||||||
std::vector<ASTPointer<VariableDeclaration>> const& getReturnParameters() const { return m_returnParameters->getParameters(); }
|
std::vector<ASTPointer<VariableDeclaration>> const& getReturnParameters() const { return m_returnParameters->getParameters(); }
|
||||||
ASTPointer<ParameterList> const& getReturnParameterList() const { return m_returnParameters; }
|
ASTPointer<ParameterList> const& getReturnParameterList() const { return m_returnParameters; }
|
||||||
Block& getBody() { return *m_body; }
|
Block const& getBody() const { return *m_body; }
|
||||||
/// @return A shared pointer of an ASTString.
|
/// @return A shared pointer of an ASTString.
|
||||||
/// Can contain a nullptr in which case indicates absence of documentation
|
/// Can contain a nullptr in which case indicates absence of documentation
|
||||||
ASTPointer<ASTString> const& getDocumentation() const { return m_documentation; }
|
ASTPointer<ASTString> const& getDocumentation() const { return m_documentation; }
|
||||||
@ -796,7 +796,7 @@ public:
|
|||||||
ASTString const& getName() const { return *m_name; }
|
ASTString const& getName() const { return *m_name; }
|
||||||
|
|
||||||
void setReferencedDeclaration(Declaration& _referencedDeclaration) { m_referencedDeclaration = &_referencedDeclaration; }
|
void setReferencedDeclaration(Declaration& _referencedDeclaration) { m_referencedDeclaration = &_referencedDeclaration; }
|
||||||
Declaration* getReferencedDeclaration() { return m_referencedDeclaration; }
|
Declaration const* getReferencedDeclaration() const { return m_referencedDeclaration; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ASTPointer<ASTString> m_name;
|
ASTPointer<ASTString> m_name;
|
||||||
|
18
Compiler.cpp
18
Compiler.cpp
@ -32,7 +32,7 @@ using namespace std;
|
|||||||
namespace dev {
|
namespace dev {
|
||||||
namespace solidity {
|
namespace solidity {
|
||||||
|
|
||||||
void Compiler::compileContract(ContractDefinition& _contract, vector<MagicVariableDeclaration const*> const& _magicGlobals)
|
void Compiler::compileContract(ContractDefinition const& _contract, vector<MagicVariableDeclaration const*> const& _magicGlobals)
|
||||||
{
|
{
|
||||||
m_context = CompilerContext(); // clear it just in case
|
m_context = CompilerContext(); // clear it just in case
|
||||||
|
|
||||||
@ -179,7 +179,7 @@ void Compiler::registerStateVariables(ContractDefinition const& _contract)
|
|||||||
m_context.addStateVariable(*variable);
|
m_context.addStateVariable(*variable);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Compiler::visit(FunctionDefinition& _function)
|
bool Compiler::visit(FunctionDefinition const& _function)
|
||||||
{
|
{
|
||||||
//@todo to simplify this, the calling convention could by changed such that
|
//@todo to simplify this, the calling convention could by changed such that
|
||||||
// caller puts: [retarg0] ... [retargm] [return address] [arg0] ... [argn]
|
// caller puts: [retarg0] ... [retargm] [return address] [arg0] ... [argn]
|
||||||
@ -240,7 +240,7 @@ bool Compiler::visit(FunctionDefinition& _function)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Compiler::visit(IfStatement& _ifStatement)
|
bool Compiler::visit(IfStatement const& _ifStatement)
|
||||||
{
|
{
|
||||||
ExpressionCompiler::compileExpression(m_context, _ifStatement.getCondition());
|
ExpressionCompiler::compileExpression(m_context, _ifStatement.getCondition());
|
||||||
eth::AssemblyItem trueTag = m_context.appendConditionalJump();
|
eth::AssemblyItem trueTag = m_context.appendConditionalJump();
|
||||||
@ -253,7 +253,7 @@ bool Compiler::visit(IfStatement& _ifStatement)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Compiler::visit(WhileStatement& _whileStatement)
|
bool Compiler::visit(WhileStatement const& _whileStatement)
|
||||||
{
|
{
|
||||||
eth::AssemblyItem loopStart = m_context.newTag();
|
eth::AssemblyItem loopStart = m_context.newTag();
|
||||||
eth::AssemblyItem loopEnd = m_context.newTag();
|
eth::AssemblyItem loopEnd = m_context.newTag();
|
||||||
@ -275,21 +275,21 @@ bool Compiler::visit(WhileStatement& _whileStatement)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Compiler::visit(Continue&)
|
bool Compiler::visit(Continue const&)
|
||||||
{
|
{
|
||||||
if (!m_continueTags.empty())
|
if (!m_continueTags.empty())
|
||||||
m_context.appendJumpTo(m_continueTags.back());
|
m_context.appendJumpTo(m_continueTags.back());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Compiler::visit(Break&)
|
bool Compiler::visit(Break const&)
|
||||||
{
|
{
|
||||||
if (!m_breakTags.empty())
|
if (!m_breakTags.empty())
|
||||||
m_context.appendJumpTo(m_breakTags.back());
|
m_context.appendJumpTo(m_breakTags.back());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Compiler::visit(Return& _return)
|
bool Compiler::visit(Return const& _return)
|
||||||
{
|
{
|
||||||
//@todo modifications are needed to make this work with functions returning multiple values
|
//@todo modifications are needed to make this work with functions returning multiple values
|
||||||
if (Expression* expression = _return.getExpression())
|
if (Expression* expression = _return.getExpression())
|
||||||
@ -305,7 +305,7 @@ bool Compiler::visit(Return& _return)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Compiler::visit(VariableDefinition& _variableDefinition)
|
bool Compiler::visit(VariableDefinition const& _variableDefinition)
|
||||||
{
|
{
|
||||||
if (Expression* expression = _variableDefinition.getExpression())
|
if (Expression* expression = _variableDefinition.getExpression())
|
||||||
{
|
{
|
||||||
@ -320,7 +320,7 @@ bool Compiler::visit(VariableDefinition& _variableDefinition)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Compiler::visit(ExpressionStatement& _expressionStatement)
|
bool Compiler::visit(ExpressionStatement const& _expressionStatement)
|
||||||
{
|
{
|
||||||
Expression& expression = _expressionStatement.getExpression();
|
Expression& expression = _expressionStatement.getExpression();
|
||||||
ExpressionCompiler::compileExpression(m_context, expression);
|
ExpressionCompiler::compileExpression(m_context, expression);
|
||||||
|
18
Compiler.h
18
Compiler.h
@ -32,7 +32,7 @@ class Compiler: private ASTVisitor
|
|||||||
public:
|
public:
|
||||||
Compiler(): m_returnTag(m_context.newTag()) {}
|
Compiler(): m_returnTag(m_context.newTag()) {}
|
||||||
|
|
||||||
void compileContract(ContractDefinition& _contract, std::vector<MagicVariableDeclaration const*> const& _magicGlobals);
|
void compileContract(ContractDefinition const& _contract, std::vector<MagicVariableDeclaration const*> const& _magicGlobals);
|
||||||
bytes getAssembledBytecode(bool _optimize = false) { return m_context.getAssembledBytecode(_optimize); }
|
bytes getAssembledBytecode(bool _optimize = false) { return m_context.getAssembledBytecode(_optimize); }
|
||||||
void streamAssembly(std::ostream& _stream) const { m_context.streamAssembly(_stream); }
|
void streamAssembly(std::ostream& _stream) const { m_context.streamAssembly(_stream); }
|
||||||
|
|
||||||
@ -48,14 +48,14 @@ private:
|
|||||||
|
|
||||||
void registerStateVariables(ContractDefinition const& _contract);
|
void registerStateVariables(ContractDefinition const& _contract);
|
||||||
|
|
||||||
virtual bool visit(FunctionDefinition& _function) override;
|
virtual bool visit(FunctionDefinition const& _function) override;
|
||||||
virtual bool visit(IfStatement& _ifStatement) override;
|
virtual bool visit(IfStatement const& _ifStatement) override;
|
||||||
virtual bool visit(WhileStatement& _whileStatement) override;
|
virtual bool visit(WhileStatement const& _whileStatement) override;
|
||||||
virtual bool visit(Continue& _continue) override;
|
virtual bool visit(Continue const& _continue) override;
|
||||||
virtual bool visit(Break& _break) override;
|
virtual bool visit(Break const& _break) override;
|
||||||
virtual bool visit(Return& _return) override;
|
virtual bool visit(Return const& _return) override;
|
||||||
virtual bool visit(VariableDefinition& _variableDefinition) override;
|
virtual bool visit(VariableDefinition const& _variableDefinition) override;
|
||||||
virtual bool visit(ExpressionStatement& _expressionStatement) override;
|
virtual bool visit(ExpressionStatement const& _expressionStatement) override;
|
||||||
|
|
||||||
|
|
||||||
CompilerContext m_context;
|
CompilerContext m_context;
|
||||||
|
@ -32,7 +32,7 @@ using namespace std;
|
|||||||
namespace dev {
|
namespace dev {
|
||||||
namespace solidity {
|
namespace solidity {
|
||||||
|
|
||||||
void ExpressionCompiler::compileExpression(CompilerContext& _context, Expression& _expression)
|
void ExpressionCompiler::compileExpression(CompilerContext& _context, Expression const& _expression)
|
||||||
{
|
{
|
||||||
ExpressionCompiler compiler(_context);
|
ExpressionCompiler compiler(_context);
|
||||||
_expression.accept(compiler);
|
_expression.accept(compiler);
|
||||||
@ -45,7 +45,7 @@ void ExpressionCompiler::appendTypeConversion(CompilerContext& _context,
|
|||||||
compiler.appendTypeConversion(_typeOnStack, _targetType);
|
compiler.appendTypeConversion(_typeOnStack, _targetType);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExpressionCompiler::visit(Assignment& _assignment)
|
bool ExpressionCompiler::visit(Assignment const& _assignment)
|
||||||
{
|
{
|
||||||
_assignment.getRightHandSide().accept(*this);
|
_assignment.getRightHandSide().accept(*this);
|
||||||
appendTypeConversion(*_assignment.getRightHandSide().getType(), *_assignment.getType());
|
appendTypeConversion(*_assignment.getRightHandSide().getType(), *_assignment.getType());
|
||||||
@ -67,7 +67,7 @@ bool ExpressionCompiler::visit(Assignment& _assignment)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExpressionCompiler::endVisit(UnaryOperation& _unaryOperation)
|
void ExpressionCompiler::endVisit(UnaryOperation const& _unaryOperation)
|
||||||
{
|
{
|
||||||
//@todo type checking and creating code for an operator should be in the same place:
|
//@todo type checking and creating code for an operator should be in the same place:
|
||||||
// the operator should know how to convert itself and to which types it applies, so
|
// the operator should know how to convert itself and to which types it applies, so
|
||||||
@ -128,10 +128,10 @@ void ExpressionCompiler::endVisit(UnaryOperation& _unaryOperation)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExpressionCompiler::visit(BinaryOperation& _binaryOperation)
|
bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation)
|
||||||
{
|
{
|
||||||
Expression& leftExpression = _binaryOperation.getLeftExpression();
|
Expression const& leftExpression = _binaryOperation.getLeftExpression();
|
||||||
Expression& rightExpression = _binaryOperation.getRightExpression();
|
Expression const& rightExpression = _binaryOperation.getRightExpression();
|
||||||
Type const& commonType = _binaryOperation.getCommonType();
|
Type const& commonType = _binaryOperation.getCommonType();
|
||||||
Token::Value const op = _binaryOperation.getOperator();
|
Token::Value const op = _binaryOperation.getOperator();
|
||||||
|
|
||||||
@ -158,7 +158,7 @@ bool ExpressionCompiler::visit(BinaryOperation& _binaryOperation)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExpressionCompiler::visit(FunctionCall& _functionCall)
|
bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||||
{
|
{
|
||||||
using Location = FunctionType::Location;
|
using Location = FunctionType::Location;
|
||||||
if (_functionCall.isTypeConversion())
|
if (_functionCall.isTypeConversion())
|
||||||
@ -166,7 +166,7 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall)
|
|||||||
//@todo struct construction
|
//@todo struct construction
|
||||||
if (asserts(_functionCall.getArguments().size() == 1))
|
if (asserts(_functionCall.getArguments().size() == 1))
|
||||||
BOOST_THROW_EXCEPTION(InternalCompilerError());
|
BOOST_THROW_EXCEPTION(InternalCompilerError());
|
||||||
Expression& firstArgument = *_functionCall.getArguments().front();
|
Expression const& firstArgument = *_functionCall.getArguments().front();
|
||||||
firstArgument.accept(*this);
|
firstArgument.accept(*this);
|
||||||
if (firstArgument.getType()->getCategory() == Type::Category::CONTRACT &&
|
if (firstArgument.getType()->getCategory() == Type::Category::CONTRACT &&
|
||||||
_functionCall.getType()->getCategory() == Type::Category::INTEGER)
|
_functionCall.getType()->getCategory() == Type::Category::INTEGER)
|
||||||
@ -268,7 +268,7 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExpressionCompiler::endVisit(MemberAccess& _memberAccess)
|
void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess)
|
||||||
{
|
{
|
||||||
ASTString const& member = _memberAccess.getMemberName();
|
ASTString const& member = _memberAccess.getMemberName();
|
||||||
switch (_memberAccess.getExpression().getType()->getCategory())
|
switch (_memberAccess.getExpression().getType()->getCategory())
|
||||||
@ -332,7 +332,7 @@ void ExpressionCompiler::endVisit(MemberAccess& _memberAccess)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExpressionCompiler::visit(IndexAccess& _indexAccess)
|
bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
|
||||||
{
|
{
|
||||||
_indexAccess.getBaseExpression().accept(*this);
|
_indexAccess.getBaseExpression().accept(*this);
|
||||||
_indexAccess.getIndexExpression().accept(*this);
|
_indexAccess.getIndexExpression().accept(*this);
|
||||||
@ -349,30 +349,30 @@ bool ExpressionCompiler::visit(IndexAccess& _indexAccess)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExpressionCompiler::endVisit(Identifier& _identifier)
|
void ExpressionCompiler::endVisit(Identifier const& _identifier)
|
||||||
{
|
{
|
||||||
Declaration* declaration = _identifier.getReferencedDeclaration();
|
Declaration const* declaration = _identifier.getReferencedDeclaration();
|
||||||
if (MagicVariableDeclaration* magicVar = dynamic_cast<MagicVariableDeclaration*>(declaration))
|
if (MagicVariableDeclaration const* magicVar = dynamic_cast<MagicVariableDeclaration const*>(declaration))
|
||||||
{
|
{
|
||||||
if (magicVar->getType()->getCategory() == Type::Category::CONTRACT) // must be "this"
|
if (magicVar->getType()->getCategory() == Type::Category::CONTRACT) // must be "this"
|
||||||
m_context << eth::Instruction::ADDRESS;
|
m_context << eth::Instruction::ADDRESS;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (FunctionDefinition* functionDef = dynamic_cast<FunctionDefinition*>(declaration))
|
if (FunctionDefinition const* functionDef = dynamic_cast<FunctionDefinition const*>(declaration))
|
||||||
{
|
{
|
||||||
m_context << m_context.getFunctionEntryLabel(*functionDef).pushTag();
|
m_context << m_context.getFunctionEntryLabel(*functionDef).pushTag();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (/*VariableDeclaration* varDef = */dynamic_cast<VariableDeclaration*>(declaration))
|
if (dynamic_cast<VariableDeclaration const*>(declaration))
|
||||||
{
|
{
|
||||||
m_currentLValue.fromIdentifier(_identifier, *_identifier.getReferencedDeclaration());
|
m_currentLValue.fromIdentifier(_identifier, *declaration);
|
||||||
m_currentLValue.retrieveValueIfLValueNotRequested(_identifier);
|
m_currentLValue.retrieveValueIfLValueNotRequested(_identifier);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
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."));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExpressionCompiler::endVisit(Literal& _literal)
|
void ExpressionCompiler::endVisit(Literal const& _literal)
|
||||||
{
|
{
|
||||||
switch (_literal.getType()->getCategory())
|
switch (_literal.getType()->getCategory())
|
||||||
{
|
{
|
||||||
@ -385,7 +385,7 @@ void ExpressionCompiler::endVisit(Literal& _literal)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExpressionCompiler::appendAndOrOperatorCode(BinaryOperation& _binaryOperation)
|
void ExpressionCompiler::appendAndOrOperatorCode(BinaryOperation const& _binaryOperation)
|
||||||
{
|
{
|
||||||
Token::Value const op = _binaryOperation.getOperator();
|
Token::Value const op = _binaryOperation.getOperator();
|
||||||
if (asserts(op == Token::OR || op == Token::AND))
|
if (asserts(op == Token::OR || op == Token::AND))
|
||||||
|
@ -44,7 +44,7 @@ class ExpressionCompiler: private ASTVisitor
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Compile the given @a _expression into the @a _context.
|
/// Compile the given @a _expression into the @a _context.
|
||||||
static void compileExpression(CompilerContext& _context, Expression& _expression);
|
static void compileExpression(CompilerContext& _context, Expression const& _expression);
|
||||||
|
|
||||||
/// Appends code to remove dirty higher order bits in case of an implicit promotion to a wider type.
|
/// Appends code to remove dirty higher order bits in case of an implicit promotion to a wider type.
|
||||||
static void appendTypeConversion(CompilerContext& _context, Type const& _typeOnStack, Type const& _targetType);
|
static void appendTypeConversion(CompilerContext& _context, Type const& _typeOnStack, Type const& _targetType);
|
||||||
@ -53,18 +53,18 @@ private:
|
|||||||
ExpressionCompiler(CompilerContext& _compilerContext):
|
ExpressionCompiler(CompilerContext& _compilerContext):
|
||||||
m_context(_compilerContext), m_currentLValue(m_context) {}
|
m_context(_compilerContext), m_currentLValue(m_context) {}
|
||||||
|
|
||||||
virtual bool visit(Assignment& _assignment) override;
|
virtual bool visit(Assignment const& _assignment) override;
|
||||||
virtual void endVisit(UnaryOperation& _unaryOperation) override;
|
virtual void endVisit(UnaryOperation const& _unaryOperation) override;
|
||||||
virtual bool visit(BinaryOperation& _binaryOperation) override;
|
virtual bool visit(BinaryOperation const& _binaryOperation) override;
|
||||||
virtual bool visit(FunctionCall& _functionCall) override;
|
virtual bool visit(FunctionCall const& _functionCall) override;
|
||||||
virtual void endVisit(MemberAccess& _memberAccess) override;
|
virtual void endVisit(MemberAccess const& _memberAccess) override;
|
||||||
virtual bool visit(IndexAccess& _indexAccess) override;
|
virtual bool visit(IndexAccess const& _indexAccess) override;
|
||||||
virtual void endVisit(Identifier& _identifier) override;
|
virtual void endVisit(Identifier const& _identifier) override;
|
||||||
virtual void endVisit(Literal& _literal) override;
|
virtual void endVisit(Literal const& _literal) override;
|
||||||
|
|
||||||
///@{
|
///@{
|
||||||
///@name Append code for various operator types
|
///@name Append code for various operator types
|
||||||
void appendAndOrOperatorCode(BinaryOperation& _binaryOperation);
|
void appendAndOrOperatorCode(BinaryOperation const& _binaryOperation);
|
||||||
void appendCompareOperatorCode(Token::Value _operator, Type const& _type);
|
void appendCompareOperatorCode(Token::Value _operator, Type const& _type);
|
||||||
void appendOrdinaryBinaryOperatorCode(Token::Value _operator, Type const& _type);
|
void appendOrdinaryBinaryOperatorCode(Token::Value _operator, Type const& _type);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user