added parsing for constant variables

This commit is contained in:
Liana Husikyan 2015-03-03 12:58:01 +01:00
parent a16677dcfb
commit 67cd3a7180
7 changed files with 42 additions and 17 deletions

View File

@ -197,7 +197,7 @@ vector<pair<FixedHash<4>, FunctionTypePointer>> const& ContractDefinition::getIn
}
for (ASTPointer<VariableDeclaration> const& v: contract->getStateVariables())
if (v->isPublic() && functionsSeen.count(v->getName()) == 0)
if (v->isPublic() && functionsSeen.count(v->getName()) == 0 && !v->isConstant())
{
FunctionType ftype(*v);
functionsSeen.insert(v->getName());
@ -322,8 +322,8 @@ string FunctionDefinition::getCanonicalSignature() const
bool VariableDeclaration::isLValue() const
{
// External function parameters are Read-Only
return !isExternalFunctionParameter();
// External function parameters and constant declared variables are Read-Only
return !isExternalFunctionParameter() && !m_isConstant;
}
void VariableDeclaration::checkTypeRequirements()

27
AST.h
View File

@ -440,13 +440,22 @@ private:
class VariableDeclaration: public Declaration
{
public:
VariableDeclaration(SourceLocation const& _location, ASTPointer<TypeName> const& _type,
ASTPointer<ASTString> const& _name, ASTPointer<Expression> _value,
Visibility _visibility,
bool _isStateVar = false, bool _isIndexed = false):
Declaration(_location, _name, _visibility),
m_typeName(_type), m_value(_value),
m_isStateVariable(_isStateVar), m_isIndexed(_isIndexed) {}
VariableDeclaration(
SourceLocation const& _location,
ASTPointer<TypeName> const& _type,
ASTPointer<ASTString> const& _name,
ASTPointer<Expression> _value,
Visibility _visibility,
bool _isStateVar = false,
bool _isIndexed = false,
bool _isConstant = false):
Declaration(_location, _name, _visibility),
m_typeName(_type),
m_value(_value),
m_isStateVariable(_isStateVar),
m_isIndexed(_isIndexed),
m_isConstant(_isConstant){}
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;
@ -465,15 +474,17 @@ public:
bool isExternalFunctionParameter() const;
bool isStateVariable() const { return m_isStateVariable; }
bool isIndexed() const { return m_isIndexed; }
bool isConstant() const { return m_isConstant; }
protected:
Visibility getDefaultVisibility() const override { return Visibility::Internal; }
private:
ASTPointer<TypeName> m_typeName; ///< can be empty ("var")
ASTPointer<Expression> m_value; ///< the assigned value, can be missing
ASTPointer<Expression> m_value; ///< the assigned value, can be missing
bool m_isStateVariable; ///< Whether or not this is a contract state variable
bool m_isIndexed; ///< Whether this is an indexed variable (used by events).
bool m_isConstant; ///< Whether the variable is a compile-time constant.
std::shared_ptr<Type const> m_type; ///< derived type, initially empty
};

View File

@ -276,13 +276,14 @@ void Compiler::registerStateVariables(ContractDefinition const& _contract)
{
for (ContractDefinition const* contract: boost::adaptors::reverse(_contract.getLinearizedBaseContracts()))
for (ASTPointer<VariableDeclaration> const& variable: contract->getStateVariables())
m_context.addStateVariable(*variable);
if (!variable->isConstant())
m_context.addStateVariable(*variable);
}
void Compiler::initializeStateVariables(ContractDefinition const& _contract)
{
for (ASTPointer<VariableDeclaration> const& variable: _contract.getStateVariables())
if (variable->getValue())
if (variable->getValue() && !variable->isConstant())
ExpressionCompiler(m_context, m_optimize).appendStateVariableInitialization(*variable);
}

View File

@ -855,8 +855,11 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier)
}
else if (FunctionDefinition const* functionDef = dynamic_cast<FunctionDefinition const*>(declaration))
m_context << m_context.getVirtualFunctionEntryLabel(*functionDef).pushTag();
else if (dynamic_cast<VariableDeclaration const*>(declaration))
setLValueFromDeclaration(*declaration, _identifier);
else if (auto variable = dynamic_cast<VariableDeclaration const*>(declaration))
{
if (!variable->isConstant())
setLValueFromDeclaration(*declaration, _identifier);
}
else if (dynamic_cast<ContractDefinition const*>(declaration))
{
// no-op

View File

@ -135,6 +135,7 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
}
while (m_scanner->getCurrentToken() == Token::Comma);
expectToken(Token::LBrace);
bool isDeclaredConst = false;
while (true)
{
Token::Value currentToken = m_scanner->getCurrentToken();
@ -152,13 +153,21 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
VarDeclParserOptions options;
options.isStateVariable = true;
options.allowInitialValue = true;
options.isDeclaredConst = isDeclaredConst;
stateVariables.push_back(parseVariableDeclaration(options));
isDeclaredConst = false;
expectToken(Token::Semicolon);
}
else if (currentToken == Token::Modifier)
modifiers.push_back(parseModifierDefinition());
else if (currentToken == Token::Event)
events.push_back(parseEventDefinition());
else if (currentToken == Token::Const)
{
solAssert(Token::isElementaryTypeName(m_scanner->peekNextToken()), "");
isDeclaredConst = true;
m_scanner->next();
}
else
BOOST_THROW_EXCEPTION(createParserError("Function, variable, struct or modifier declaration expected."));
}
@ -348,7 +357,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
}
return nodeFactory.createNode<VariableDeclaration>(type, identifier, value,
visibility, _options.isStateVariable,
isIndexed);
isIndexed, _options.isDeclaredConst);
}
ASTPointer<ModifierDefinition> Parser::parseModifierDefinition()

View File

@ -54,6 +54,7 @@ private:
bool allowIndexed = false;
bool allowEmptyName = false;
bool allowInitialValue = false;
bool isDeclaredConst = false;
};
///@{

View File

@ -516,7 +516,7 @@ private:
std::vector<std::string> m_parameterNames;
std::vector<std::string> m_returnParameterNames;
Location const m_location;
/// true iff the function takes an arbitrary number of arguments of arbitrary types
/// true if the function takes an arbitrary number of arguments of arbitrary types
bool const m_arbitraryParameters = false;
bool const m_gasSet = false; ///< true iff the gas value to be used is on the stack
bool const m_valueSet = false; ///< true iff the value to be sent is on the stack