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. 92
      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(
"Non-empty \"returns\" directive for constructor."));
FunctionDefinition const* fallbackFunction = getFallbackFunction();
if (fallbackFunction && fallbackFunction->getScope() == this && !fallbackFunction->getParameters().empty())
BOOST_THROW_EXCEPTION(fallbackFunction->getParameterList().createTypeError(
"Fallback function cannot take parameters."));
FunctionDefinition const* fallbackFunction = nullptr;
for (ASTPointer<FunctionDefinition> const& function: getDefinedFunctions())
if (function->getName().empty())
{
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())
modifier->checkTypeRequirements();
@ -478,7 +486,7 @@ void FunctionCall::checkTypeRequirements()
if (m_arguments.size() != 1)
BOOST_THROW_EXCEPTION(createTypeError("More than one argument for explicit type conversion."));
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()))
BOOST_THROW_EXCEPTION(createTypeError("Explicit type conversion not allowed."));
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
// function parameters
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."));
if (m_names.empty())
{
for (size_t i = 0; i < m_arguments.size(); ++i)
if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i]))
BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in function call."));
if (functionType->getLocation() != FunctionType::Location::SHA3 &&
!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i]))
BOOST_THROW_EXCEPTION(m_arguments[i]->createTypeError("Invalid type for argument in function call."));
}
else
{
if (functionType->getLocation() == FunctionType::Location::SHA3)
BOOST_THROW_EXCEPTION(createTypeError("Named arguments cannnot be used for SHA3."));
auto const& parameterNames = functionType->getParameterNames();
if (parameterNames.size() != m_names.size())
BOOST_THROW_EXCEPTION(createTypeError("Some argument names are missing."));
// check duplicate names
for (size_t i = 0; i < m_names.size(); i++) {
for (size_t j = i + 1; j < m_names.size(); j++) {
for (size_t i = 0; i < m_names.size(); i++)
for (size_t j = i + 1; j < m_names.size(); 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++) {
bool found = false;
@ -525,7 +534,7 @@ void FunctionCall::checkTypeRequirements()
}
}
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.
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;
private:

4
libsolidity/DeclarationContainer.cpp

@ -30,6 +30,9 @@ namespace solidity
bool DeclarationContainer::registerDeclaration(Declaration const& _declaration, bool _update)
{
if (_declaration.getName().empty())
return true;
if (!_update && m_declarations.find(_declaration.getName()) != m_declarations.end())
return false;
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
{
solAssert(!_name.empty(), "Attempt to resolve empty name.");
auto result = m_declarations.find(_name);
if (result != m_declarations.end())
return result->second;

4
libsolidity/DeclarationContainer.h

@ -42,8 +42,8 @@ public:
explicit DeclarationContainer(Declaration const* _enclosingDeclaration = nullptr,
DeclarationContainer const* _enclosingContainer = nullptr):
m_enclosingDeclaration(_enclosingDeclaration), m_enclosingContainer(_enclosingContainer) {}
/// Registers the declaration in the scope unless its name is already declared.
/// @returns true iff it was not yet declared.
/// Registers the declaration in the scope unless its name is already declared or the name is empty.
/// @returns false if the name was already declared.
bool registerDeclaration(Declaration const& _declaration, bool _update = false);
Declaration const* resolveName(ASTString const& _name, bool _recursive = false) const;
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();
vector<ASTPointer<Expression const>> const& callArguments = _functionCall.getArguments();
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;
if (callArgumentNames.empty())
@ -274,7 +275,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
m_context << u256(0) << eth::Instruction::CODECOPY;
unsigned length = bytecode.size();
length += appendArgumentCopyToMemory(function.getParameterTypes(), arguments, length);
length += appendArgumentsCopyToMemory(arguments, function.getParameterTypes(), length);
// size, offset, endowment
m_context << u256(length) << u256(0);
if (function.valueSet())
@ -325,9 +326,11 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
m_context << eth::Instruction::SUICIDE;
break;
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;
}
case Location::LOG0:
case Location::LOG1:
case Location::LOG2:
@ -797,7 +800,7 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio
// reserve space for the function identifier
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
Type const* firstType = _functionType.getReturnParameterTypes().empty() ? nullptr :
@ -833,28 +836,34 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio
}
}
unsigned ExpressionCompiler::appendArgumentCopyToMemory(TypePointers const& _types,
vector<ASTPointer<Expression const>> const& _arguments,
unsigned _memoryOffset)
unsigned ExpressionCompiler::appendArgumentsCopyToMemory(vector<ASTPointer<Expression const>> const& _arguments,
TypePointers const& _types,
unsigned _memoryOffset,
bool _padToWordBoundaries)
{
solAssert(_types.empty() || _types.size() == _arguments.size(), "");
unsigned length = 0;
for (unsigned i = 0; i < _arguments.size(); ++i)
length += appendExpressionCopyToMemory(*_types[i], *_arguments[i], _memoryOffset + length);
for (size_t i = 0; i < _arguments.size(); ++i)
{
_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;
}
unsigned ExpressionCompiler::appendTypeConversionAndMoveToMemory(Type const& _expectedType, Type const& _type,
Location const& _location, unsigned _memoryOffset)
unsigned ExpressionCompiler::appendTypeMoveToMemory(Type const& _type, Location const& _location, unsigned _memoryOffset, bool _padToWordBoundaries)
{
appendTypeConversion(_type, _expectedType, true);
unsigned const c_numBytes = CompilerUtils::getPaddedSize(_expectedType.getCalldataEncodedSize());
unsigned const c_encodedSize = _type.getCalldataEncodedSize();
unsigned const c_numBytes = _padToWordBoundaries ? CompilerUtils::getPaddedSize(c_encodedSize) : c_encodedSize;
if (c_numBytes == 0 || c_numBytes > 32)
BOOST_THROW_EXCEPTION(CompilerError()
<< errinfo_sourceLocation(_location)
<< errinfo_comment("Type " + _expectedType.toString() + " not yet supported."));
bool const c_leftAligned = _expectedType.getCategory() == Type::Category::STRING;
bool const c_padToWords = true;
return CompilerUtils(m_context).storeInMemory(_memoryOffset, c_numBytes, c_leftAligned, c_padToWords);
<< errinfo_comment("Type " + _type.toString() + " not yet supported."));
bool const c_leftAligned = _type.getCategory() == Type::Category::STRING;
return CompilerUtils(m_context).storeInMemory(_memoryOffset, c_numBytes, c_leftAligned, _padToWordBoundaries);
}
unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType,
@ -862,7 +871,8 @@ unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedT
unsigned _memoryOffset)
{
_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)
@ -870,20 +880,20 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
FunctionType accessorType(_varDecl);
unsigned length = 0;
TypePointers const& params = accessorType.getParameterTypes();
TypePointers const& paramTypes = accessorType.getParameterTypes();
// move arguments to memory
for (TypePointer const& param: boost::adaptors::reverse(params))
length += appendTypeConversionAndMoveToMemory(*param, *param, Location(), length);
for (TypePointer const& paramType: boost::adaptors::reverse(paramTypes))
length += appendTypeMoveToMemory(*paramType, Location(), length);
// retrieve the position of the variable
m_context << m_context.getStorageLocationOfVariable(_varDecl);
TypePointer returnType = _varDecl.getType();
for (TypePointer const& param: params)
for (TypePointer const& paramType: paramTypes)
{
// move offset to memory
CompilerUtils(m_context).storeInMemory(length);
unsigned argLen = CompilerUtils::getPaddedSize(param->getCalldataEncodedSize());
unsigned argLen = CompilerUtils::getPaddedSize(paramType->getCalldataEncodedSize());
length -= argLen;
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.
void appendExternalFunctionCall(FunctionType const& _functionType, std::vector<ASTPointer<Expression const>> const& _arguments,
bool bare = false);
/// Appends code that copies the given arguments to memory (with optional offset).
/// @returns the number of bytes copied to memory
unsigned appendArgumentCopyToMemory(TypePointers const& _types,
std::vector<ASTPointer<Expression const>> const& _arguments,
unsigned _memoryOffset = 0);
/// Appends code that copies a type to memory.
/// @returns the number of bytes copied to memory
unsigned appendTypeConversionAndMoveToMemory(Type const& _expectedType, Type const& _type,
Location const& _location, unsigned _memoryOffset = 0);
/// Appends code that evaluates a single expression and copies it to memory (with optional offset).
/// @returns the number of bytes copied to memory
/// Appends code that evaluates the given arguments and moves the result to memory (with optional offset).
/// @returns the number of bytes moved to memory
unsigned appendArgumentsCopyToMemory(std::vector<ASTPointer<Expression const>> const& _arguments,
TypePointers const& _types = {},
unsigned _memoryOffset = 0,
bool _padToWordBoundaries = true);
/// Appends code that moves a stack element of the given type to memory
/// @returns the number of bytes moved to memory
unsigned appendTypeMoveToMemory(Type const& _type, Location const& _location, unsigned _memoryOffset,
bool _padToWordBoundaries = true);
/// 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 _memoryOffset = 0);

26
libsolidity/Parser.cpp

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

1
libsolidity/Parser.h

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

5
libsolidity/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

7
libsolidity/Types.cpp

@ -357,6 +357,13 @@ u256 IntegerConstantType::literalValue(Literal const*) const
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
{
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.
virtual bool isValueType() const { return false; }
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.
virtual MemberList const& getMembers() const { return EmptyMemberList; }
@ -140,7 +142,7 @@ public:
virtual u256 literalValue(Literal const*) const
{
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Literal value requested "
"for type without literals."));
"for type without literals."));
}
protected:
@ -213,6 +215,7 @@ public:
virtual std::string toString() 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.
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)
BOOST_THROW_EXCEPTION(FunctionNotFoundException() << FunctionName(transaction.functionId.toStdString()));
encoder.encode(f);
if (!transaction.functionId.isEmpty())
encoder.encode(f);
for (int p = 0; p < transaction.parameterValues.size(); p++)
{
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())
{
bytes param = encoder.encodedData();
contractCode.insert(contractCode.end(), param.begin(), param.end());
Address newAddress = deployContract(contractCode, transaction);
if (newAddress != m_contractAddress)
{

21
mix/qml/FilesSection.qml

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

19
mix/qml/ProjectList.qml

@ -15,7 +15,7 @@ Item {
FontLoader
{
id: srcSansProLight
source: "qrc:/qml/fonts/SourceSansPro-Regular.ttf"
source: "qrc:/qml/fonts/SourceSansPro-Light.ttf"
}
Rectangle
@ -54,6 +54,7 @@ Item {
font.family: srcSansProLight.name
font.pointSize: Style.title.pointSize
anchors.verticalCenter: parent.verticalCenter
font.weight: Font.Light
}
}
@ -79,7 +80,7 @@ Item {
spacing: 0
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)
id: sectionRepeater
FilesSection
@ -127,6 +128,15 @@ Item {
}
}
onDocumentOpened: {
if (document.groupName === modelData)
sectionRepeater.selected(document.documentId, modelData);
}
onNewProject: {
sectionModel.clear();
}
onProjectLoaded: {
addDocToSubModel();
if (modelData === "Contracts")
@ -141,7 +151,12 @@ Item {
{
var newDoc = projectModel.getDocument(documentId);
if (newDoc.groupName === modelData)
{
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 string color: "#808080"
property string background: "#f0f0f0"
property int height: 70
property int height: 55
property int pointSize: 18
}
@ -22,8 +22,9 @@ QtObject {
property string sectionColor: "#808080"
property string selectedColor: "white"
property string highlightColor: "#4a90e2"
property int height: 32
property int fileNameHeight: 45
property int fontSize: 15
property int height: 25
property int fileNameHeight: 30
property int fontSize: 13
property int sectionFontSize: 13
}
}

58
mix/qml/TransactionDialog.qml

@ -60,15 +60,39 @@ Window {
else
{
var parameters = codeModel.code.contract.constructor.parameters;
for (var p = 0; p < parameters.length; p++) {
var pname = parameters[p].name;
paramsModel.append({ name: pname, type: parameters[p].type, value: itemParams[pname] !== undefined ? itemParams[pname].value() : "" });
}
for (var p = 0; p < parameters.length; p++)
loadParameter(parameters[p]);
}
visible = 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() {
paramsModel.clear();
if (!paramsModel)
@ -76,30 +100,8 @@ Window {
if (functionComboBox.currentIndex >= 0 && functionComboBox.currentIndex < functionsModel.count) {
var func = codeModel.code.contract.functions[functionComboBox.currentIndex];
var parameters = func.parameters;
for (var p = 0; p < parameters.length; p++) {
var pname = parameters[p].name;
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 });
}
for (var p = 0; p < parameters.length; p++)
loadParameter(parameters[p]);
}
}

2
mix/qml/js/ProjectModel.js

@ -90,7 +90,7 @@ function addFile(fileName) {
var isJs = extension === ".js";
var isImg = extension === ".png" || extension === ".gif" || extension === ".jpg" || extension === ".svg";
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 = {
contract: false,
path: p,

71
test/SolidityABIJSON.cpp

@ -409,7 +409,78 @@ BOOST_AUTO_TEST_CASE(inherited)
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()

92
test/SolidityEndToEndTest.cpp

@ -576,7 +576,7 @@ BOOST_AUTO_TEST_CASE(simple_mapping)
" }\n"
"}";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("get(uint8)", byte(0)) == encodeArgs(byte(0x00)));
BOOST_CHECK(callContractFunction("get(uint8)", byte(0x01)) == encodeArgs(byte(0x00)));
BOOST_CHECK(callContractFunction("get(uint8)", byte(0xa7)) == encodeArgs(byte(0x00)));
@ -933,7 +933,7 @@ BOOST_AUTO_TEST_CASE(multiple_elementary_accessors)
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("data()") == encodeArgs(8));
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("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_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()
}

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_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)
{
char const* sourceCode = "contract c { function f() { var x = f(); } }";

Loading…
Cancel
Save