diff options
-rw-r--r-- | AST.cpp | 13 | ||||
-rw-r--r--[-rwxr-xr-x] | AST.h | 3 | ||||
-rw-r--r-- | ExpressionCompiler.cpp | 47 | ||||
-rw-r--r-- | Parser.cpp | 16 | ||||
-rw-r--r-- | Scanner.cpp | 5 | ||||
-rw-r--r-- | Types.cpp | 71 | ||||
-rw-r--r-- | Types.h | 3 | ||||
-rw-r--r--[-rwxr-xr-x] | Utils.h | 0 |
8 files changed, 91 insertions, 67 deletions
@@ -383,6 +383,8 @@ void VariableDefinition::checkTypeRequirements() BOOST_THROW_EXCEPTION(m_value->createTypeError("Invalid integer constant " + type->toString())); type = intType; } + else if (type->getCategory() == Type::Category::VOID) + BOOST_THROW_EXCEPTION(m_variable->createTypeError("var cannot be void type")); m_variable->setType(type); } } @@ -597,17 +599,6 @@ void ElementaryTypeNameExpression::checkTypeRequirements() 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() { m_type = Type::forLiteral(*this); @@ -1127,7 +1127,8 @@ public: }; Literal(Location const& _location, Token::Value _token, ASTPointer<ASTString> const& _value, - Token::Value _sub = Token::ILLEGAL); + SubDenomination _sub = SubDenomination::None): + PrimaryExpression(_location), m_token(_token), m_value(_value), m_subDenomination(_sub) {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; virtual void checkTypeRequirements() override; diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp index cd133222..4a1110db 100644 --- a/ExpressionCompiler.cpp +++ b/ExpressionCompiler.cpp @@ -887,19 +887,17 @@ unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedT void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& _varDecl) { - FunctionType thisType(_varDecl); - solAssert(thisType.getReturnParameterTypes().size() == 1, ""); - TypePointer const& resultType = thisType.getReturnParameterTypes().front(); - unsigned sizeOnStack; + FunctionType accessorType(_varDecl); unsigned length = 0; - TypePointers const& params = thisType.getParameterTypes(); + TypePointers const& params = accessorType.getParameterTypes(); // move arguments to memory for (TypePointer const& param: boost::adaptors::reverse(params)) length += appendTypeConversionAndMoveToMemory(*param, *param, Location(), length); - // retrieve the position of the mapping + // retrieve the position of the variable m_context << m_context.getStorageLocationOfVariable(_varDecl); + TypePointer returnType = _varDecl.getType(); for (TypePointer const& param: params) { @@ -908,13 +906,40 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& unsigned argLen = CompilerUtils::getPaddedSize(param->getCalldataEncodedSize()); length -= argLen; m_context << u256(argLen + 32) << u256(length) << eth::Instruction::SHA3; + + returnType = dynamic_cast<MappingType const&>(*returnType).getValueType(); } - m_currentLValue = LValue(m_context, LValue::STORAGE, *resultType); - m_currentLValue.retrieveValue(resultType, Location(), true); - sizeOnStack = resultType->getSizeOnStack(); - solAssert(sizeOnStack <= 15, "Stack too deep."); - m_context << eth::dupInstruction(sizeOnStack + 1) << eth::Instruction::JUMP; + unsigned retSizeOnStack = 0; + solAssert(accessorType.getReturnParameterTypes().size() >= 1, ""); + if (StructType const* structType = dynamic_cast<StructType const*>(returnType.get())) + { + auto const& names = accessorType.getReturnParameterNames(); + auto const& types = accessorType.getReturnParameterTypes(); + // struct + for (size_t i = 0; i < names.size(); ++i) + { + m_context << eth::Instruction::DUP1 + << structType->getStorageOffsetOfMember(names[i]) + << eth::Instruction::ADD; + m_currentLValue = LValue(m_context, LValue::STORAGE, *types[i]); + m_currentLValue.retrieveValue(types[i], Location(), true); + solAssert(types[i]->getSizeOnStack() == 1, "Returning struct elements with stack size != 1 not yet implemented."); + m_context << eth::Instruction::SWAP1; + retSizeOnStack += types[i]->getSizeOnStack(); + } + m_context << eth::Instruction::POP; + } + else + { + // simple value + solAssert(accessorType.getReturnParameterTypes().size() == 1, ""); + m_currentLValue = LValue(m_context, LValue::STORAGE, *returnType); + m_currentLValue.retrieveValue(returnType, Location(), true); + retSizeOnStack = returnType->getSizeOnStack(); + } + solAssert(retSizeOnStack <= 15, "Stack too deep."); + m_context << eth::dupInstruction(retSizeOnStack + 1) << eth::Instruction::JUMP; } ExpressionCompiler::LValue::LValue(CompilerContext& _compilerContext, LValueType _type, Type const& _dataType, @@ -684,7 +684,6 @@ ASTPointer<Expression> Parser::parsePrimaryExpression() ASTNodeFactory nodeFactory(*this); Token::Value token = m_scanner->getCurrentToken(); ASTPointer<Expression> expression; - Token::Value nextToken = Token::ILLEGAL; switch (token) { case Token::TRUE_LITERAL: @@ -692,12 +691,19 @@ ASTPointer<Expression> Parser::parsePrimaryExpression() expression = nodeFactory.createNode<Literal>(token, getLiteralAndAdvance()); break; case Token::NUMBER: - nextToken = m_scanner->peekNextToken(); + if (Token::isEtherSubdenomination(m_scanner->peekNextToken())) + { + ASTPointer<ASTString> literal = getLiteralAndAdvance(); + nodeFactory.markEndPosition(); + Literal::SubDenomination subdenomination = static_cast<Literal::SubDenomination>(m_scanner->getCurrentToken()); + m_scanner->next(); + expression = nodeFactory.createNode<Literal>(token, literal, subdenomination); + break; + } + // fall-through case Token::STRING_LITERAL: nodeFactory.markEndPosition(); - expression = nodeFactory.createNode<Literal>(token, getLiteralAndAdvance(), nextToken); - if (Token::isEtherSubdenomination(nextToken)) - m_scanner->next(); + expression = nodeFactory.createNode<Literal>(token, getLiteralAndAdvance()); break; case Token::IDENTIFIER: nodeFactory.markEndPosition(); diff --git a/Scanner.cpp b/Scanner.cpp index b283ca10..6a8ecd9d 100644 --- a/Scanner.cpp +++ b/Scanner.cpp @@ -458,10 +458,7 @@ void Scanner::scanToken() // - -- -= advance(); if (m_char == '-') - { - advance(); - token = Token::DEC; - } + token = selectToken(Token::DEC); else if (m_char == '=') token = selectToken(Token::ASSIGN_SUB); else @@ -91,7 +91,7 @@ shared_ptr<Type const> Type::forLiteral(Literal const& _literal) case Token::FALSE_LITERAL: return make_shared<BoolType>(); case Token::NUMBER: - return IntegerConstantType::fromLiteral(_literal.getValue()); + return make_shared<IntegerConstantType>(_literal); case Token::STRING_LITERAL: //@todo put larger strings into dynamic strings return StaticStringType::smallestTypeForLiteral(_literal.getValue()); @@ -216,9 +216,25 @@ const MemberList IntegerType::AddressMemberList = strings{}, FunctionType::Location::BARE)}, {"send", make_shared<FunctionType>(strings{"uint"}, strings{}, FunctionType::Location::SEND)}}); -shared_ptr<IntegerConstantType const> IntegerConstantType::fromLiteral(string const& _literal) +IntegerConstantType::IntegerConstantType(Literal const& _literal) { - return make_shared<IntegerConstantType>(bigint(_literal)); + m_value = bigint(_literal.getValue()); + + switch (_literal.getSubDenomination()) + { + case Literal::SubDenomination::Wei: + case Literal::SubDenomination::None: + break; + case Literal::SubDenomination::Szabo: + m_value *= bigint("1000000000000"); + break; + case Literal::SubDenomination::Finney: + m_value *= bigint("1000000000000000"); + break; + case Literal::SubDenomination::Ether: + m_value *= bigint("1000000000000000000"); + break; + } } bool IntegerConstantType::isImplicitlyConvertibleTo(Type const& _convertTo) const @@ -326,7 +342,7 @@ string IntegerConstantType::toString() const return "int_const " + m_value.str(); } -u256 IntegerConstantType::literalValue(Literal const* _literal) const +u256 IntegerConstantType::literalValue(Literal const*) const { u256 value; // we ignore the literal and hope that the type was correctly determined @@ -338,26 +354,6 @@ u256 IntegerConstantType::literalValue(Literal const* _literal) const else 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; } @@ -654,22 +650,31 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl): { TypePointers params; vector<string> paramNames; - TypePointers retParams; - vector<string> retParamNames; - TypePointer varDeclType = _varDecl.getType(); - auto mappingType = dynamic_cast<MappingType const*>(varDeclType.get()); - auto returnType = varDeclType; + auto returnType = _varDecl.getType(); - while (mappingType != nullptr) + while (auto mappingType = dynamic_cast<MappingType const*>(returnType.get())) { params.push_back(mappingType->getKeyType()); paramNames.push_back(""); returnType = mappingType->getValueType(); - mappingType = dynamic_cast<MappingType const*>(mappingType->getValueType().get()); } - retParams.push_back(returnType); - retParamNames.push_back(""); + TypePointers retParams; + vector<string> retParamNames; + if (auto structType = dynamic_cast<StructType const*>(returnType.get())) + { + for (pair<string, TypePointer> const& member: structType->getMembers()) + if (member.second->canLiveOutsideStorage()) + { + retParamNames.push_back(member.first); + retParams.push_back(member.second); + } + } + else + { + retParams.push_back(returnType); + retParamNames.push_back(""); + } swap(params, m_parameterTypes); swap(paramNames, m_parameterNames); @@ -200,8 +200,7 @@ class IntegerConstantType: public Type public: virtual Category getCategory() const override { return Category::INTEGER_CONSTANT; } - static std::shared_ptr<IntegerConstantType const> fromLiteral(std::string const& _literal); - + explicit IntegerConstantType(Literal const& _literal); explicit IntegerConstantType(bigint _value): m_value(_value) {} virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; |