mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Logical operators.
This commit is contained in:
parent
055254847e
commit
c604481cef
@ -199,16 +199,23 @@ void IRGeneratorForStatements::endVisit(UnaryOperation const& _unaryOperation)
|
|||||||
solUnimplementedAssert(false, "");
|
solUnimplementedAssert(false, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRGeneratorForStatements::endVisit(BinaryOperation const& _binOp)
|
bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp)
|
||||||
{
|
{
|
||||||
solAssert(!!_binOp.annotation().commonType, "");
|
solAssert(!!_binOp.annotation().commonType, "");
|
||||||
TypePointer commonType = _binOp.annotation().commonType;
|
TypePointer commonType = _binOp.annotation().commonType;
|
||||||
langutil::Token op = _binOp.getOperator();
|
langutil::Token op = _binOp.getOperator();
|
||||||
|
|
||||||
if (op == Token::And || op == Token::Or)
|
if (op == Token::And || op == Token::Or)
|
||||||
// special case: short-circuiting
|
{
|
||||||
solUnimplementedAssert(false, "");
|
// This can short-circuit!
|
||||||
else if (commonType->category() == Type::Category::RationalNumber)
|
appendAndOrOperatorCode(_binOp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_binOp.leftExpression().accept(*this);
|
||||||
|
_binOp.rightExpression().accept(*this);
|
||||||
|
|
||||||
|
if (commonType->category() == Type::Category::RationalNumber)
|
||||||
defineExpression(_binOp) <<
|
defineExpression(_binOp) <<
|
||||||
toCompactHexWithPrefix(commonType->literalValue(nullptr)) <<
|
toCompactHexWithPrefix(commonType->literalValue(nullptr)) <<
|
||||||
"\n";
|
"\n";
|
||||||
@ -259,6 +266,7 @@ void IRGeneratorForStatements::endVisit(BinaryOperation const& _binOp)
|
|||||||
else
|
else
|
||||||
solUnimplementedAssert(false, "");
|
solUnimplementedAssert(false, "");
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||||
@ -429,6 +437,24 @@ ostream& IRGeneratorForStatements::defineExpression(Expression const& _expressio
|
|||||||
return m_code << "let " << m_context.variable(_expression) << " := ";
|
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)
|
void IRGeneratorForStatements::setLValue(Expression const& _expression, unique_ptr<IRLValue> _lvalue)
|
||||||
{
|
{
|
||||||
solAssert(!m_currentLValue, "");
|
solAssert(!m_currentLValue, "");
|
||||||
|
@ -52,7 +52,7 @@ public:
|
|||||||
bool visit(Break const& _breakStatement) override;
|
bool visit(Break const& _breakStatement) override;
|
||||||
void endVisit(Return const& _return) override;
|
void endVisit(Return const& _return) override;
|
||||||
void endVisit(UnaryOperation const& _unaryOperation) 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;
|
void endVisit(FunctionCall const& _funCall) override;
|
||||||
bool visit(InlineAssembly const& _inlineAsm) override;
|
bool visit(InlineAssembly const& _inlineAsm) override;
|
||||||
bool visit(Identifier const& _identifier) override;
|
bool visit(Identifier const& _identifier) override;
|
||||||
@ -64,6 +64,8 @@ private:
|
|||||||
std::string expressionAsType(Expression const& _expression, Type const& _to);
|
std::string expressionAsType(Expression const& _expression, Type const& _to);
|
||||||
std::ostream& defineExpression(Expression const& _expression);
|
std::ostream& defineExpression(Expression const& _expression);
|
||||||
|
|
||||||
|
void appendAndOrOperatorCode(BinaryOperation const& _binOp);
|
||||||
|
|
||||||
void setLValue(Expression const& _expression, std::unique_ptr<IRLValue> _lvalue);
|
void setLValue(Expression const& _expression, std::unique_ptr<IRLValue> _lvalue);
|
||||||
|
|
||||||
static Type const& type(Expression const& _expression);
|
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