Merge pull request #953 from LefterisJP/sol_ethSubDenominations

Solidity ether subdenominations
This commit is contained in:
Gav Wood 2015-02-05 17:12:19 -08:00
commit 59a3909376
5 changed files with 65 additions and 8 deletions

11
AST.cpp
View File

@ -594,6 +594,17 @@ void ElementaryTypeNameExpression::checkTypeRequirements()
m_type = make_shared<TypeType>(Type::fromElementaryTypeName(m_typeToken)); m_type = make_shared<TypeType>(Type::fromElementaryTypeName(m_typeToken));
} }
Literal::Literal(Location const& _location, Token::Value _token,
ASTPointer<ASTString> const& _value,
Token::Value _sub):
PrimaryExpression(_location), m_token(_token), m_value(_value)
{
if (Token::isEtherSubdenomination(_sub))
m_subDenomination = static_cast<Literal::SubDenomination>(_sub);
else
m_subDenomination = Literal::SubDenomination::None;
}
void Literal::checkTypeRequirements() void Literal::checkTypeRequirements()
{ {
m_type = Type::forLiteral(*this); m_type = Type::forLiteral(*this);

18
AST.h
View File

@ -1112,13 +1112,22 @@ 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 class Literal: public PrimaryExpression
{ {
public: public:
Literal(Location const& _location, Token::Value _token, ASTPointer<ASTString> const& _value): enum class SubDenomination
PrimaryExpression(_location), m_token(_token), m_value(_value) {} {
None = Token::ILLEGAL,
Wei = Token::SubWei,
Szabo = Token::SubSzabo,
Finney = Token::SubFinney,
Ether = Token::SubEther
};
Literal(Location const& _location, Token::Value _token,
ASTPointer<ASTString> const& _value,
Token::Value _sub = Token::ILLEGAL);
virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override; virtual void accept(ASTConstVisitor& _visitor) const override;
virtual void checkTypeRequirements() override; virtual void checkTypeRequirements() override;
@ -1127,9 +1136,12 @@ public:
/// @returns the non-parsed value of the literal /// @returns the non-parsed value of the literal
ASTString const& getValue() const { return *m_value; } ASTString const& getValue() const { return *m_value; }
SubDenomination getSubDenomination() const { return m_subDenomination; }
private: private:
Token::Value m_token; Token::Value m_token;
ASTPointer<ASTString> m_value; ASTPointer<ASTString> m_value;
SubDenomination m_subDenomination;
}; };
/// @} /// @}

View File

@ -180,7 +180,7 @@ ASTPointer<InheritanceSpecifier> Parser::parseInheritanceSpecifier()
Declaration::Visibility Parser::parseVisibilitySpecifier(Token::Value _token) Declaration::Visibility Parser::parseVisibilitySpecifier(Token::Value _token)
{ {
Declaration::Visibility visibility; Declaration::Visibility visibility = Declaration::Visibility::DEFAULT;
if (_token == Token::PUBLIC) if (_token == Token::PUBLIC)
visibility = Declaration::Visibility::PUBLIC; visibility = Declaration::Visibility::PUBLIC;
else if (_token == Token::PROTECTED) else if (_token == Token::PROTECTED)
@ -684,6 +684,7 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
ASTNodeFactory nodeFactory(*this); ASTNodeFactory nodeFactory(*this);
Token::Value token = m_scanner->getCurrentToken(); Token::Value token = m_scanner->getCurrentToken();
ASTPointer<Expression> expression; ASTPointer<Expression> expression;
Token::Value nextToken = Token::ILLEGAL;
switch (token) switch (token)
{ {
case Token::TRUE_LITERAL: case Token::TRUE_LITERAL:
@ -691,9 +692,12 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
expression = nodeFactory.createNode<Literal>(token, getLiteralAndAdvance()); expression = nodeFactory.createNode<Literal>(token, getLiteralAndAdvance());
break; break;
case Token::NUMBER: case Token::NUMBER:
nextToken = m_scanner->peekNextToken();
case Token::STRING_LITERAL: case Token::STRING_LITERAL:
nodeFactory.markEndPosition(); nodeFactory.markEndPosition();
expression = nodeFactory.createNode<Literal>(token, getLiteralAndAdvance()); expression = nodeFactory.createNode<Literal>(token, getLiteralAndAdvance(), nextToken);
if (Token::isEtherSubdenomination(nextToken))
m_scanner->next();
break; break;
case Token::IDENTIFIER: case Token::IDENTIFIER:
nodeFactory.markEndPosition(); nodeFactory.markEndPosition();

View File

@ -174,6 +174,11 @@ namespace solidity
K(WHILE, "while", 0) \ K(WHILE, "while", 0) \
\ \
\ \
/* Ether subdenominations */ \
K(SubWei, "wei", 0) \
K(SubSzabo, "szabo", 0) \
K(SubFinney, "finney", 0) \
K(SubEther, "ether", 0) \
/* type keywords, keep them in this order, keep int as first keyword /* type keywords, keep them in this order, keep int as first keyword
* the implementation in Types.cpp has to be synced to this here * the implementation in Types.cpp has to be synced to this here
* TODO more to be added */ \ * TODO more to be added */ \
@ -378,6 +383,7 @@ public:
static bool isCountOp(Value op) { return op == INC || op == DEC; } static bool isCountOp(Value op) { return op == INC || op == DEC; }
static bool isShiftOp(Value op) { return (SHL <= op) && (op <= SHR); } static bool isShiftOp(Value op) { return (SHL <= op) && (op <= SHR); }
static bool isVisibilitySpecifier(Value op) { return op == PUBLIC || op == PRIVATE || op == PROTECTED; } static bool isVisibilitySpecifier(Value op) { return op == PUBLIC || op == PRIVATE || op == PROTECTED; }
static bool isEtherSubdenomination(Value op) { return op == SubWei || op == SubSzabo || op == SubFinney || op == Token::SubEther; }
// Returns a string corresponding to the JS token string // Returns a string corresponding to the JS token string
// (.e., "<" for the token LT) or NULL if the token doesn't // (.e., "<" for the token LT) or NULL if the token doesn't

View File

@ -326,15 +326,39 @@ string IntegerConstantType::toString() const
return "int_const " + m_value.str(); return "int_const " + m_value.str();
} }
u256 IntegerConstantType::literalValue(Literal const*) const u256 IntegerConstantType::literalValue(Literal const* _literal) const
{ {
u256 value;
// we ignore the literal and hope that the type was correctly determined // we ignore the literal and hope that the type was correctly determined
solAssert(m_value <= u256(-1), "Integer constant too large."); solAssert(m_value <= u256(-1), "Integer constant too large.");
solAssert(m_value >= -(bigint(1) << 255), "Integer constant too small."); solAssert(m_value >= -(bigint(1) << 255), "Integer constant too small.");
if (m_value >= 0) if (m_value >= 0)
return u256(m_value); value = u256(m_value);
else else
return s2u(s256(m_value)); value = s2u(s256(m_value));
if (_literal)
{
Literal::SubDenomination sub =_literal->getSubDenomination();
switch(sub)
{
case Literal::SubDenomination::Wei:
case Literal::SubDenomination::None:
break;
case Literal::SubDenomination::Szabo:
value *= u256(1000000000000);
break;
case Literal::SubDenomination::Finney:
value *= u256(1000000000000000);
break;
case Literal::SubDenomination::Ether:
value *= u256(1000000000000000000);
break;
}
}
return value;
} }
shared_ptr<IntegerType const> IntegerConstantType::getIntegerType() const shared_ptr<IntegerType const> IntegerConstantType::getIntegerType() const