aboutsummaryrefslogtreecommitdiffstats
path: root/ExpressionCompiler.cpp
diff options
context:
space:
mode:
authorChristian <c@ethdev.com>2014-12-19 18:31:17 +0800
committerChristian <c@ethdev.com>2015-01-09 22:16:09 +0800
commitbe623273f329b841bfda2a0aef91f091aa81b216 (patch)
tree6467f6a373d9f7156b78e44685aa08fafa7d8e3e /ExpressionCompiler.cpp
parentbe1e89da42e0ed9828dd2fb5939fd7bd48140be7 (diff)
downloaddexon-solidity-be623273f329b841bfda2a0aef91f091aa81b216.tar.gz
dexon-solidity-be623273f329b841bfda2a0aef91f091aa81b216.tar.zst
dexon-solidity-be623273f329b841bfda2a0aef91f091aa81b216.zip
Arbitrary precision integer constants.
Diffstat (limited to 'ExpressionCompiler.cpp')
-rw-r--r--ExpressionCompiler.cpp42
1 files changed, 30 insertions, 12 deletions
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp
index 7238a6a1..cf91a763 100644
--- a/ExpressionCompiler.cpp
+++ b/ExpressionCompiler.cpp
@@ -71,12 +71,20 @@ bool ExpressionCompiler::visit(Assignment const& _assignment)
return false;
}
-void ExpressionCompiler::endVisit(UnaryOperation const& _unaryOperation)
+bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation)
{
//@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
// put this code together with "Type::acceptsBinary/UnaryOperator" into a class that
// represents the operator
+ if (_unaryOperation.getType()->getCategory() == Type::Category::INTEGER_CONSTANT)
+ {
+ m_context << _unaryOperation.getType()->literalValue(nullptr);
+ return false;
+ }
+
+ _unaryOperation.getSubExpression().accept(*this);
+
switch (_unaryOperation.getOperator())
{
case Token::NOT: // !
@@ -128,6 +136,7 @@ void ExpressionCompiler::endVisit(UnaryOperation const& _unaryOperation)
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid unary operator: " +
string(Token::toString(_unaryOperation.getOperator()))));
}
+ return false;
}
bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation)
@@ -139,17 +148,19 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation)
if (op == Token::AND || op == Token::OR) // special case: short-circuiting
appendAndOrOperatorCode(_binaryOperation);
+ else if (commonType.getCategory() == Type::Category::INTEGER_CONSTANT)
+ m_context << commonType.literalValue(nullptr);
else
{
- bool cleanupNeeded = false;
- if (commonType.getCategory() == Type::Category::INTEGER)
- if (Token::isCompareOp(op) || op == Token::DIV || op == Token::MOD)
- cleanupNeeded = true;
+ bool cleanupNeeded = commonType.getCategory() == Type::Category::INTEGER &&
+ (Token::isCompareOp(op) || op == Token::DIV || op == Token::MOD);
// for commutative operators, push the literal as late as possible to allow improved optimization
- //@todo this has to be extended for literal expressions
- bool swap = (m_optimize && Token::isCommutativeOp(op) && dynamic_cast<Literal const*>(&rightExpression)
- && !dynamic_cast<Literal const*>(&leftExpression));
+ auto isLiteral = [](Expression const& _e)
+ {
+ return dynamic_cast<Literal const*>(&_e) || _e.getType()->getCategory() == Type::Category::INTEGER_CONSTANT;
+ };
+ bool swap = m_optimize && Token::isCommutativeOp(op) && isLiteral(rightExpression) && !isLiteral(leftExpression);
if (swap)
{
leftExpression.accept(*this);
@@ -478,10 +489,10 @@ void ExpressionCompiler::endVisit(Literal const& _literal)
{
switch (_literal.getType()->getCategory())
{
- case Type::Category::INTEGER:
+ case Type::Category::INTEGER_CONSTANT:
case Type::Category::BOOL:
case Type::Category::STRING:
- m_context << _literal.getType()->literalValue(_literal);
+ m_context << _literal.getType()->literalValue(&_literal);
break;
default:
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Only integer, boolean and string literals implemented for now."));
@@ -617,9 +628,16 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con
if (_typeOnStack == _targetType && !_cleanupNeeded)
return;
- if (_typeOnStack.getCategory() == Type::Category::INTEGER)
+ Type::Category stackTypeCategory = _typeOnStack.getCategory();
+ Type::Category targetTypeCategory = _targetType.getCategory();
+ if (stackTypeCategory == Type::Category::INTEGER)
+ {
+ solAssert(targetTypeCategory == Type::Category::INTEGER || targetTypeCategory == Type::Category::CONTRACT, "");
appendHighBitsCleanup(dynamic_cast<IntegerType const&>(_typeOnStack));
- else if (_typeOnStack.getCategory() == Type::Category::STRING)
+ }
+ else if (stackTypeCategory == Type::Category::INTEGER_CONSTANT)
+ solAssert(targetTypeCategory == Type::Category::INTEGER || targetTypeCategory == Type::Category::CONTRACT, "");
+ else if (stackTypeCategory == Type::Category::STRING)
{
// nothing to do, strings are high-order-bit-aligned
//@todo clear lower-order bytes if we allow explicit conversion to shorter strings