mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #6660 from ethereum/shortCircuiting
Short circuiting
This commit is contained in:
commit
133fd18223
@ -131,6 +131,21 @@ bool IRGeneratorForStatements::visit(Assignment const& _assignment)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IRGeneratorForStatements::visit(TupleExpression const& _tuple)
|
||||
{
|
||||
if (_tuple.isInlineArray())
|
||||
solUnimplementedAssert(false, "");
|
||||
else
|
||||
{
|
||||
solUnimplementedAssert(!_tuple.annotation().lValueRequested, "");
|
||||
solUnimplementedAssert(_tuple.components().size() == 1, "");
|
||||
solAssert(_tuple.components().front(), "");
|
||||
_tuple.components().front()->accept(*this);
|
||||
defineExpression(_tuple) << m_context.variable(*_tuple.components().front()) << "\n";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IRGeneratorForStatements::visit(ForStatement const& _for)
|
||||
{
|
||||
m_code << "for {\n";
|
||||
@ -199,16 +214,23 @@ void IRGeneratorForStatements::endVisit(UnaryOperation const& _unaryOperation)
|
||||
solUnimplementedAssert(false, "");
|
||||
}
|
||||
|
||||
void IRGeneratorForStatements::endVisit(BinaryOperation const& _binOp)
|
||||
bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp)
|
||||
{
|
||||
solAssert(!!_binOp.annotation().commonType, "");
|
||||
TypePointer commonType = _binOp.annotation().commonType;
|
||||
langutil::Token op = _binOp.getOperator();
|
||||
|
||||
if (op == Token::And || op == Token::Or)
|
||||
// special case: short-circuiting
|
||||
solUnimplementedAssert(false, "");
|
||||
else if (commonType->category() == Type::Category::RationalNumber)
|
||||
{
|
||||
// This can short-circuit!
|
||||
appendAndOrOperatorCode(_binOp);
|
||||
return false;
|
||||
}
|
||||
|
||||
_binOp.leftExpression().accept(*this);
|
||||
_binOp.rightExpression().accept(*this);
|
||||
|
||||
if (commonType->category() == Type::Category::RationalNumber)
|
||||
defineExpression(_binOp) <<
|
||||
toCompactHexWithPrefix(commonType->literalValue(nullptr)) <<
|
||||
"\n";
|
||||
@ -259,6 +281,7 @@ void IRGeneratorForStatements::endVisit(BinaryOperation const& _binOp)
|
||||
else
|
||||
solUnimplementedAssert(false, "");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
@ -429,6 +452,24 @@ ostream& IRGeneratorForStatements::defineExpression(Expression const& _expressio
|
||||
return m_code << "let " << m_context.variable(_expression) << " := ";
|
||||
}
|
||||
|
||||
void IRGeneratorForStatements::appendAndOrOperatorCode(BinaryOperation const& _binOp)
|
||||
{
|
||||
langutil::Token const op = _binOp.getOperator();
|
||||
solAssert(op == Token::Or || op == Token::And, "");
|
||||
|
||||
_binOp.leftExpression().accept(*this);
|
||||
|
||||
string value = m_context.variable(_binOp);
|
||||
m_code << "let " << value << " := " << m_context.variable(_binOp.leftExpression()) << "\n";
|
||||
if (op == Token::Or)
|
||||
m_code << "if iszero(" << value << ") {\n";
|
||||
else
|
||||
m_code << "if " << value << " {\n";
|
||||
_binOp.rightExpression().accept(*this);
|
||||
m_code << value << " := " + m_context.variable(_binOp.rightExpression()) << "\n";
|
||||
m_code << "}\n";
|
||||
}
|
||||
|
||||
void IRGeneratorForStatements::setLValue(Expression const& _expression, unique_ptr<IRLValue> _lvalue)
|
||||
{
|
||||
solAssert(!m_currentLValue, "");
|
||||
|
@ -47,12 +47,13 @@ public:
|
||||
|
||||
void endVisit(VariableDeclarationStatement const& _variableDeclaration) override;
|
||||
bool visit(Assignment const& _assignment) override;
|
||||
bool visit(TupleExpression const& _tuple) override;
|
||||
bool visit(ForStatement const& _forStatement) override;
|
||||
bool visit(Continue const& _continueStatement) override;
|
||||
bool visit(Break const& _breakStatement) override;
|
||||
void endVisit(Return const& _return) override;
|
||||
void endVisit(UnaryOperation const& _unaryOperation) override;
|
||||
void endVisit(BinaryOperation const& _binOp) override;
|
||||
bool visit(BinaryOperation const& _binOp) override;
|
||||
void endVisit(FunctionCall const& _funCall) override;
|
||||
bool visit(InlineAssembly const& _inlineAsm) override;
|
||||
bool visit(Identifier const& _identifier) override;
|
||||
@ -64,6 +65,8 @@ private:
|
||||
std::string expressionAsType(Expression const& _expression, Type const& _to);
|
||||
std::ostream& defineExpression(Expression const& _expression);
|
||||
|
||||
void appendAndOrOperatorCode(BinaryOperation const& _binOp);
|
||||
|
||||
void setLValue(Expression const& _expression, std::unique_ptr<IRLValue> _lvalue);
|
||||
|
||||
static Type const& type(Expression const& _expression);
|
||||
|
17
test/libsolidity/semanticTests/viaYul/short_circuit.sol
Normal file
17
test/libsolidity/semanticTests/viaYul/short_circuit.sol
Normal file
@ -0,0 +1,17 @@
|
||||
contract C {
|
||||
function or(uint x) public returns (bool t, uint y) {
|
||||
t = (x == 0 || ((x = 8) > 0));
|
||||
y = x;
|
||||
}
|
||||
function and(uint x) public returns (bool t, uint y) {
|
||||
t = (x == 0 && ((x = 8) > 0));
|
||||
y = x;
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: true
|
||||
// ----
|
||||
// or(uint256): 0 -> true, 0
|
||||
// and(uint256): 0 -> true, 8
|
||||
// or(uint256): 1 -> true, 8
|
||||
// and(uint256): 1 -> false, 1
|
Loading…
Reference in New Issue
Block a user