Browse Source

Merge branch 'develop' of github.com:ethereum/cpp-ethereum into develop

cl-refactor
Gav Wood 10 years ago
parent
commit
761da78505
  1. 39
      libsolidity/AST.cpp
  2. 2
      libsolidity/AST.h
  3. 4
      libsolidity/DeclarationContainer.cpp
  4. 4
      libsolidity/DeclarationContainer.h
  5. 58
      libsolidity/ExpressionCompiler.cpp
  6. 23
      libsolidity/ExpressionCompiler.h
  7. 26
      libsolidity/Parser.cpp
  8. 1
      libsolidity/Parser.h
  9. 5
      libsolidity/Scanner.cpp
  10. 7
      libsolidity/Types.cpp
  11. 5
      libsolidity/Types.h
  12. 0
      libsolidity/Utils.h
  13. 6
      mix/ClientModel.cpp
  14. 21
      mix/qml/FilesSection.qml
  15. 19
      mix/qml/ProjectList.qml
  16. 9
      mix/qml/Style.qml
  17. 58
      mix/qml/TransactionDialog.qml
  18. 2
      mix/qml/js/ProjectModel.js
  19. 71
      test/SolidityABIJSON.cpp
  20. 90
      test/SolidityEndToEndTest.cpp
  21. 42
      test/SolidityNameAndTypeResolution.cpp

39
libsolidity/AST.cpp

@ -58,11 +58,19 @@ void ContractDefinition::checkTypeRequirements()
BOOST_THROW_EXCEPTION(constructor->getReturnParameterList()->createTypeError( BOOST_THROW_EXCEPTION(constructor->getReturnParameterList()->createTypeError(
"Non-empty \"returns\" directive for constructor.")); "Non-empty \"returns\" directive for constructor."));
FunctionDefinition const* fallbackFunction = getFallbackFunction(); FunctionDefinition const* fallbackFunction = nullptr;
if (fallbackFunction && fallbackFunction->getScope() == this && !fallbackFunction->getParameters().empty()) for (ASTPointer<FunctionDefinition> const& function: getDefinedFunctions())
BOOST_THROW_EXCEPTION(fallbackFunction->getParameterList().createTypeError( if (function->getName().empty())
"Fallback function cannot take parameters.")); {
if (fallbackFunction)
BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_comment("Only one fallback function is allowed."));
else
{
fallbackFunction = function.get();
if (!fallbackFunction->getParameters().empty())
BOOST_THROW_EXCEPTION(fallbackFunction->getParameterList().createTypeError("Fallback function cannot take parameters."));
}
}
for (ASTPointer<ModifierDefinition> const& modifier: getFunctionModifiers()) for (ASTPointer<ModifierDefinition> const& modifier: getFunctionModifiers())
modifier->checkTypeRequirements(); modifier->checkTypeRequirements();
@ -478,7 +486,7 @@ void FunctionCall::checkTypeRequirements()
if (m_arguments.size() != 1) if (m_arguments.size() != 1)
BOOST_THROW_EXCEPTION(createTypeError("More than one argument for explicit type conversion.")); BOOST_THROW_EXCEPTION(createTypeError("More than one argument for explicit type conversion."));
if (!m_names.empty()) if (!m_names.empty())
BOOST_THROW_EXCEPTION(createTypeError("Type conversion can't allow named arguments.")); BOOST_THROW_EXCEPTION(createTypeError("Type conversion cannot allow named arguments."));
if (!m_arguments.front()->getType()->isExplicitlyConvertibleTo(*type.getActualType())) if (!m_arguments.front()->getType()->isExplicitlyConvertibleTo(*type.getActualType()))
BOOST_THROW_EXCEPTION(createTypeError("Explicit type conversion not allowed.")); BOOST_THROW_EXCEPTION(createTypeError("Explicit type conversion not allowed."));
m_type = type.getActualType(); m_type = type.getActualType();
@ -489,28 +497,29 @@ void FunctionCall::checkTypeRequirements()
// and then ask if that is implicitly convertible to the struct represented by the // and then ask if that is implicitly convertible to the struct represented by the
// function parameters // function parameters
TypePointers const& parameterTypes = functionType->getParameterTypes(); TypePointers const& parameterTypes = functionType->getParameterTypes();
if (parameterTypes.size() != m_arguments.size()) if (functionType->getLocation() != FunctionType::Location::SHA3 && parameterTypes.size() != m_arguments.size())
BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for function call.")); BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for function call."));
if (m_names.empty()) if (m_names.empty())
{ {
for (size_t i = 0; i < m_arguments.size(); ++i) for (size_t i = 0; i < m_arguments.size(); ++i)
if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i])) if (functionType->getLocation() != FunctionType::Location::SHA3 &&
BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in function call.")); !m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i]))
BOOST_THROW_EXCEPTION(m_arguments[i]->createTypeError("Invalid type for argument in function call."));
} }
else else
{ {
if (functionType->getLocation() == FunctionType::Location::SHA3)
BOOST_THROW_EXCEPTION(createTypeError("Named arguments cannnot be used for SHA3."));
auto const& parameterNames = functionType->getParameterNames(); auto const& parameterNames = functionType->getParameterNames();
if (parameterNames.size() != m_names.size()) if (parameterNames.size() != m_names.size())
BOOST_THROW_EXCEPTION(createTypeError("Some argument names are missing.")); BOOST_THROW_EXCEPTION(createTypeError("Some argument names are missing."));
// check duplicate names // check duplicate names
for (size_t i = 0; i < m_names.size(); i++) { for (size_t i = 0; i < m_names.size(); i++)
for (size_t j = i + 1; j < m_names.size(); j++) { for (size_t j = i + 1; j < m_names.size(); j++)
if (*m_names[i] == *m_names[j]) if (*m_names[i] == *m_names[j])
BOOST_THROW_EXCEPTION(createTypeError("Duplicate named argument.")); BOOST_THROW_EXCEPTION(m_arguments[i]->createTypeError("Duplicate named argument."));
}
}
for (size_t i = 0; i < m_names.size(); i++) { for (size_t i = 0; i < m_names.size(); i++) {
bool found = false; bool found = false;
@ -525,7 +534,7 @@ void FunctionCall::checkTypeRequirements()
} }
} }
if (!found) if (!found)
BOOST_THROW_EXCEPTION(createTypeError("Named argument doesn't match function declaration.")); BOOST_THROW_EXCEPTION(createTypeError("Named argument does not match function declaration."));
} }
} }

2
libsolidity/AST.h

@ -250,7 +250,7 @@ public:
/// Returns the constructor or nullptr if no constructor was specified. /// Returns the constructor or nullptr if no constructor was specified.
FunctionDefinition const* getConstructor() const; FunctionDefinition const* getConstructor() const;
/// Returns the fallback function or nullptr if no constructor was specified. /// Returns the fallback function or nullptr if no fallback function was specified.
FunctionDefinition const* getFallbackFunction() const; FunctionDefinition const* getFallbackFunction() const;
private: private:

4
libsolidity/DeclarationContainer.cpp

@ -30,6 +30,9 @@ namespace solidity
bool DeclarationContainer::registerDeclaration(Declaration const& _declaration, bool _update) bool DeclarationContainer::registerDeclaration(Declaration const& _declaration, bool _update)
{ {
if (_declaration.getName().empty())
return true;
if (!_update && m_declarations.find(_declaration.getName()) != m_declarations.end()) if (!_update && m_declarations.find(_declaration.getName()) != m_declarations.end())
return false; return false;
m_declarations[_declaration.getName()] = &_declaration; m_declarations[_declaration.getName()] = &_declaration;
@ -38,6 +41,7 @@ bool DeclarationContainer::registerDeclaration(Declaration const& _declaration,
Declaration const* DeclarationContainer::resolveName(ASTString const& _name, bool _recursive) const Declaration const* DeclarationContainer::resolveName(ASTString const& _name, bool _recursive) const
{ {
solAssert(!_name.empty(), "Attempt to resolve empty name.");
auto result = m_declarations.find(_name); auto result = m_declarations.find(_name);
if (result != m_declarations.end()) if (result != m_declarations.end())
return result->second; return result->second;

4
libsolidity/DeclarationContainer.h

@ -42,8 +42,8 @@ public:
explicit DeclarationContainer(Declaration const* _enclosingDeclaration = nullptr, explicit DeclarationContainer(Declaration const* _enclosingDeclaration = nullptr,
DeclarationContainer const* _enclosingContainer = nullptr): DeclarationContainer const* _enclosingContainer = nullptr):
m_enclosingDeclaration(_enclosingDeclaration), m_enclosingContainer(_enclosingContainer) {} m_enclosingDeclaration(_enclosingDeclaration), m_enclosingContainer(_enclosingContainer) {}
/// Registers the declaration in the scope unless its name is already declared. /// Registers the declaration in the scope unless its name is already declared or the name is empty.
/// @returns true iff it was not yet declared. /// @returns false if the name was already declared.
bool registerDeclaration(Declaration const& _declaration, bool _update = false); bool registerDeclaration(Declaration const& _declaration, bool _update = false);
Declaration const* resolveName(ASTString const& _name, bool _recursive = false) const; Declaration const* resolveName(ASTString const& _name, bool _recursive = false) const;
Declaration const* getEnclosingDeclaration() const { return m_enclosingDeclaration; } Declaration const* getEnclosingDeclaration() const { return m_enclosingDeclaration; }

58
libsolidity/ExpressionCompiler.cpp

@ -206,7 +206,8 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
TypePointers const& parameterTypes = function.getParameterTypes(); TypePointers const& parameterTypes = function.getParameterTypes();
vector<ASTPointer<Expression const>> const& callArguments = _functionCall.getArguments(); vector<ASTPointer<Expression const>> const& callArguments = _functionCall.getArguments();
vector<ASTPointer<ASTString>> const& callArgumentNames = _functionCall.getNames(); vector<ASTPointer<ASTString>> const& callArgumentNames = _functionCall.getNames();
solAssert(callArguments.size() == parameterTypes.size(), ""); if (function.getLocation() != Location::SHA3)
solAssert(callArguments.size() == parameterTypes.size(), "");
vector<ASTPointer<Expression const>> arguments; vector<ASTPointer<Expression const>> arguments;
if (callArgumentNames.empty()) if (callArgumentNames.empty())
@ -274,7 +275,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
m_context << u256(0) << eth::Instruction::CODECOPY; m_context << u256(0) << eth::Instruction::CODECOPY;
unsigned length = bytecode.size(); unsigned length = bytecode.size();
length += appendArgumentCopyToMemory(function.getParameterTypes(), arguments, length); length += appendArgumentsCopyToMemory(arguments, function.getParameterTypes(), length);
// size, offset, endowment // size, offset, endowment
m_context << u256(length) << u256(0); m_context << u256(length) << u256(0);
if (function.valueSet()) if (function.valueSet())
@ -325,9 +326,11 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
m_context << eth::Instruction::SUICIDE; m_context << eth::Instruction::SUICIDE;
break; break;
case Location::SHA3: case Location::SHA3:
appendExpressionCopyToMemory(*function.getParameterTypes().front(), *arguments.front()); {
m_context << u256(32) << u256(0) << eth::Instruction::SHA3; unsigned length = appendArgumentsCopyToMemory(arguments, TypePointers(), 0, false);
m_context << u256(length) << u256(0) << eth::Instruction::SHA3;
break; break;
}
case Location::LOG0: case Location::LOG0:
case Location::LOG1: case Location::LOG1:
case Location::LOG2: case Location::LOG2:
@ -797,7 +800,7 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio
// reserve space for the function identifier // reserve space for the function identifier
unsigned dataOffset = bare ? 0 : CompilerUtils::dataStartOffset; unsigned dataOffset = bare ? 0 : CompilerUtils::dataStartOffset;
dataOffset += appendArgumentCopyToMemory(_functionType.getParameterTypes(), _arguments, dataOffset); dataOffset += appendArgumentsCopyToMemory(_arguments, _functionType.getParameterTypes(), dataOffset);
//@todo only return the first return value for now //@todo only return the first return value for now
Type const* firstType = _functionType.getReturnParameterTypes().empty() ? nullptr : Type const* firstType = _functionType.getReturnParameterTypes().empty() ? nullptr :
@ -833,28 +836,34 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio
} }
} }
unsigned ExpressionCompiler::appendArgumentCopyToMemory(TypePointers const& _types, unsigned ExpressionCompiler::appendArgumentsCopyToMemory(vector<ASTPointer<Expression const>> const& _arguments,
vector<ASTPointer<Expression const>> const& _arguments, TypePointers const& _types,
unsigned _memoryOffset) unsigned _memoryOffset,
bool _padToWordBoundaries)
{ {
solAssert(_types.empty() || _types.size() == _arguments.size(), "");
unsigned length = 0; unsigned length = 0;
for (unsigned i = 0; i < _arguments.size(); ++i) for (size_t i = 0; i < _arguments.size(); ++i)
length += appendExpressionCopyToMemory(*_types[i], *_arguments[i], _memoryOffset + length); {
_arguments[i]->accept(*this);
TypePointer const& expectedType = _types.empty() ? _arguments[i]->getType()->getRealType() : _types[i];
appendTypeConversion(*_arguments[i]->getType(), *expectedType, true);
length += appendTypeMoveToMemory(*expectedType, _arguments[i]->getLocation(),
_memoryOffset + length, _padToWordBoundaries);
}
return length; return length;
} }
unsigned ExpressionCompiler::appendTypeConversionAndMoveToMemory(Type const& _expectedType, Type const& _type, unsigned ExpressionCompiler::appendTypeMoveToMemory(Type const& _type, Location const& _location, unsigned _memoryOffset, bool _padToWordBoundaries)
Location const& _location, unsigned _memoryOffset)
{ {
appendTypeConversion(_type, _expectedType, true); unsigned const c_encodedSize = _type.getCalldataEncodedSize();
unsigned const c_numBytes = CompilerUtils::getPaddedSize(_expectedType.getCalldataEncodedSize()); unsigned const c_numBytes = _padToWordBoundaries ? CompilerUtils::getPaddedSize(c_encodedSize) : c_encodedSize;
if (c_numBytes == 0 || c_numBytes > 32) if (c_numBytes == 0 || c_numBytes > 32)
BOOST_THROW_EXCEPTION(CompilerError() BOOST_THROW_EXCEPTION(CompilerError()
<< errinfo_sourceLocation(_location) << errinfo_sourceLocation(_location)
<< errinfo_comment("Type " + _expectedType.toString() + " not yet supported.")); << errinfo_comment("Type " + _type.toString() + " not yet supported."));
bool const c_leftAligned = _expectedType.getCategory() == Type::Category::STRING; bool const c_leftAligned = _type.getCategory() == Type::Category::STRING;
bool const c_padToWords = true; return CompilerUtils(m_context).storeInMemory(_memoryOffset, c_numBytes, c_leftAligned, _padToWordBoundaries);
return CompilerUtils(m_context).storeInMemory(_memoryOffset, c_numBytes, c_leftAligned, c_padToWords);
} }
unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType, unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType,
@ -862,7 +871,8 @@ unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedT
unsigned _memoryOffset) unsigned _memoryOffset)
{ {
_expression.accept(*this); _expression.accept(*this);
return appendTypeConversionAndMoveToMemory(_expectedType, *_expression.getType(), _expression.getLocation(), _memoryOffset); appendTypeConversion(*_expression.getType(), _expectedType, true);
return appendTypeMoveToMemory(_expectedType, _expression.getLocation(), _memoryOffset);
} }
void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& _varDecl) void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& _varDecl)
@ -870,20 +880,20 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
FunctionType accessorType(_varDecl); FunctionType accessorType(_varDecl);
unsigned length = 0; unsigned length = 0;
TypePointers const& params = accessorType.getParameterTypes(); TypePointers const& paramTypes = accessorType.getParameterTypes();
// move arguments to memory // move arguments to memory
for (TypePointer const& param: boost::adaptors::reverse(params)) for (TypePointer const& paramType: boost::adaptors::reverse(paramTypes))
length += appendTypeConversionAndMoveToMemory(*param, *param, Location(), length); length += appendTypeMoveToMemory(*paramType, Location(), length);
// retrieve the position of the variable // retrieve the position of the variable
m_context << m_context.getStorageLocationOfVariable(_varDecl); m_context << m_context.getStorageLocationOfVariable(_varDecl);
TypePointer returnType = _varDecl.getType(); TypePointer returnType = _varDecl.getType();
for (TypePointer const& param: params) for (TypePointer const& paramType: paramTypes)
{ {
// move offset to memory // move offset to memory
CompilerUtils(m_context).storeInMemory(length); CompilerUtils(m_context).storeInMemory(length);
unsigned argLen = CompilerUtils::getPaddedSize(param->getCalldataEncodedSize()); unsigned argLen = CompilerUtils::getPaddedSize(paramType->getCalldataEncodedSize());
length -= argLen; length -= argLen;
m_context << u256(argLen + 32) << u256(length) << eth::Instruction::SHA3; m_context << u256(argLen + 32) << u256(length) << eth::Instruction::SHA3;

23
libsolidity/ExpressionCompiler.h

@ -92,17 +92,18 @@ private:
/// Appends code to call a function of the given type with the given arguments. /// Appends code to call a function of the given type with the given arguments.
void appendExternalFunctionCall(FunctionType const& _functionType, std::vector<ASTPointer<Expression const>> const& _arguments, void appendExternalFunctionCall(FunctionType const& _functionType, std::vector<ASTPointer<Expression const>> const& _arguments,
bool bare = false); bool bare = false);
/// Appends code that copies the given arguments to memory (with optional offset). /// Appends code that evaluates the given arguments and moves the result to memory (with optional offset).
/// @returns the number of bytes copied to memory /// @returns the number of bytes moved to memory
unsigned appendArgumentCopyToMemory(TypePointers const& _types, unsigned appendArgumentsCopyToMemory(std::vector<ASTPointer<Expression const>> const& _arguments,
std::vector<ASTPointer<Expression const>> const& _arguments, TypePointers const& _types = {},
unsigned _memoryOffset = 0); unsigned _memoryOffset = 0,
/// Appends code that copies a type to memory. bool _padToWordBoundaries = true);
/// @returns the number of bytes copied to memory /// Appends code that moves a stack element of the given type to memory
unsigned appendTypeConversionAndMoveToMemory(Type const& _expectedType, Type const& _type, /// @returns the number of bytes moved to memory
Location const& _location, unsigned _memoryOffset = 0); unsigned appendTypeMoveToMemory(Type const& _type, Location const& _location, unsigned _memoryOffset,
/// Appends code that evaluates a single expression and copies it to memory (with optional offset). bool _padToWordBoundaries = true);
/// @returns the number of bytes copied to memory /// Appends code that evaluates a single expression and moves the result to memory (with optional offset).
/// @returns the number of bytes moved to memory
unsigned appendExpressionCopyToMemory(Type const& _expectedType, Expression const& _expression, unsigned appendExpressionCopyToMemory(Type const& _expectedType, Expression const& _expression,
unsigned _memoryOffset = 0); unsigned _memoryOffset = 0);

26
libsolidity/Parser.cpp

@ -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::DEFAULT; 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)
@ -267,20 +267,31 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(VarDeclParserOp
{ {
ASTNodeFactory nodeFactory(*this); ASTNodeFactory nodeFactory(*this);
ASTPointer<TypeName> type = parseTypeName(_options.allowVar); ASTPointer<TypeName> type = parseTypeName(_options.allowVar);
if (type != nullptr)
nodeFactory.setEndPositionFromNode(type);
bool isIndexed = false; bool isIndexed = false;
ASTPointer<ASTString> identifier;
Token::Value token = m_scanner->getCurrentToken(); Token::Value token = m_scanner->getCurrentToken();
Declaration::Visibility visibility(Declaration::Visibility::DEFAULT);
if (_options.isStateVariable && Token::isVisibilitySpecifier(token))
visibility = parseVisibilitySpecifier(token);
if (_options.allowIndexed && token == Token::INDEXED) if (_options.allowIndexed && token == Token::INDEXED)
{ {
isIndexed = true; isIndexed = true;
m_scanner->next(); m_scanner->next();
} }
Declaration::Visibility visibility(Declaration::Visibility::DEFAULT);
if (_options.isStateVariable && Token::isVisibilitySpecifier(token))
visibility = parseVisibilitySpecifier(token);
nodeFactory.markEndPosition(); nodeFactory.markEndPosition();
return nodeFactory.createNode<VariableDeclaration>(type, expectIdentifierToken(), if (_options.allowEmptyName && m_scanner->getCurrentToken() != Token::IDENTIFIER)
visibility, _options.isStateVariable, {
isIndexed); identifier = make_shared<ASTString>("");
solAssert(type != nullptr, "");
nodeFactory.setEndPositionFromNode(type);
}
else
identifier = expectIdentifierToken();
return nodeFactory.createNode<VariableDeclaration>(type, identifier,
visibility, _options.isStateVariable,
isIndexed);
} }
ASTPointer<ModifierDefinition> Parser::parseModifierDefinition() ASTPointer<ModifierDefinition> Parser::parseModifierDefinition()
@ -402,6 +413,7 @@ ASTPointer<ParameterList> Parser::parseParameterList(bool _allowEmpty, bool _all
vector<ASTPointer<VariableDeclaration>> parameters; vector<ASTPointer<VariableDeclaration>> parameters;
VarDeclParserOptions options; VarDeclParserOptions options;
options.allowIndexed = _allowIndexed; options.allowIndexed = _allowIndexed;
options.allowEmptyName = true;
expectToken(Token::LPAREN); expectToken(Token::LPAREN);
if (!_allowEmpty || m_scanner->getCurrentToken() != Token::RPAREN) if (!_allowEmpty || m_scanner->getCurrentToken() != Token::RPAREN)
{ {

1
libsolidity/Parser.h

@ -50,6 +50,7 @@ private:
bool allowVar = false; bool allowVar = false;
bool isStateVariable = false; bool isStateVariable = false;
bool allowIndexed = false; bool allowIndexed = false;
bool allowEmptyName = false;
}; };
///@{ ///@{

5
libsolidity/Scanner.cpp

@ -458,10 +458,7 @@ void Scanner::scanToken()
// - -- -= // - -- -=
advance(); advance();
if (m_char == '-') if (m_char == '-')
{ token = selectToken(Token::DEC);
advance();
token = Token::DEC;
}
else if (m_char == '=') else if (m_char == '=')
token = selectToken(Token::ASSIGN_SUB); token = selectToken(Token::ASSIGN_SUB);
else else

7
libsolidity/Types.cpp

@ -357,6 +357,13 @@ u256 IntegerConstantType::literalValue(Literal const*) const
return value; return value;
} }
TypePointer IntegerConstantType::getRealType() const
{
auto intType = getIntegerType();
solAssert(!!intType, "getRealType called with invalid integer constant " + toString());
return intType;
}
shared_ptr<IntegerType const> IntegerConstantType::getIntegerType() const shared_ptr<IntegerType const> IntegerConstantType::getIntegerType() const
{ {
bigint value = m_value; bigint value = m_value;

5
libsolidity/Types.h

@ -130,6 +130,8 @@ public:
/// i.e. it behaves differently in lvalue context and in value context. /// i.e. it behaves differently in lvalue context and in value context.
virtual bool isValueType() const { return false; } virtual bool isValueType() const { return false; }
virtual unsigned getSizeOnStack() const { return 1; } virtual unsigned getSizeOnStack() const { return 1; }
/// @returns the real type of some types, like e.g: IntegerConstant
virtual TypePointer getRealType() const { return shared_from_this(); }
/// Returns the list of all members of this type. Default implementation: no members. /// Returns the list of all members of this type. Default implementation: no members.
virtual MemberList const& getMembers() const { return EmptyMemberList; } virtual MemberList const& getMembers() const { return EmptyMemberList; }
@ -140,7 +142,7 @@ public:
virtual u256 literalValue(Literal const*) const virtual u256 literalValue(Literal const*) const
{ {
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Literal value requested " BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Literal value requested "
"for type without literals.")); "for type without literals."));
} }
protected: protected:
@ -213,6 +215,7 @@ public:
virtual std::string toString() const override; virtual std::string toString() const override;
virtual u256 literalValue(Literal const* _literal) const override; virtual u256 literalValue(Literal const* _literal) const override;
virtual TypePointer getRealType() const override;
/// @returns the smallest integer type that can hold the value or an empty pointer if not possible. /// @returns the smallest integer type that can hold the value or an empty pointer if not possible.
std::shared_ptr<IntegerType const> getIntegerType() const; std::shared_ptr<IntegerType const> getIntegerType() const;

0
libsolidity/Utils.h

6
mix/ClientModel.cpp

@ -236,8 +236,8 @@ void ClientModel::executeSequence(std::vector<TransactionSettings> const& _seque
} }
if (!f) if (!f)
BOOST_THROW_EXCEPTION(FunctionNotFoundException() << FunctionName(transaction.functionId.toStdString())); BOOST_THROW_EXCEPTION(FunctionNotFoundException() << FunctionName(transaction.functionId.toStdString()));
if (!transaction.functionId.isEmpty())
encoder.encode(f); encoder.encode(f);
for (int p = 0; p < transaction.parameterValues.size(); p++) for (int p = 0; p < transaction.parameterValues.size(); p++)
{ {
if (f->parametersList().at(p)->type() != transaction.parameterValues.at(p)->declaration()->type()) if (f->parametersList().at(p)->type() != transaction.parameterValues.at(p)->declaration()->type())
@ -247,6 +247,8 @@ void ClientModel::executeSequence(std::vector<TransactionSettings> const& _seque
if (transaction.functionId.isEmpty()) if (transaction.functionId.isEmpty())
{ {
bytes param = encoder.encodedData();
contractCode.insert(contractCode.end(), param.begin(), param.end());
Address newAddress = deployContract(contractCode, transaction); Address newAddress = deployContract(contractCode, transaction);
if (newAddress != m_contractAddress) if (newAddress != m_contractAddress)
{ {

21
mix/qml/FilesSection.qml

@ -54,6 +54,12 @@ ColumnLayout {
source: "qrc:/qml/fonts/SourceSansPro-Regular.ttf" source: "qrc:/qml/fonts/SourceSansPro-Regular.ttf"
} }
FontLoader
{
id: boldFont
source: "qrc:/qml/fonts/SourceSansPro-Bold.ttf"
}
RowLayout RowLayout
{ {
anchors.top: parent.top anchors.top: parent.top
@ -64,12 +70,12 @@ ColumnLayout {
Image { Image {
source: "qrc:/qml/img/opentriangleindicator_filesproject.png" source: "qrc:/qml/img/opentriangleindicator_filesproject.png"
width: 15 width: 15
sourceSize.width: 15 sourceSize.width: 12
id: imgArrow id: imgArrow
anchors.right: section.left anchors.right: section.left
anchors.rightMargin: 5 anchors.rightMargin: 8
anchors.top: parent.top anchors.top: parent.top
anchors.topMargin: 8 anchors.topMargin: 6
} }
Text Text
@ -79,10 +85,8 @@ ColumnLayout {
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: Style.general.leftMargin anchors.leftMargin: Style.general.leftMargin
color: Style.documentsList.sectionColor color: Style.documentsList.sectionColor
font.family: fileNameFont.name font.family: boldFont.name
font.pointSize: Style.documentsList.fontSize font.pointSize: Style.documentsList.sectionFontSize
font.weight: Font.Bold
font.letterSpacing: 1
states: [ states: [
State { State {
name: "hidden" name: "hidden"
@ -154,6 +158,9 @@ ColumnLayout {
rootItem.isSelected = true; rootItem.isSelected = true;
else else
rootItem.isSelected = false; rootItem.isSelected = false;
if (rootItem.isSelected && section.state === "hidden")
section.state = "";
} }
} }
} }

19
mix/qml/ProjectList.qml

@ -15,7 +15,7 @@ Item {
FontLoader FontLoader
{ {
id: srcSansProLight id: srcSansProLight
source: "qrc:/qml/fonts/SourceSansPro-Regular.ttf" source: "qrc:/qml/fonts/SourceSansPro-Light.ttf"
} }
Rectangle Rectangle
@ -54,6 +54,7 @@ Item {
font.family: srcSansProLight.name font.family: srcSansProLight.name
font.pointSize: Style.title.pointSize font.pointSize: Style.title.pointSize
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
font.weight: Font.Light
} }
} }
@ -79,7 +80,7 @@ Item {
spacing: 0 spacing: 0
Repeater { Repeater {
model: ["Contracts", "Javascript", "HTML", "Styles", "Images", "Misc"] model: [qsTr("Contracts"), qsTr("Javascript"), qsTr("Web Pages"), qsTr("Styles"), qsTr("Images"), qsTr("Misc")];
signal selected(string doc, string groupName) signal selected(string doc, string groupName)
id: sectionRepeater id: sectionRepeater
FilesSection FilesSection
@ -127,6 +128,15 @@ Item {
} }
} }
onDocumentOpened: {
if (document.groupName === modelData)
sectionRepeater.selected(document.documentId, modelData);
}
onNewProject: {
sectionModel.clear();
}
onProjectLoaded: { onProjectLoaded: {
addDocToSubModel(); addDocToSubModel();
if (modelData === "Contracts") if (modelData === "Contracts")
@ -141,7 +151,12 @@ Item {
{ {
var newDoc = projectModel.getDocument(documentId); var newDoc = projectModel.getDocument(documentId);
if (newDoc.groupName === modelData) if (newDoc.groupName === modelData)
{
sectionModel.append(newDoc); sectionModel.append(newDoc);
projectModel.openDocument(newDoc.documentId);
sectionRepeater.selected(newDoc.documentId, modelData);
}
} }
} }
} }

9
mix/qml/Style.qml

@ -12,7 +12,7 @@ QtObject {
property QtObject title: QtObject { property QtObject title: QtObject {
property string color: "#808080" property string color: "#808080"
property string background: "#f0f0f0" property string background: "#f0f0f0"
property int height: 70 property int height: 55
property int pointSize: 18 property int pointSize: 18
} }
@ -22,8 +22,9 @@ QtObject {
property string sectionColor: "#808080" property string sectionColor: "#808080"
property string selectedColor: "white" property string selectedColor: "white"
property string highlightColor: "#4a90e2" property string highlightColor: "#4a90e2"
property int height: 32 property int height: 25
property int fileNameHeight: 45 property int fileNameHeight: 30
property int fontSize: 15 property int fontSize: 13
property int sectionFontSize: 13
} }
} }

58
mix/qml/TransactionDialog.qml

@ -60,15 +60,39 @@ Window {
else else
{ {
var parameters = codeModel.code.contract.constructor.parameters; var parameters = codeModel.code.contract.constructor.parameters;
for (var p = 0; p < parameters.length; p++) { for (var p = 0; p < parameters.length; p++)
var pname = parameters[p].name; loadParameter(parameters[p]);
paramsModel.append({ name: pname, type: parameters[p].type, value: itemParams[pname] !== undefined ? itemParams[pname].value() : "" });
}
} }
visible = true; visible = true;
valueField.focus = true; valueField.focus = true;
} }
function loadParameter(parameter)
{
var type = parameter.type;
var pname = parameter.name;
var varComponent;
if (type.indexOf("int") !== -1)
varComponent = Qt.createComponent("qrc:/qml/QIntType.qml");
else if (type.indexOf("real") !== -1)
varComponent = Qt.createComponent("qrc:/qml/QRealType.qml");
else if (type.indexOf("string") !== -1 || type.indexOf("text") !== -1)
varComponent = Qt.createComponent("qrc:/qml/QStringType.qml");
else if (type.indexOf("hash") !== -1 || type.indexOf("address") !== -1)
varComponent = Qt.createComponent("qrc:/qml/QHashType.qml");
else if (type.indexOf("bool") !== -1)
varComponent = Qt.createComponent("qrc:/qml/QBoolType.qml");
var param = varComponent.createObject(modalTransactionDialog);
var value = itemParams[pname] !== undefined ? itemParams[pname] : "";
param.setValue(value);
param.setDeclaration(parameter);
qType.push({ name: pname, value: param });
paramsModel.append({ name: pname, type: type, value: value });
}
function loadParameters() { function loadParameters() {
paramsModel.clear(); paramsModel.clear();
if (!paramsModel) if (!paramsModel)
@ -76,30 +100,8 @@ Window {
if (functionComboBox.currentIndex >= 0 && functionComboBox.currentIndex < functionsModel.count) { if (functionComboBox.currentIndex >= 0 && functionComboBox.currentIndex < functionsModel.count) {
var func = codeModel.code.contract.functions[functionComboBox.currentIndex]; var func = codeModel.code.contract.functions[functionComboBox.currentIndex];
var parameters = func.parameters; var parameters = func.parameters;
for (var p = 0; p < parameters.length; p++) { for (var p = 0; p < parameters.length; p++)
var pname = parameters[p].name; loadParameter(parameters[p]);
var varComponent;
var type = parameters[p].type;
if (type.indexOf("int") !== -1)
varComponent = Qt.createComponent("qrc:/qml/QIntType.qml");
else if (type.indexOf("real") !== -1)
varComponent = Qt.createComponent("qrc:/qml/QRealType.qml");
else if (type.indexOf("string") !== -1 || type.indexOf("text") !== -1)
varComponent = Qt.createComponent("qrc:/qml/QStringType.qml");
else if (type.indexOf("hash") !== -1 || type.indexOf("address") !== -1)
varComponent = Qt.createComponent("qrc:/qml/QHashType.qml");
else if (type.indexOf("bool") !== -1)
varComponent = Qt.createComponent("qrc:/qml/QBoolType.qml");
var param = varComponent.createObject(modalTransactionDialog);
var value = itemParams[pname] !== undefined ? itemParams[pname] : "";
param.setValue(value);
param.setDeclaration(parameters[p]);
qType.push({ name: pname, value: param });
paramsModel.append({ name: pname, type: parameters[p].type, value: value });
}
} }
} }

2
mix/qml/js/ProjectModel.js

@ -90,7 +90,7 @@ function addFile(fileName) {
var isJs = extension === ".js"; var isJs = extension === ".js";
var isImg = extension === ".png" || extension === ".gif" || extension === ".jpg" || extension === ".svg"; var isImg = extension === ".png" || extension === ".gif" || extension === ".jpg" || extension === ".svg";
var syntaxMode = isContract ? "solidity" : isJs ? "javascript" : isHtml ? "htmlmixed" : isCss ? "css" : ""; var syntaxMode = isContract ? "solidity" : isJs ? "javascript" : isHtml ? "htmlmixed" : isCss ? "css" : "";
var groupName = isContract ? "Contracts" : isJs ? "Javascript" : isHtml ? "HTML" : isCss ? "Styles" : isImg ? "Images" : "Misc"; var groupName = isContract ? qsTr("Contracts") : isJs ? qsTr("Javascript") : isHtml ? qsTr("Web Pages") : isCss ? qsTr("Styles") : isImg ? qsTr("Images") : qsTr("Misc");
var docData = { var docData = {
contract: false, contract: false,
path: p, path: p,

71
test/SolidityABIJSON.cpp

@ -409,7 +409,78 @@ BOOST_AUTO_TEST_CASE(inherited)
checkInterface(sourceCode, interface); checkInterface(sourceCode, interface);
} }
BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one)
{
char const* sourceCode = R"(
contract test {
function f(uint, uint k) returns(uint ret_k, uint ret_g){
uint g = 8;
ret_k = k;
ret_g = g;
}
})";
char const* interface = R"([
{
"name": "f",
"constant": false,
"type": "function",
"inputs": [
{
"name": "",
"type": "uint256"
},
{
"name": "k",
"type": "uint256"
}
],
"outputs": [
{
"name": "ret_k",
"type": "uint256"
},
{
"name": "ret_g",
"type": "uint256"
}
]
}
])";
checkInterface(sourceCode, interface);
}
BOOST_AUTO_TEST_CASE(empty_name_return_parameter)
{
char const* sourceCode = R"(
contract test {
function f(uint k) returns(uint){
return k;
}
})";
char const* interface = R"([
{
"name": "f",
"constant": false,
"type": "function",
"inputs": [
{
"name": "k",
"type": "uint256"
}
],
"outputs": [
{
"name": "",
"type": "uint256"
}
]
}
])";
checkInterface(sourceCode, interface);
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

90
test/SolidityEndToEndTest.cpp

@ -933,7 +933,7 @@ BOOST_AUTO_TEST_CASE(multiple_elementary_accessors)
compileAndRun(sourceCode); compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("data()") == encodeArgs(8)); BOOST_CHECK(callContractFunction("data()") == encodeArgs(8));
BOOST_CHECK(callContractFunction("name()") == encodeArgs("Celina")); BOOST_CHECK(callContractFunction("name()") == encodeArgs("Celina"));
BOOST_CHECK(callContractFunction("a_hash()") == encodeArgs(dev::sha3(toBigEndian(u256(123))))); BOOST_CHECK(callContractFunction("a_hash()") == encodeArgs(dev::sha3(bytes({0x7b}))));
BOOST_CHECK(callContractFunction("an_address()") == encodeArgs(toBigEndian(u160(0x1337)))); BOOST_CHECK(callContractFunction("an_address()") == encodeArgs(toBigEndian(u160(0x1337))));
BOOST_CHECK(callContractFunction("super_secret_data()") == bytes()); BOOST_CHECK(callContractFunction("super_secret_data()") == bytes());
} }
@ -2113,6 +2113,94 @@ BOOST_AUTO_TEST_CASE(event_lots_of_data)
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::sha3(string("Deposit(address,hash256,uint256,bool)"))); BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::sha3(string("Deposit(address,hash256,uint256,bool)")));
} }
BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one)
{
char const* sourceCode = R"(
contract test {
function f(uint, uint k) returns(uint ret_k, uint ret_g){
uint g = 8;
ret_k = k;
ret_g = g;
}
})";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("f(uint256,uint256)", 5, 9) != encodeArgs(5, 8));
BOOST_CHECK(callContractFunction("f(uint256,uint256)", 5, 9) == encodeArgs(9, 8));
}
BOOST_AUTO_TEST_CASE(empty_name_return_parameter)
{
char const* sourceCode = R"(
contract test {
function f(uint k) returns(uint){
return k;
}
})";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("f(uint256)", 9) == encodeArgs(9));
}
BOOST_AUTO_TEST_CASE(sha3_multiple_arguments)
{
char const* sourceCode = R"(
contract c {
function foo(uint a, uint b, uint c) returns (hash d)
{
d = sha3(a, b, c);
}
})";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("foo(uint256,uint256,uint256)", 10, 12, 13) == encodeArgs(
dev::sha3(
toBigEndian(u256(10)) +
toBigEndian(u256(12)) +
toBigEndian(u256(13)))));
}
BOOST_AUTO_TEST_CASE(sha3_multiple_arguments_with_numeric_literals)
{
char const* sourceCode = R"(
contract c {
function foo(uint a, uint16 b) returns (hash d)
{
d = sha3(a, b, 145);
}
})";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("foo(uint256,uint16)", 10, 12) == encodeArgs(
dev::sha3(
toBigEndian(u256(10)) +
bytes({0x0, 0xc}) +
bytes({0x91}))));
}
BOOST_AUTO_TEST_CASE(sha3_multiple_arguments_with_string_literals)
{
char const* sourceCode = R"(
contract c {
function foo() returns (hash d)
{
d = sha3("foo");
}
function bar(uint a, uint16 b) returns (hash d)
{
d = sha3(a, b, 145, "foo");
}
})";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("foo()") == encodeArgs(dev::sha3("foo")));
BOOST_CHECK(callContractFunction("bar(uint256,uint16)", 10, 12) == encodeArgs(
dev::sha3(
toBigEndian(u256(10)) +
bytes({0x0, 0xc}) +
bytes({0x91}) +
bytes({0x66, 0x6f, 0x6f}))));
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
} }

42
test/SolidityNameAndTypeResolution.cpp

@ -904,6 +904,48 @@ BOOST_AUTO_TEST_CASE(invalid_parameter_names_in_named_args)
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
} }
BOOST_AUTO_TEST_CASE(empty_name_input_parameter)
{
char const* text = R"(
contract test {
function f(uint){
}
})";
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
}
BOOST_AUTO_TEST_CASE(empty_name_return_parameter)
{
char const* text = R"(
contract test {
function f() returns(bool){
}
})";
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
}
BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one)
{
char const* text = R"(
contract test {
function f(uint, uint k) returns(uint ret_k){
return k;
}
})";
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
}
BOOST_AUTO_TEST_CASE(empty_name_return_parameter_with_named_one)
{
char const* text = R"(
contract test {
function f() returns(uint ret_k, uint){
return 5;
}
})";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_CASE(disallow_declaration_of_void_type) BOOST_AUTO_TEST_CASE(disallow_declaration_of_void_type)
{ {
char const* sourceCode = "contract c { function f() { var x = f(); } }"; char const* sourceCode = "contract c { function f() { var x = f(); } }";

Loading…
Cancel
Save