From 52050201e39b823ea9e6133e47c7e9e779dc1f07 Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Tue, 17 Feb 2015 16:21:38 +0100 Subject: [PATCH 1/5] Inline member initialisation renamed VariableDefinition class to VariableDeclarationStatement added tests --- AST.cpp | 22 +++++++++++++------ AST.h | 25 +++++++++++++--------- ASTForward.h | 2 +- ASTJsonConverter.cpp | 4 ++-- ASTJsonConverter.h | 4 ++-- ASTPrinter.cpp | 4 ++-- ASTPrinter.h | 4 ++-- ASTVisitor.h | 8 +++---- AST_accept.h | 12 +++++------ Compiler.cpp | 16 ++++++++++++-- Compiler.h | 3 ++- ExpressionCompiler.cpp | 30 +++++++++++++++++++++++--- ExpressionCompiler.h | 13 +++++++++++- NameAndTypeResolver.cpp | 6 +++--- NameAndTypeResolver.h | 2 +- Parser.cpp | 47 ++++++++++++++++++++++------------------- Parser.h | 9 ++++---- Types.cpp | 2 +- 18 files changed, 139 insertions(+), 74 deletions(-) diff --git a/AST.cpp b/AST.cpp index 761427db4..a18785ae1 100644 --- a/AST.cpp +++ b/AST.cpp @@ -77,6 +77,9 @@ void ContractDefinition::checkTypeRequirements() for (ASTPointer const& function: getDefinedFunctions()) function->checkTypeRequirements(); + for (ASTPointer const& variable: m_stateVariables) + variable->checkTypeRequirements(); + // check for hash collisions in function signatures set> hashes; for (auto const& it: getInterfaceFunctionList()) @@ -294,6 +297,12 @@ bool VariableDeclaration::isLValue() const return !isExternalFunctionParameter(); } +void VariableDeclaration::checkTypeRequirements() +{ + if (m_value) + m_value->checkTypeRequirements(); +} + bool VariableDeclaration::isExternalFunctionParameter() const { auto const* function = dynamic_cast(getScope()); @@ -390,26 +399,26 @@ void Return::checkTypeRequirements() m_expression->expectType(*m_returnParameters->getParameters().front()->getType()); } -void VariableDefinition::checkTypeRequirements() +void VariableDeclarationStatement::checkTypeRequirements() { // Variables can be declared without type (with "var"), in which case the first assignment // sets the type. // Note that assignments before the first declaration are legal because of the special scoping // rules inherited from JavaScript. - if (m_value) + if (m_variable->getValue()) { if (m_variable->getType()) - m_value->expectType(*m_variable->getType()); + m_variable->getValue()->expectType(*m_variable->getType()); else { // no type declared and no previous assignment, infer the type - m_value->checkTypeRequirements(); - TypePointer type = m_value->getType(); + m_variable->getValue()->checkTypeRequirements(); + TypePointer type = m_variable->getValue()->getType(); if (type->getCategory() == Type::Category::IntegerConstant) { auto intType = dynamic_pointer_cast(type)->getIntegerType(); if (!intType) - BOOST_THROW_EXCEPTION(m_value->createTypeError("Invalid integer constant " + type->toString())); + BOOST_THROW_EXCEPTION(m_variable->getValue()->createTypeError("Invalid integer constant " + type->toString())); type = intType; } else if (type->getCategory() == Type::Category::Void) @@ -418,7 +427,6 @@ void VariableDefinition::checkTypeRequirements() } } } - void Assignment::checkTypeRequirements() { m_leftHandSide->checkTypeRequirements(); diff --git a/AST.h b/AST.h index 64dac594d..c7fd068d9 100644 --- a/AST.h +++ b/AST.h @@ -432,14 +432,17 @@ class VariableDeclaration: public Declaration { public: VariableDeclaration(Location const& _location, ASTPointer const& _type, - ASTPointer const& _name, Visibility _visibility, - bool _isStateVar = false, bool _isIndexed = false): - Declaration(_location, _name, _visibility), m_typeName(_type), - m_isStateVariable(_isStateVar), m_isIndexed(_isIndexed) {} + ASTPointer const& _name, ASTPointer _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) {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; TypeName const* getTypeName() const { return m_typeName.get(); } + ASTPointer const& getValue() const { return m_value; } /// Returns the declared or inferred type. Can be an empty pointer if no type was explicitly /// declared and there is no assignment to the variable that fixes the type. @@ -447,6 +450,9 @@ public: void setType(std::shared_ptr const& _type) { m_type = _type; } virtual bool isLValue() const override; + + /// Checks that all parameters have allowed types and calls checkTypeRequirements on the body. + void checkTypeRequirements(); bool isLocalVariable() const { return !!dynamic_cast(getScope()); } bool isExternalFunctionParameter() const; bool isStateVariable() const { return m_isStateVariable; } @@ -457,6 +463,7 @@ protected: private: ASTPointer m_typeName; ///< can be empty ("var") + ASTPointer 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). @@ -833,22 +840,20 @@ private: * also be "var") but the actual assignment can be missing. * Examples: var a = 2; uint256 a; */ -class VariableDefinition: public Statement +class VariableDeclarationStatement: public Statement { public: - VariableDefinition(Location const& _location, ASTPointer _variable, - ASTPointer _value): - Statement(_location), m_variable(_variable), m_value(_value) {} + VariableDeclarationStatement(Location const& _location, ASTPointer _variable): + Statement(_location), m_variable(_variable) {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; virtual void checkTypeRequirements() override; VariableDeclaration const& getDeclaration() const { return *m_variable; } - Expression const* getExpression() const { return m_value.get(); } + Expression const* getExpression() const { return m_variable->getValue().get(); } private: ASTPointer m_variable; - ASTPointer m_value; ///< the assigned value, can be missing }; /** diff --git a/ASTForward.h b/ASTForward.h index 0b6817e45..3a151b63e 100644 --- a/ASTForward.h +++ b/ASTForward.h @@ -63,7 +63,7 @@ class ForStatement; class Continue; class Break; class Return; -class VariableDefinition; +class VariableDeclarationStatement; class ExpressionStatement; class Expression; class Assignment; diff --git a/ASTJsonConverter.cpp b/ASTJsonConverter.cpp index 04feafe2f..c30e4ca2b 100644 --- a/ASTJsonConverter.cpp +++ b/ASTJsonConverter.cpp @@ -198,7 +198,7 @@ bool ASTJsonConverter::visit(Return const&) return true; } -bool ASTJsonConverter::visit(VariableDefinition const&) +bool ASTJsonConverter::visit(VariableDeclarationStatement const&) { addJsonNode("VariableDefinition", {}, true); return true; @@ -394,7 +394,7 @@ void ASTJsonConverter::endVisit(Return const&) goUp(); } -void ASTJsonConverter::endVisit(VariableDefinition const&) +void ASTJsonConverter::endVisit(VariableDeclarationStatement const&) { goUp(); } diff --git a/ASTJsonConverter.h b/ASTJsonConverter.h index 466801e9c..30a92e66c 100644 --- a/ASTJsonConverter.h +++ b/ASTJsonConverter.h @@ -64,7 +64,7 @@ public: bool visit(Continue const& _node) override; bool visit(Break const& _node) override; bool visit(Return const& _node) override; - bool visit(VariableDefinition const& _node) override; + bool visit(VariableDeclarationStatement const& _node) override; bool visit(ExpressionStatement const& _node) override; bool visit(Expression const& _node) override; bool visit(Assignment const& _node) override; @@ -98,7 +98,7 @@ public: void endVisit(Continue const&) override; void endVisit(Break const&) override; void endVisit(Return const&) override; - void endVisit(VariableDefinition const&) override; + void endVisit(VariableDeclarationStatement const&) override; void endVisit(ExpressionStatement const&) override; void endVisit(Expression const&) override; void endVisit(Assignment const&) override; diff --git a/ASTPrinter.cpp b/ASTPrinter.cpp index d380b0029..aead6abd8 100644 --- a/ASTPrinter.cpp +++ b/ASTPrinter.cpp @@ -225,7 +225,7 @@ bool ASTPrinter::visit(Return const& _node) return goDeeper(); } -bool ASTPrinter::visit(VariableDefinition const& _node) +bool ASTPrinter::visit(VariableDeclarationStatement const& _node) { writeLine("VariableDefinition"); printSourcePart(_node); @@ -469,7 +469,7 @@ void ASTPrinter::endVisit(Return const&) m_indentation--; } -void ASTPrinter::endVisit(VariableDefinition const&) +void ASTPrinter::endVisit(VariableDeclarationStatement const&) { m_indentation--; } diff --git a/ASTPrinter.h b/ASTPrinter.h index d9072aacc..7a0ef5a65 100644 --- a/ASTPrinter.h +++ b/ASTPrinter.h @@ -68,7 +68,7 @@ public: bool visit(Continue const& _node) override; bool visit(Break const& _node) override; bool visit(Return const& _node) override; - bool visit(VariableDefinition const& _node) override; + bool visit(VariableDeclarationStatement const& _node) override; bool visit(ExpressionStatement const& _node) override; bool visit(Expression const& _node) override; bool visit(Assignment const& _node) override; @@ -109,7 +109,7 @@ public: void endVisit(Continue const&) override; void endVisit(Break const&) override; void endVisit(Return const&) override; - void endVisit(VariableDefinition const&) override; + void endVisit(VariableDeclarationStatement const&) override; void endVisit(ExpressionStatement const&) override; void endVisit(Expression const&) override; void endVisit(Assignment const&) override; diff --git a/ASTVisitor.h b/ASTVisitor.h index a7fa6b1cf..2ecfbe4b1 100644 --- a/ASTVisitor.h +++ b/ASTVisitor.h @@ -69,7 +69,7 @@ public: virtual bool visit(Continue&) { return true; } virtual bool visit(Break&) { return true; } virtual bool visit(Return&) { return true; } - virtual bool visit(VariableDefinition&) { return true; } + virtual bool visit(VariableDeclarationStatement&) { return true; } virtual bool visit(ExpressionStatement&) { return true; } virtual bool visit(Expression&) { return true; } virtual bool visit(Assignment&) { return true; } @@ -112,7 +112,7 @@ public: virtual void endVisit(Continue&) { } virtual void endVisit(Break&) { } virtual void endVisit(Return&) { } - virtual void endVisit(VariableDefinition&) { } + virtual void endVisit(VariableDeclarationStatement&) { } virtual void endVisit(ExpressionStatement&) { } virtual void endVisit(Expression&) { } virtual void endVisit(Assignment&) { } @@ -159,7 +159,7 @@ public: virtual bool visit(Continue const&) { return true; } virtual bool visit(Break const&) { return true; } virtual bool visit(Return const&) { return true; } - virtual bool visit(VariableDefinition const&) { return true; } + virtual bool visit(VariableDeclarationStatement const&) { return true; } virtual bool visit(ExpressionStatement const&) { return true; } virtual bool visit(Expression const&) { return true; } virtual bool visit(Assignment const&) { return true; } @@ -202,7 +202,7 @@ public: virtual void endVisit(Continue const&) { } virtual void endVisit(Break const&) { } virtual void endVisit(Return const&) { } - virtual void endVisit(VariableDefinition const&) { } + virtual void endVisit(VariableDeclarationStatement const&) { } virtual void endVisit(ExpressionStatement const&) { } virtual void endVisit(Expression const&) { } virtual void endVisit(Assignment const&) { } diff --git a/AST_accept.h b/AST_accept.h index b71e103df..217a565f0 100644 --- a/AST_accept.h +++ b/AST_accept.h @@ -475,24 +475,24 @@ void ExpressionStatement::accept(ASTConstVisitor& _visitor) const _visitor.endVisit(*this); } -void VariableDefinition::accept(ASTVisitor& _visitor) +void VariableDeclarationStatement::accept(ASTVisitor& _visitor) { if (_visitor.visit(*this)) { m_variable->accept(_visitor); - if (m_value) - m_value->accept(_visitor); + if (m_variable->getValue()) + m_variable->getValue()->accept(_visitor); } _visitor.endVisit(*this); } -void VariableDefinition::accept(ASTConstVisitor& _visitor) const +void VariableDeclarationStatement::accept(ASTConstVisitor& _visitor) const { if (_visitor.visit(*this)) { m_variable->accept(_visitor); - if (m_value) - m_value->accept(_visitor); + if (m_variable->getValue()) + m_variable->getValue()->accept(_visitor); } _visitor.endVisit(*this); } diff --git a/Compiler.cpp b/Compiler.cpp index 14acc0113..f552210f4 100644 --- a/Compiler.cpp +++ b/Compiler.cpp @@ -73,7 +73,7 @@ void Compiler::packIntoContractCreator(ContractDefinition const& _contract, Comp for (ASTPointer const& base: contract->getBaseContracts()) { ContractDefinition const* baseContract = dynamic_cast( - base->getName()->getReferencedDeclaration()); + base->getName()->getReferencedDeclaration()); solAssert(baseContract, ""); if (baseArguments.count(baseContract) == 0) baseArguments[baseContract] = &base->getArguments(); @@ -85,12 +85,14 @@ void Compiler::packIntoContractCreator(ContractDefinition const& _contract, Comp { ContractDefinition const* base = bases[bases.size() - i]; solAssert(base, ""); + initializeStateVariables(*base); FunctionDefinition const* baseConstructor = base->getConstructor(); if (!baseConstructor) continue; solAssert(baseArguments[base], ""); appendBaseConstructorCall(*baseConstructor, *baseArguments[base]); } + initializeStateVariables(_contract); if (_contract.getConstructor()) appendConstructorCall(*_contract.getConstructor()); @@ -247,6 +249,16 @@ void Compiler::registerStateVariables(ContractDefinition const& _contract) m_context.addStateVariable(*variable); } +void Compiler::initializeStateVariables(ContractDefinition const& _contract) +{ + for(ASTPointer const& variable: _contract.getStateVariables()) + if (variable->getValue()) + { + compileExpression(*(variable->getValue()), (variable->getValue())->getType()); + ExpressionCompiler::appendStateVariableInitialization(m_context, *variable); + } +} + bool Compiler::visit(VariableDeclaration const& _variableDeclaration) { solAssert(_variableDeclaration.isStateVariable(), "Compiler visit to non-state variable declaration."); @@ -429,7 +441,7 @@ bool Compiler::visit(Return const& _return) return false; } -bool Compiler::visit(VariableDefinition const& _variableDefinition) +bool Compiler::visit(VariableDeclarationStatement const& _variableDefinition) { if (Expression const* expression = _variableDefinition.getExpression()) { diff --git a/Compiler.h b/Compiler.h index 1aeaee88f..0838512ee 100644 --- a/Compiler.h +++ b/Compiler.h @@ -59,6 +59,7 @@ private: void appendReturnValuePacker(TypePointers const& _typeParameters); void registerStateVariables(ContractDefinition const& _contract); + void initializeStateVariables(ContractDefinition const& _contract); virtual bool visit(VariableDeclaration const& _variableDeclaration) override; virtual bool visit(FunctionDefinition const& _function) override; @@ -68,7 +69,7 @@ private: virtual bool visit(Continue const& _continue) override; virtual bool visit(Break const& _break) override; virtual bool visit(Return const& _return) override; - virtual bool visit(VariableDefinition const& _variableDefinition) override; + virtual bool visit(VariableDeclarationStatement const& _variableDefinition) override; virtual bool visit(ExpressionStatement const& _expressionStatement) override; virtual bool visit(PlaceholderStatement const&) override; diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp index a8bc53e0f..74dfb2b5e 100644 --- a/ExpressionCompiler.cpp +++ b/ExpressionCompiler.cpp @@ -56,6 +56,19 @@ void ExpressionCompiler::appendStateVariableAccessor(CompilerContext& _context, compiler.appendStateVariableAccessor(_varDecl); } +void ExpressionCompiler::appendStateVariableInitialization(CompilerContext& _context, VariableDeclaration const& _varDecl, bool _optimize) +{ + ExpressionCompiler compiler(_context, _optimize); + compiler.appendStateVariableInitialization(_varDecl); +} + +void ExpressionCompiler::appendStateVariableInitialization(VariableDeclaration const& _varDecl) +{ + m_currentLValue.fromStateVariable(_varDecl); + m_currentLValue.storeValue(*_varDecl.getType(), _varDecl.getLocation()); + m_currentLValue.reset(); +} + bool ExpressionCompiler::visit(Assignment const& _assignment) { _assignment.getRightHandSide().accept(*this); @@ -77,7 +90,6 @@ bool ExpressionCompiler::visit(Assignment const& _assignment) } m_currentLValue.storeValue(*_assignment.getRightHandSide().getType(), _assignment.getLocation()); m_currentLValue.reset(); - return false; } @@ -1018,12 +1030,24 @@ void ExpressionCompiler::LValue::fromIdentifier(Identifier const& _identifier, D m_dataType = _identifier.getType(); solAssert(m_dataType->getStorageSize() <= numeric_limits::max(), "The storage size of " + m_dataType->toString() + " should fit in an unsigned"); - m_size = unsigned(m_dataType->getStorageSize()); } + m_size = unsigned(m_dataType->getStorageSize()); + } else BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_identifier.getLocation()) << errinfo_comment("Identifier type not supported or identifier not found.")); } +void ExpressionCompiler::LValue::fromStateVariable(VariableDeclaration const& _declaration) +{ + solAssert(m_context->isStateVariable(&_declaration), "Not a state variable."); + *m_context << m_context->getStorageLocationOfVariable(_declaration); + m_type = LValueType::Storage; + m_dataType = _declaration.getType(); + solAssert(m_dataType->getStorageSize() <= numeric_limits::max(), + "The storage size of " + m_dataType->toString() + " should fit in an unsigned"); + m_size = unsigned(m_dataType->getStorageSize()); +} + void ExpressionCompiler::LValue::retrieveValue(Location const& _location, bool _remove) const { switch (m_type) @@ -1117,7 +1141,7 @@ void ExpressionCompiler::LValue::storeValue(Type const& _sourceType, Location co } else { - solAssert(_sourceType.getCategory() == m_dataType->getCategory(), ""); + solAssert(_sourceType.getCategory() == m_dataType->getCategory(), "Wrong type conversation for assignment."); if (m_dataType->getCategory() == Type::Category::ByteArray) { CompilerUtils(*m_context).copyByteArrayToStorage( diff --git a/ExpressionCompiler.h b/ExpressionCompiler.h index 471d81865..3567a9148 100644 --- a/ExpressionCompiler.h +++ b/ExpressionCompiler.h @@ -59,6 +59,9 @@ public: /// Appends code for a State Variable accessor function static void appendStateVariableAccessor(CompilerContext& _context, VariableDeclaration const& _varDecl, bool _optimize = false); + /// Appends code for a State Variable Initialization function + static void appendStateVariableInitialization(CompilerContext& _context, VariableDeclaration const& _varDecl, bool _optimize = false); + private: explicit ExpressionCompiler(CompilerContext& _compilerContext, bool _optimize = false): m_optimize(_optimize), m_context(_compilerContext), m_currentLValue(m_context) {} @@ -111,6 +114,9 @@ private: /// Appends code for a State Variable accessor function void appendStateVariableAccessor(VariableDeclaration const& _varDecl); + /// Appends code for a State Variable initialization + void appendStateVariableInitialization(VariableDeclaration const& _varDecl); + /** * Helper class to store and retrieve lvalues to and from various locations. * All types except STACK store a reference in a slot on the stack, STACK just @@ -126,8 +132,13 @@ private: std::shared_ptr const& _dataType, unsigned _baseStackOffset = 0); /// Set type according to the declaration and retrieve the reference. - /// @a _expression is the current expression + /// @a _identifier is the current identifier void fromIdentifier(Identifier const& _identifier, Declaration const& _declaration); + + /// Set type according to the declaration and retrieve the reference. + /// @a _declaration is the variable declaration + void fromStateVariable(VariableDeclaration const& _declaration); + void reset() { m_type = LValueType::None; m_dataType.reset(); m_baseStackOffset = 0; m_size = 0; } bool isValid() const { return m_type != LValueType::None; } diff --git a/NameAndTypeResolver.cpp b/NameAndTypeResolver.cpp index e19b0bf9e..15e1ac6f5 100644 --- a/NameAndTypeResolver.cpp +++ b/NameAndTypeResolver.cpp @@ -267,12 +267,12 @@ void DeclarationRegistrationHelper::endVisit(ModifierDefinition&) closeCurrentScope(); } -void DeclarationRegistrationHelper::endVisit(VariableDefinition& _variableDefinition) +void DeclarationRegistrationHelper::endVisit(VariableDeclarationStatement& _variableDeclarationStatement) { // Register the local variables with the function // This does not fit here perfectly, but it saves us another AST visit. - solAssert(m_currentFunction, "Variable definition without function."); - m_currentFunction->addLocalVariable(_variableDefinition.getDeclaration()); + solAssert(m_currentFunction, "Variable declaration without function."); + m_currentFunction->addLocalVariable(_variableDeclarationStatement.getDeclaration()); } bool DeclarationRegistrationHelper::visit(VariableDeclaration& _declaration) diff --git a/NameAndTypeResolver.h b/NameAndTypeResolver.h index d9ac98ce5..63b8ab637 100644 --- a/NameAndTypeResolver.h +++ b/NameAndTypeResolver.h @@ -105,7 +105,7 @@ private: void endVisit(FunctionDefinition& _function) override; bool visit(ModifierDefinition& _modifier) override; void endVisit(ModifierDefinition& _modifier) override; - void endVisit(VariableDefinition& _variableDefinition) override; + void endVisit(VariableDeclarationStatement& _variableDeclarationStatement) override; bool visit(VariableDeclaration& _declaration) override; bool visit(EventDefinition& _event) override; void endVisit(EventDefinition& _event) override; diff --git a/Parser.cpp b/Parser.cpp index 72334c6cc..9940fb8d9 100644 --- a/Parser.cpp +++ b/Parser.cpp @@ -148,6 +148,7 @@ ASTPointer Parser::parseContractDefinition() { VarDeclParserOptions options; options.isStateVariable = true; + options.allowInitialValue = true; stateVariables.push_back(parseVariableDeclaration(options)); expectToken(Token::Semicolon); } @@ -324,9 +325,19 @@ ASTPointer Parser::parseVariableDeclaration(VarDeclParserOp } else identifier = expectIdentifierToken(); - return nodeFactory.createNode(type, identifier, - visibility, _options.isStateVariable, - isIndexed); + ASTPointer value; + if (_options.allowInitialValue) + { + if (m_scanner->getCurrentToken() == Token::Assign) + { + m_scanner->next(); + value = parseExpression(); + nodeFactory.setEndPositionFromNode(value); + } + } + return nodeFactory.createNode(type, identifier, value, + visibility, _options.isStateVariable, + isIndexed); } ASTPointer Parser::parseModifierDefinition() @@ -519,7 +530,7 @@ ASTPointer Parser::parseStatement() } // fall-through default: - statement = parseVarDefOrExprStmt(); + statement = parseVarDeclOrExprStmt(); } expectToken(Token::Semicolon); return statement; @@ -568,7 +579,7 @@ ASTPointer Parser::parseForStatement() // LTODO: Maybe here have some predicate like peekExpression() instead of checking for semicolon and RParen? if (m_scanner->getCurrentToken() != Token::Semicolon) - initExpression = parseVarDefOrExprStmt(); + initExpression = parseVarDeclOrExprStmt(); expectToken(Token::Semicolon); if (m_scanner->getCurrentToken() != Token::Semicolon) @@ -587,30 +598,22 @@ ASTPointer Parser::parseForStatement() body); } -ASTPointer Parser::parseVarDefOrExprStmt() +ASTPointer Parser::parseVarDeclOrExprStmt() { - if (peekVariableDefinition()) - return parseVariableDefinition(); + if (peekVariableDeclarationStatement()) + return parseVariableDeclarationStatement(); else return parseExpressionStatement(); } -ASTPointer Parser::parseVariableDefinition() +ASTPointer Parser::parseVariableDeclarationStatement() { ASTNodeFactory nodeFactory(*this); VarDeclParserOptions options; options.allowVar = true; + options.allowInitialValue = true; ASTPointer variable = parseVariableDeclaration(options); - ASTPointer value; - if (m_scanner->getCurrentToken() == Token::Assign) - { - m_scanner->next(); - value = parseExpression(); - nodeFactory.setEndPositionFromNode(value); - } - else - nodeFactory.setEndPositionFromNode(variable); - return nodeFactory.createNode(variable, value); + return nodeFactory.createNode(variable); } ASTPointer Parser::parseExpressionStatement() @@ -822,11 +825,11 @@ pair>, vector>> Parser::pars } -bool Parser::peekVariableDefinition() +bool Parser::peekVariableDeclarationStatement() { - // distinguish between variable definition (and potentially assignment) and expression statement + // distinguish between variable declaration (and potentially assignment) and expression statement // (which include assignments to other expressions and pre-declared variables) - // We have a variable definition if we get a keyword that specifies a type name, or + // We have a variable declaration if we get a keyword that specifies a type name, or // in the case of a user-defined type, we have two identifiers following each other. return (m_scanner->getCurrentToken() == Token::Mapping || m_scanner->getCurrentToken() == Token::Var || diff --git a/Parser.h b/Parser.h index 1bb4ea977..4034aec85 100644 --- a/Parser.h +++ b/Parser.h @@ -51,6 +51,7 @@ private: bool isStateVariable = false; bool allowIndexed = false; bool allowEmptyName = false; + bool allowInitialValue = false; }; ///@{ @@ -76,8 +77,8 @@ private: ASTPointer parseIfStatement(); ASTPointer parseWhileStatement(); ASTPointer parseForStatement(); - ASTPointer parseVarDefOrExprStmt(); - ASTPointer parseVariableDefinition(); + ASTPointer parseVarDeclOrExprStmt(); + ASTPointer parseVariableDeclarationStatement(); ASTPointer parseExpressionStatement(); ASTPointer parseExpression(); ASTPointer parseBinaryExpression(int _minPrecedence = 4); @@ -91,8 +92,8 @@ private: ///@{ ///@name Helper functions - /// Peeks ahead in the scanner to determine if a variable definition is going to follow - bool peekVariableDefinition(); + /// Peeks ahead in the scanner to determine if a variable declaration statement is going to follow + bool peekVariableDeclarationStatement(); /// If current token value is not _value, throw exception otherwise advance token. void expectToken(Token::Value _value); diff --git a/Types.cpp b/Types.cpp index a9c480176..55dedd921 100644 --- a/Types.cpp +++ b/Types.cpp @@ -653,7 +653,7 @@ MemberList const& StructType::getMembers() const // We need to lazy-initialize it because of recursive references. if (!m_members) { - vector> members; + MemberList::MemberMap members; for (ASTPointer const& variable: m_struct.getMembers()) members.push_back(make_pair(variable->getName(), variable->getType())); m_members.reset(new MemberList(members)); From 1ed86b33bcb07f432209953ec4ed1779d0831452 Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Fri, 20 Feb 2015 11:57:42 +0100 Subject: [PATCH 2/5] cosmetic changes --- Compiler.cpp | 2 +- ExpressionCompiler.cpp | 17 ++++++----------- ExpressionCompiler.h | 2 +- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/Compiler.cpp b/Compiler.cpp index f552210f4..bdc29fab9 100644 --- a/Compiler.cpp +++ b/Compiler.cpp @@ -251,7 +251,7 @@ void Compiler::registerStateVariables(ContractDefinition const& _contract) void Compiler::initializeStateVariables(ContractDefinition const& _contract) { - for(ASTPointer const& variable: _contract.getStateVariables()) + for (ASTPointer const& variable: _contract.getStateVariables()) if (variable->getValue()) { compileExpression(*(variable->getValue()), (variable->getValue())->getType()); diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp index 74dfb2b5e..c2a10ab45 100644 --- a/ExpressionCompiler.cpp +++ b/ExpressionCompiler.cpp @@ -64,7 +64,7 @@ void ExpressionCompiler::appendStateVariableInitialization(CompilerContext& _con void ExpressionCompiler::appendStateVariableInitialization(VariableDeclaration const& _varDecl) { - m_currentLValue.fromStateVariable(_varDecl); + m_currentLValue.fromVariableDeclaration(_varDecl); m_currentLValue.storeValue(*_varDecl.getType(), _varDecl.getLocation()); m_currentLValue.reset(); } @@ -1024,22 +1024,17 @@ void ExpressionCompiler::LValue::fromIdentifier(Identifier const& _identifier, D m_baseStackOffset = m_context->getBaseStackOffsetOfVariable(_declaration); } else if (m_context->isStateVariable(&_declaration)) - { - *m_context << m_context->getStorageLocationOfVariable(_declaration); - m_type = LValueType::Storage; - m_dataType = _identifier.getType(); - solAssert(m_dataType->getStorageSize() <= numeric_limits::max(), - "The storage size of " + m_dataType->toString() + " should fit in an unsigned"); - m_size = unsigned(m_dataType->getStorageSize()); - } + //{ + fromVariableDeclaration(_declaration); + //} else BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_identifier.getLocation()) << errinfo_comment("Identifier type not supported or identifier not found.")); } -void ExpressionCompiler::LValue::fromStateVariable(VariableDeclaration const& _declaration) +void ExpressionCompiler::LValue::fromVariableDeclaration(Declaration const& _declaration) { - solAssert(m_context->isStateVariable(&_declaration), "Not a state variable."); + //solAssert(m_context->isStateVariable(&_declaration), "Not a state variable."); *m_context << m_context->getStorageLocationOfVariable(_declaration); m_type = LValueType::Storage; m_dataType = _declaration.getType(); diff --git a/ExpressionCompiler.h b/ExpressionCompiler.h index 3567a9148..a29abc7f1 100644 --- a/ExpressionCompiler.h +++ b/ExpressionCompiler.h @@ -137,7 +137,7 @@ private: /// Set type according to the declaration and retrieve the reference. /// @a _declaration is the variable declaration - void fromStateVariable(VariableDeclaration const& _declaration); + void fromVariableDeclaration(const Declaration &_declaration); void reset() { m_type = LValueType::None; m_dataType.reset(); m_baseStackOffset = 0; m_size = 0; } From 858acaa1937ccc2f6cc13bb3076abc32c43789b0 Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Fri, 20 Feb 2015 12:27:39 +0100 Subject: [PATCH 3/5] corrected accept for variableDeclaration changes after code review --- AST.h | 2 +- ASTPrinter.cpp | 2 +- AST_accept.h | 17 ++++++++--------- Compiler.cpp | 3 --- ExpressionCompiler.cpp | 13 +++++++------ 5 files changed, 17 insertions(+), 20 deletions(-) diff --git a/AST.h b/AST.h index c7fd068d9..064457d3b 100644 --- a/AST.h +++ b/AST.h @@ -451,7 +451,7 @@ public: virtual bool isLValue() const override; - /// Checks that all parameters have allowed types and calls checkTypeRequirements on the body. + /// Calls checkTypeRequirments for all state variables. void checkTypeRequirements(); bool isLocalVariable() const { return !!dynamic_cast(getScope()); } bool isExternalFunctionParameter() const; diff --git a/ASTPrinter.cpp b/ASTPrinter.cpp index aead6abd8..209bb73e6 100644 --- a/ASTPrinter.cpp +++ b/ASTPrinter.cpp @@ -227,7 +227,7 @@ bool ASTPrinter::visit(Return const& _node) bool ASTPrinter::visit(VariableDeclarationStatement const& _node) { - writeLine("VariableDefinition"); + writeLine("VariableDeclarationStatement"); printSourcePart(_node); return goDeeper(); } diff --git a/AST_accept.h b/AST_accept.h index 217a565f0..b1577ecd3 100644 --- a/AST_accept.h +++ b/AST_accept.h @@ -196,17 +196,24 @@ void FunctionDefinition::accept(ASTConstVisitor& _visitor) const void VariableDeclaration::accept(ASTVisitor& _visitor) { if (_visitor.visit(*this)) + { if (m_typeName) m_typeName->accept(_visitor); + if (m_value) + m_value->accept(_visitor); + } _visitor.endVisit(*this); } void VariableDeclaration::accept(ASTConstVisitor& _visitor) const { if (_visitor.visit(*this)) + { if (m_typeName) m_typeName->accept(_visitor); - _visitor.endVisit(*this); + if (m_value) + m_value->accept(_visitor); + } } void ModifierDefinition::accept(ASTVisitor& _visitor) @@ -478,22 +485,14 @@ void ExpressionStatement::accept(ASTConstVisitor& _visitor) const void VariableDeclarationStatement::accept(ASTVisitor& _visitor) { if (_visitor.visit(*this)) - { m_variable->accept(_visitor); - if (m_variable->getValue()) - m_variable->getValue()->accept(_visitor); - } _visitor.endVisit(*this); } void VariableDeclarationStatement::accept(ASTConstVisitor& _visitor) const { if (_visitor.visit(*this)) - { m_variable->accept(_visitor); - if (m_variable->getValue()) - m_variable->getValue()->accept(_visitor); - } _visitor.endVisit(*this); } diff --git a/Compiler.cpp b/Compiler.cpp index bdc29fab9..23014da6c 100644 --- a/Compiler.cpp +++ b/Compiler.cpp @@ -253,10 +253,7 @@ void Compiler::initializeStateVariables(ContractDefinition const& _contract) { for (ASTPointer const& variable: _contract.getStateVariables()) if (variable->getValue()) - { - compileExpression(*(variable->getValue()), (variable->getValue())->getType()); ExpressionCompiler::appendStateVariableInitialization(m_context, *variable); - } } bool Compiler::visit(VariableDeclaration const& _variableDeclaration) diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp index c2a10ab45..653bf8298 100644 --- a/ExpressionCompiler.cpp +++ b/ExpressionCompiler.cpp @@ -58,15 +58,19 @@ void ExpressionCompiler::appendStateVariableAccessor(CompilerContext& _context, void ExpressionCompiler::appendStateVariableInitialization(CompilerContext& _context, VariableDeclaration const& _varDecl, bool _optimize) { + compileExpression(_context, *(_varDecl.getValue()), _optimize); + if (_varDecl.getValue()->getType()) + appendTypeConversion(_context, *(_varDecl.getValue())->getType(), *(_varDecl.getValue())->getType()); + ExpressionCompiler compiler(_context, _optimize); compiler.appendStateVariableInitialization(_varDecl); } void ExpressionCompiler::appendStateVariableInitialization(VariableDeclaration const& _varDecl) { - m_currentLValue.fromVariableDeclaration(_varDecl); - m_currentLValue.storeValue(*_varDecl.getType(), _varDecl.getLocation()); - m_currentLValue.reset(); + LValue lvalue = LValue(m_context); + lvalue.fromVariableDeclaration(_varDecl); + lvalue.storeValue(*_varDecl.getType(), _varDecl.getLocation()); } bool ExpressionCompiler::visit(Assignment const& _assignment) @@ -1024,9 +1028,7 @@ void ExpressionCompiler::LValue::fromIdentifier(Identifier const& _identifier, D m_baseStackOffset = m_context->getBaseStackOffsetOfVariable(_declaration); } else if (m_context->isStateVariable(&_declaration)) - //{ fromVariableDeclaration(_declaration); - //} else BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_identifier.getLocation()) << errinfo_comment("Identifier type not supported or identifier not found.")); @@ -1034,7 +1036,6 @@ void ExpressionCompiler::LValue::fromIdentifier(Identifier const& _identifier, D void ExpressionCompiler::LValue::fromVariableDeclaration(Declaration const& _declaration) { - //solAssert(m_context->isStateVariable(&_declaration), "Not a state variable."); *m_context << m_context->getStorageLocationOfVariable(_declaration); m_type = LValueType::Storage; m_dataType = _declaration.getType(); From d0c36795a0998f9ad143c01882cb33334cbd471c Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Fri, 20 Feb 2015 20:09:46 +0100 Subject: [PATCH 4/5] renamed fromIdentifier to fromStateVariable --- ExpressionCompiler.cpp | 29 +++++++++++++---------------- ExpressionCompiler.h | 8 ++------ 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp index 653bf8298..e76a8a795 100644 --- a/ExpressionCompiler.cpp +++ b/ExpressionCompiler.cpp @@ -69,7 +69,7 @@ void ExpressionCompiler::appendStateVariableInitialization(CompilerContext& _con void ExpressionCompiler::appendStateVariableInitialization(VariableDeclaration const& _varDecl) { LValue lvalue = LValue(m_context); - lvalue.fromVariableDeclaration(_varDecl); + lvalue.fromDeclaration(_varDecl, _varDecl.getValue()->getLocation()); lvalue.storeValue(*_varDecl.getType(), _varDecl.getLocation()); } @@ -588,7 +588,7 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier) m_context << m_context.getVirtualFunctionEntryLabel(*functionDef).pushTag(); else if (dynamic_cast(declaration)) { - m_currentLValue.fromIdentifier(_identifier, *declaration); + m_currentLValue.fromDeclaration(*declaration, _identifier.getLocation()); m_currentLValue.retrieveValueIfLValueNotRequested(_identifier); } else if (dynamic_cast(declaration)) @@ -1018,32 +1018,29 @@ ExpressionCompiler::LValue::LValue(CompilerContext& _compilerContext, LValueType m_size = unsigned(m_dataType->getSizeOnStack()); } -void ExpressionCompiler::LValue::fromIdentifier(Identifier const& _identifier, Declaration const& _declaration) +void ExpressionCompiler::LValue::fromDeclaration(Declaration const& _declaration, Location const& _location) { if (m_context->isLocalVariable(&_declaration)) { m_type = LValueType::Stack; - m_dataType = _identifier.getType(); + m_dataType = _declaration.getType(); m_size = m_dataType->getSizeOnStack(); m_baseStackOffset = m_context->getBaseStackOffsetOfVariable(_declaration); } else if (m_context->isStateVariable(&_declaration)) - fromVariableDeclaration(_declaration); + { + *m_context << m_context->getStorageLocationOfVariable(_declaration); + m_type = LValueType::Storage; + m_dataType = _declaration.getType(); + solAssert(m_dataType->getStorageSize() <= numeric_limits::max(), + "The storage size of " + m_dataType->toString() + " should fit in an unsigned"); + m_size = unsigned(m_dataType->getStorageSize()); + } else - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_identifier.getLocation()) + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_location) << errinfo_comment("Identifier type not supported or identifier not found.")); } -void ExpressionCompiler::LValue::fromVariableDeclaration(Declaration const& _declaration) -{ - *m_context << m_context->getStorageLocationOfVariable(_declaration); - m_type = LValueType::Storage; - m_dataType = _declaration.getType(); - solAssert(m_dataType->getStorageSize() <= numeric_limits::max(), - "The storage size of " + m_dataType->toString() + " should fit in an unsigned"); - m_size = unsigned(m_dataType->getStorageSize()); -} - void ExpressionCompiler::LValue::retrieveValue(Location const& _location, bool _remove) const { switch (m_type) diff --git a/ExpressionCompiler.h b/ExpressionCompiler.h index a29abc7f1..889c58b19 100644 --- a/ExpressionCompiler.h +++ b/ExpressionCompiler.h @@ -132,12 +132,8 @@ private: std::shared_ptr const& _dataType, unsigned _baseStackOffset = 0); /// Set type according to the declaration and retrieve the reference. - /// @a _identifier is the current identifier - void fromIdentifier(Identifier const& _identifier, Declaration const& _declaration); - - /// Set type according to the declaration and retrieve the reference. - /// @a _declaration is the variable declaration - void fromVariableDeclaration(const Declaration &_declaration); + /// @a _location is the current location + void fromDeclaration(Declaration const& _declaration, Location const& _location); void reset() { m_type = LValueType::None; m_dataType.reset(); m_baseStackOffset = 0; m_size = 0; } From fa3cd1cdc2b9e328e46508de6cd4b0fdaab62f84 Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Fri, 20 Feb 2015 23:04:32 +0100 Subject: [PATCH 5/5] renamed local vaiable in fromDeclaration added missing endvisit --- AST_accept.h | 1 + ExpressionCompiler.cpp | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/AST_accept.h b/AST_accept.h index b1577ecd3..5bd6993db 100644 --- a/AST_accept.h +++ b/AST_accept.h @@ -214,6 +214,7 @@ void VariableDeclaration::accept(ASTConstVisitor& _visitor) const if (m_value) m_value->accept(_visitor); } + _visitor.endVisit(*this); } void ModifierDefinition::accept(ASTVisitor& _visitor) diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp index e76a8a795..461dfef14 100644 --- a/ExpressionCompiler.cpp +++ b/ExpressionCompiler.cpp @@ -68,9 +68,9 @@ void ExpressionCompiler::appendStateVariableInitialization(CompilerContext& _con void ExpressionCompiler::appendStateVariableInitialization(VariableDeclaration const& _varDecl) { - LValue lvalue = LValue(m_context); - lvalue.fromDeclaration(_varDecl, _varDecl.getValue()->getLocation()); - lvalue.storeValue(*_varDecl.getType(), _varDecl.getLocation()); + LValue var = LValue(m_context); + var.fromDeclaration(_varDecl, _varDecl.getValue()->getLocation()); + var.storeValue(*_varDecl.getType(), _varDecl.getLocation()); } bool ExpressionCompiler::visit(Assignment const& _assignment)