From dca5f7b57bb5b535930d437c806f48a25cf6b569 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 4 Feb 2015 16:37:54 +0100 Subject: [PATCH] Adding ether subdenominations after constan literals --- AST.cpp | 11 +++++++++++ AST.h | 16 +++++++++++++--- Parser.cpp | 6 ++++-- Token.h | 5 +++++ Types.cpp | 27 ++++++++++++++++++++++++--- 5 files changed, 57 insertions(+), 8 deletions(-) diff --git a/AST.cpp b/AST.cpp index 6028c07cf..f0c60e05d 100644 --- a/AST.cpp +++ b/AST.cpp @@ -594,6 +594,17 @@ void ElementaryTypeNameExpression::checkTypeRequirements() m_type = make_shared(Type::fromElementaryTypeName(m_typeToken)); } +Literal::Literal(Location const& _location, Token::Value _token, + ASTPointer const& _value, + Token::Value _sub): + PrimaryExpression(_location), m_token(_token), m_value(_value) +{ + solAssert(_sub == Token::ILLEGAL || _sub == Token::ETH_SUB_WEI || + _sub == Token::ETH_SUB_SZABO || _sub == Token::ETH_SUB_FINNEY || + _sub == Token::ETH_SUB_ETHER, "Illegal Token::Value given to Literal ctor"); + m_subDenomination =static_cast(_sub); +} + void Literal::checkTypeRequirements() { m_type = Type::forLiteral(*this); diff --git a/AST.h b/AST.h index 525907bf4..ecf91c059 100755 --- a/AST.h +++ b/AST.h @@ -1112,13 +1112,20 @@ private: }; /** - * A literal string or number. @see Type::literalToBigEndian is used to actually parse its value. + * A literal string or number. @see ExpressionCompiler::endVisit() is used to actually parse its value. */ class Literal: public PrimaryExpression { public: - Literal(Location const& _location, Token::Value _token, ASTPointer const& _value): - PrimaryExpression(_location), m_token(_token), m_value(_value) {} + enum class ethSubDenomination { + NONE = Token::ILLEGAL, + WEI = Token::ETH_SUB_WEI, + SZABO = Token::ETH_SUB_SZABO, + FINNEY = Token::ETH_SUB_FINNEY, + ETHER = Token::ETH_SUB_ETHER}; + Literal(Location const& _location, Token::Value _token, + ASTPointer const& _value, + Token::Value _sub = Token::ILLEGAL); virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; virtual void checkTypeRequirements() override; @@ -1127,9 +1134,12 @@ public: /// @returns the non-parsed value of the literal ASTString const& getValue() const { return *m_value; } + ethSubDenomination getSubDenomination() const { return m_subDenomination; } + private: Token::Value m_token; ASTPointer m_value; + ethSubDenomination m_subDenomination; }; /// @} diff --git a/Parser.cpp b/Parser.cpp index 0ad7bd7ca..739bbdd61 100644 --- a/Parser.cpp +++ b/Parser.cpp @@ -180,7 +180,7 @@ ASTPointer Parser::parseInheritanceSpecifier() Declaration::Visibility Parser::parseVisibilitySpecifier(Token::Value _token) { - Declaration::Visibility visibility; + Declaration::Visibility visibility = Declaration::Visibility::DEFAULT; if (_token == Token::PUBLIC) visibility = Declaration::Visibility::PUBLIC; else if (_token == Token::PROTECTED) @@ -684,6 +684,7 @@ ASTPointer Parser::parsePrimaryExpression() ASTNodeFactory nodeFactory(*this); Token::Value token = m_scanner->getCurrentToken(); ASTPointer expression; + Token::Value nextToken = Token::ILLEGAL; switch (token) { case Token::TRUE_LITERAL: @@ -691,9 +692,10 @@ ASTPointer Parser::parsePrimaryExpression() expression = nodeFactory.createNode(token, getLiteralAndAdvance()); break; case Token::NUMBER: + nextToken = m_scanner->peekNextToken(); case Token::STRING_LITERAL: nodeFactory.markEndPosition(); - expression = nodeFactory.createNode(token, getLiteralAndAdvance()); + expression = nodeFactory.createNode(token, getLiteralAndAdvance(), nextToken); break; case Token::IDENTIFIER: nodeFactory.markEndPosition(); diff --git a/Token.h b/Token.h index 76e504499..7b9608254 100644 --- a/Token.h +++ b/Token.h @@ -174,6 +174,11 @@ namespace solidity K(WHILE, "while", 0) \ \ \ + /* Ether subdenominations */ \ + K(ETH_SUB_WEI, "wei", 0) \ + K(ETH_SUB_SZABO, "szabo", 0) \ + K(ETH_SUB_FINNEY, "finney", 0) \ + K(ETH_SUB_ETHER, "ether", 0) \ /* type keywords, keep them in this order, keep int as first keyword * the implementation in Types.cpp has to be synced to this here * TODO more to be added */ \ diff --git a/Types.cpp b/Types.cpp index 54e701c10..98c648025 100644 --- a/Types.cpp +++ b/Types.cpp @@ -326,15 +326,36 @@ string IntegerConstantType::toString() const return "int_const " + m_value.str(); } -u256 IntegerConstantType::literalValue(Literal const*) const +u256 IntegerConstantType::literalValue(Literal const* _literal) const { + Literal::ethSubDenomination sub =_literal->getSubDenomination(); + u256 value; // we ignore the literal and hope that the type was correctly determined solAssert(m_value <= u256(-1), "Integer constant too large."); solAssert(m_value >= -(bigint(1) << 255), "Integer constant too small."); + + if (m_value >= 0) - return u256(m_value); + value = u256(m_value); else - return s2u(s256(m_value)); + value = s2u(s256(m_value)); + + switch(sub) { + case Literal::ethSubDenomination::WEI: + case Literal::ethSubDenomination::NONE: + break; + case Literal::ethSubDenomination::SZABO: + value *= u256(1000000000000); + break; + case Literal::ethSubDenomination::FINNEY: + value *= u256(1000000000000000); + break; + case Literal::ethSubDenomination::ETHER: + value *= u256(1000000000000000000); + break; + } + + return value; } shared_ptr IntegerConstantType::getIntegerType() const