#pragma once
#include <libsolidity/ast/ASTVisitor.h>
#include <libsolidity/codegen/LValue.h>
#include <libsolidity/interface/DebugSettings.h>
#include <liblangutil/Exceptions.h>
#include <liblangutil/SourceLocation.h>
#include <libsolutil/Common.h>
#include <functional>
#include <memory>
namespace solidity::evmasm
{
class AssemblyItem; }
namespace solidity::frontend
{
class CompilerContext;
class CompilerUtils;
class Type;
class IntegerType;
class ArrayType;
class ExpressionCompiler: private ASTConstVisitor
{
public:
ExpressionCompiler(
CompilerContext& _compilerContext,
bool _optimiseOrderLiterals
):
m_optimiseOrderLiterals(_optimiseOrderLiterals),
m_context(_compilerContext)
{}
void compile(Expression const& _expression);
void appendStateVariableInitialization(VariableDeclaration const& _varDecl);
void appendStateVariableAccessor(VariableDeclaration const& _varDecl);
void appendConstStateVariableAccessor(VariableDeclaration const& _varDecl);
private:
bool visit(Conditional const& _condition) override;
bool visit(Assignment const& _assignment) override;
bool visit(TupleExpression const& _tuple) override;
bool visit(UnaryOperation const& _unaryOperation) override;
bool visit(BinaryOperation const& _binaryOperation) override;
bool visit(FunctionCall const& _functionCall) override;
bool visit(FunctionCallOptions const& _functionCallOptions) override;
bool visit(NewExpression const& _newExpression) override;
bool visit(MemberAccess const& _memberAccess) override;
bool visit(IndexAccess const& _indexAccess) override;
bool visit(IndexRangeAccess const& _indexAccess) override;
void endVisit(Identifier const& _identifier) override;
void endVisit(Literal const& _literal) override;
void appendAndOrOperatorCode(BinaryOperation const& _binaryOperation);
void appendCompareOperatorCode(Token _operator, Type const& _type);
void appendOrdinaryBinaryOperatorCode(Token _operator, Type const& _type);
void appendArithmeticOperatorCode(Token _operator, Type const& _type);
void appendBitOperatorCode(Token _operator);
void appendShiftOperatorCode(Token _operator, Type const& _valueType, Type const& _shiftAmountType);
void appendExpOperatorCode(Type const& _valueType, Type const& _exponentType);
void appendExternalFunctionCall(
FunctionType const& _functionType,
std::vector<ASTPointer<Expression const>> const& _arguments,
bool _tryCall
);
void appendExpressionCopyToMemory(Type const& _expectedType, Expression const& _expression);
void appendVariable(VariableDeclaration const& _variable, Expression const& _expression);
void setLValueFromDeclaration(Declaration const& _declaration, Expression const& _expression);
void setLValueToStorageItem(Expression const& _expression);
template <class LValueType, class... Arguments>
void setLValue(Expression const& _expression, Arguments const&... _arguments);
static bool cleanupNeededForOp(Type::Category _type, Token _op, Arithmetic _arithmetic);
void acceptAndConvert(Expression const& _expression, Type const& _type, bool _cleanupNeeded = false);
CompilerUtils utils();
bool m_optimiseOrderLiterals;
CompilerContext& m_context;
std::unique_ptr<LValue> m_currentLValue;
};
template <class LValueType, class... Arguments>
void ExpressionCompiler::setLValue(Expression const& _expression, Arguments const&... _arguments)
{
solAssert(!m_currentLValue, "Current LValue not reset before trying to set new one.");
std::unique_ptr<LValueType> lvalue = std::make_unique<LValueType>(m_context, _arguments...);
if (_expression.annotation().willBeWrittenTo)
m_currentLValue = move(lvalue);
else
lvalue->retrieveValue(_expression.location(), true);
}
}