aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AST.cpp13
-rw-r--r--[-rwxr-xr-x]AST.h3
-rw-r--r--ExpressionCompiler.cpp47
-rw-r--r--Parser.cpp16
-rw-r--r--Scanner.cpp5
-rw-r--r--Types.cpp71
-rw-r--r--Types.h3
-rw-r--r--[-rwxr-xr-x]Utils.h0
8 files changed, 91 insertions, 67 deletions
diff --git a/AST.cpp b/AST.cpp
index 26897dda..6f5b1f38 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -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);
diff --git a/AST.h b/AST.h
index bced99f9..47f2a40c 100755..100644
--- a/AST.h
+++ b/AST.h
@@ -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,
diff --git a/Parser.cpp b/Parser.cpp
index 741b9aba..d8c15c36 100644
--- a/Parser.cpp
+++ b/Parser.cpp
@@ -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
diff --git a/Types.cpp b/Types.cpp
index 6a128202..7a7672c6 100644
--- a/Types.cpp
+++ b/Types.cpp
@@ -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);
diff --git a/Types.h b/Types.h
index fcd6d956..7118f746 100644
--- a/Types.h
+++ b/Types.h
@@ -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;
diff --git a/Utils.h b/Utils.h
index 1411f66b..1411f66b 100755..100644
--- a/Utils.h
+++ b/Utils.h