Allow "new expressions" also for general type names.

Breaking change: If you want to send value with a contract creation, you
have to use parentheses now:

`(new ContractName).value(2 ether)(arg1, arg2)`
This commit is contained in:
chriseth
2015-11-26 13:10:12 +01:00
parent cd94aa978a
commit 30b325fdc1
9 changed files with 73 additions and 33 deletions
@@ -44,6 +44,7 @@ bool ReferencesResolver::visit(UserDefinedTypeName const& _typeName)
fatalDeclarationError(_typeName.location(), "Identifier not found or not unique.");
_typeName.annotation().referencedDeclaration = declaration;
_typeName.annotation().contractScope = m_currentContract;
return true;
}
+39 -24
View File
@@ -1045,34 +1045,43 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
void TypeChecker::endVisit(NewExpression const& _newExpression)
{
auto contract = dynamic_cast<ContractDefinition const*>(&dereference(_newExpression.contractName()));
if (auto contractName = dynamic_cast<UserDefinedTypeName const*>(&_newExpression.typeName()))
{
auto contract = dynamic_cast<ContractDefinition const*>(&dereference(*contractName));
if (!contract)
fatalTypeError(_newExpression.location(), "Identifier is not a contract.");
if (!contract->annotation().isFullyImplemented)
typeError(_newExpression.location(), "Trying to create an instance of an abstract contract.");
if (!contract)
fatalTypeError(_newExpression.location(), "Identifier is not a contract.");
if (!contract->annotation().isFullyImplemented)
typeError(_newExpression.location(), "Trying to create an instance of an abstract contract.");
auto scopeContract = _newExpression.contractName().annotation().contractScope;
scopeContract->annotation().contractDependencies.insert(contract);
solAssert(
!contract->annotation().linearizedBaseContracts.empty(),
"Linearized base contracts not yet available."
);
if (contractDependenciesAreCyclic(*scopeContract))
typeError(
_newExpression.location(),
"Circular reference for contract creation (cannot create instance of derived or same contract)."
auto scopeContract = contractName->annotation().contractScope;
scopeContract->annotation().contractDependencies.insert(contract);
solAssert(
!contract->annotation().linearizedBaseContracts.empty(),
"Linearized base contracts not yet available."
);
if (contractDependenciesAreCyclic(*scopeContract))
typeError(
_newExpression.location(),
"Circular reference for contract creation (cannot create instance of derived or same contract)."
);
auto contractType = make_shared<ContractType>(*contract);
TypePointers const& parameterTypes = contractType->constructorType()->parameterTypes();
_newExpression.annotation().type = make_shared<FunctionType>(
parameterTypes,
TypePointers{contractType},
strings(),
strings(),
FunctionType::Location::Creation
);
auto contractType = make_shared<ContractType>(*contract);
TypePointers const& parameterTypes = contractType->constructorType()->parameterTypes();
_newExpression.annotation().type = make_shared<FunctionType>(
parameterTypes,
TypePointers{contractType},
strings(),
strings(),
FunctionType::Location::Creation
);
}
else if (auto arrayTypeName = dynamic_cast<ArrayTypeName const*>(&_newExpression.typeName()))
{
solAssert(false, "Not yet implemented.");
}
else
fatalTypeError(_newExpression.location(), "Contract or array type expected.");
}
bool TypeChecker::visit(MemberAccess const& _memberAccess)
@@ -1288,6 +1297,12 @@ Declaration const& TypeChecker::dereference(Identifier const& _identifier)
return *_identifier.annotation().referencedDeclaration;
}
Declaration const& TypeChecker::dereference(UserDefinedTypeName const& _typeName)
{
solAssert(!!_typeName.annotation().referencedDeclaration, "Declaration not stored.");
return *_typeName.annotation().referencedDeclaration;
}
void TypeChecker::expectType(Expression const& _expression, Type const& _expectedType)
{
_expression.accept(*this);
+2
View File
@@ -108,6 +108,8 @@ private:
/// @returns the referenced declaration and throws on error.
Declaration const& dereference(Identifier const& _identifier);
/// @returns the referenced declaration and throws on error.
Declaration const& dereference(UserDefinedTypeName const& _typeName);
/// Runs type checks on @a _expression to infer its type and then checks that it is implicitly
/// convertible to @a _expectedType.