mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
tmp
This commit is contained in:
parent
bd4be335d4
commit
f9d6e805ba
@ -41,7 +41,12 @@ bool DebugWarner::visitNode(ASTNode const& _node)
|
||||
auto const& typeInferenceAnnotation = m_analysis.annotation<TypeInference>(_node);
|
||||
if (typeInferenceAnnotation.type)
|
||||
{
|
||||
m_errorReporter.info(0000_error, _node.location(), "Inferred type: " + m_analysis.typeSystem().env().typeToString(*typeInferenceAnnotation.type));
|
||||
Type type = m_analysis.typeSystem().env().resolveRecursive(*typeInferenceAnnotation.type);
|
||||
m_errorReporter.info(
|
||||
0000_error,
|
||||
_node.location(),
|
||||
"Inferred type: " + m_analysis.typeSystem().env().typeToString(type) + ":" + TypeSystemHelpers{m_analysis.typeSystem()}.sortToString(m_analysis.typeSystem().env().sort(type))
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -328,9 +328,27 @@ bool TypeInference::visit(BinaryOperation const& _binaryOperation)
|
||||
unify(*leftAnnotation.type, *rightAnnotation.type, _binaryOperation.location());
|
||||
operationAnnotation.type = leftAnnotation.type;
|
||||
}
|
||||
else if (_binaryOperation.getOperator() == Token::RightArrow)
|
||||
{
|
||||
_binaryOperation.leftExpression().accept(*this);
|
||||
_binaryOperation.rightExpression().accept(*this);
|
||||
auto getType = [&](std::optional<Type> _type) -> Type {
|
||||
solAssert(_type);
|
||||
if (helper.isKindType(*_type))
|
||||
return helper.destKindType(*_type);
|
||||
else
|
||||
{
|
||||
m_errorReporter.typeError(0000_error, _binaryOperation.leftExpression().location(), "Expected type but got " + m_env->typeToString(*leftAnnotation.type));
|
||||
return m_typeSystem.freshTypeVariable(false, {});
|
||||
}
|
||||
};
|
||||
Type leftType = getType(leftAnnotation.type);
|
||||
Type rightType = getType(rightAnnotation.type);
|
||||
operationAnnotation.type = helper.kindType(helper.functionType(leftType, rightType));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_errorReporter.typeError(0000_error, _binaryOperation.location(), "Binary operations other than colon in type context not yet supported.");
|
||||
m_errorReporter.typeError(0000_error, _binaryOperation.location(), "Invalid binary operations in type context.");
|
||||
operationAnnotation.type = helper.kindType(m_typeSystem.freshTypeVariable(false, {}));
|
||||
}
|
||||
return false;
|
||||
@ -358,12 +376,17 @@ bool TypeInference::visit(VariableDeclaration const& _variableDeclaration)
|
||||
_variableDeclaration.typeExpression()->accept(*this);
|
||||
auto& typeExpressionAnnotation = annotation(*_variableDeclaration.typeExpression());
|
||||
solAssert(typeExpressionAnnotation.type);
|
||||
variableAnnotation.type = m_env->fresh(helper.destKindType(*typeExpressionAnnotation.type), false);
|
||||
if (helper.isKindType(*typeExpressionAnnotation.type))
|
||||
variableAnnotation.type = m_env->fresh(helper.destKindType(*typeExpressionAnnotation.type), false);
|
||||
else
|
||||
{
|
||||
m_errorReporter.typeError(0000_error, _variableDeclaration.typeExpression()->location(), "Expected type, but got " + m_env->typeToString(*typeExpressionAnnotation.type));
|
||||
variableAnnotation.type = m_typeSystem.freshTypeVariable(false, {});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
variableAnnotation.type = m_typeSystem.freshTypeVariable(false, {});
|
||||
|
||||
return false;
|
||||
case ExpressionContext::Type:
|
||||
if (_variableDeclaration.typeExpression())
|
||||
@ -469,12 +492,12 @@ bool TypeInference::visit(Identifier const& _identifier)
|
||||
|
||||
if (dynamic_cast<VariableDeclaration const*>(referencedDeclaration))
|
||||
{
|
||||
helper.destKindType(*declarationAnnotation.type);
|
||||
// TODO: helper.destKindType(*declarationAnnotation.type);
|
||||
identifierAnnotation.type = declarationAnnotation.type;
|
||||
}
|
||||
else if (dynamic_cast<TypeDefinition const*>(referencedDeclaration))
|
||||
{
|
||||
helper.destKindType(*declarationAnnotation.type);
|
||||
// TODO: helper.destKindType(*declarationAnnotation.type);
|
||||
identifierAnnotation.type = m_env->fresh(*declarationAnnotation.type, true);
|
||||
}
|
||||
else
|
||||
@ -511,12 +534,27 @@ void TypeInference::endVisit(TupleExpression const& _tupleExpression)
|
||||
auto& expressionAnnotation = annotation(_tupleExpression);
|
||||
solAssert(!expressionAnnotation.type);
|
||||
|
||||
TypeSystemHelpers helper{m_typeSystem};
|
||||
auto componentTypes = _tupleExpression.components() | ranges::views::transform([&](auto _expr) -> Type {
|
||||
auto& componentAnnotation = annotation(*_expr);
|
||||
solAssert(componentAnnotation.type);
|
||||
return *componentAnnotation.type;
|
||||
switch(m_expressionContext)
|
||||
{
|
||||
case ExpressionContext::Term:
|
||||
return *componentAnnotation.type;
|
||||
case ExpressionContext::Type:
|
||||
if (helper.isKindType(*componentAnnotation.type))
|
||||
return helper.destKindType(*componentAnnotation.type);
|
||||
else
|
||||
{
|
||||
m_errorReporter.typeError(0000_error, _expr->location(), "Expected type, but got " + m_env->typeToString(*componentAnnotation.type));
|
||||
return m_typeSystem.freshTypeVariable(false, {});
|
||||
}
|
||||
case ExpressionContext::Sort:
|
||||
return *componentAnnotation.type;
|
||||
}
|
||||
solAssert(false);
|
||||
}) | ranges::to<vector<Type>>;
|
||||
TypeSystemHelpers helper{m_typeSystem};
|
||||
switch (m_expressionContext)
|
||||
{
|
||||
case ExpressionContext::Term:
|
||||
@ -658,12 +696,12 @@ bool TypeInference::visit(TypeDefinition const& _typeDefinition)
|
||||
|
||||
TypeSystemHelpers helper{m_typeSystem};
|
||||
if (arguments.empty())
|
||||
typeDefinitionAnnotation.type = helper.kindType(m_typeSystem.type(TypeExpression::Constructor{&_typeDefinition}, arguments));
|
||||
typeDefinitionAnnotation.type = helper.kindType(m_typeSystem.type(TypeConstant::Constructor{&_typeDefinition}, arguments));
|
||||
else
|
||||
typeDefinitionAnnotation.type =
|
||||
helper.functionType(
|
||||
helper.kindType(helper.tupleType(arguments)),
|
||||
helper.kindType(m_typeSystem.type(TypeExpression::Constructor{&_typeDefinition}, arguments))
|
||||
helper.kindType(m_typeSystem.type(TypeConstant::Constructor{&_typeDefinition}, arguments))
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@ -679,15 +717,33 @@ void TypeInference::endVisit(FunctionCall const& _functionCall)
|
||||
|
||||
Type functionType = *expressionAnnotation.type;
|
||||
|
||||
TypeSystemHelpers helper{m_typeSystem};
|
||||
std::vector<Type> argTypes;
|
||||
for(auto arg: _functionCall.arguments())
|
||||
{
|
||||
auto& argAnnotation = annotation(*arg);
|
||||
solAssert(argAnnotation.type);
|
||||
argTypes.emplace_back(*argAnnotation.type);
|
||||
switch(m_expressionContext)
|
||||
{
|
||||
case ExpressionContext::Term:
|
||||
argTypes.emplace_back(*argAnnotation.type);
|
||||
break;
|
||||
case ExpressionContext::Type:
|
||||
if (helper.isKindType(*argAnnotation.type))
|
||||
argTypes.emplace_back(helper.destKindType(*argAnnotation.type));
|
||||
else
|
||||
{
|
||||
m_errorReporter.typeError(0000_error, arg->location(), "Expected type, but got " + m_env->typeToString(*argAnnotation.type));
|
||||
argTypes.emplace_back(m_typeSystem.freshTypeVariable(false, {}));
|
||||
}
|
||||
break;
|
||||
case ExpressionContext::Sort:
|
||||
m_errorReporter.typeError(0000_error, _functionCall.location(), "Function call in sort context.");
|
||||
functionCallAnnotation.type = m_typeSystem.freshTypeVariable(false, {});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TypeSystemHelpers helper{m_typeSystem};
|
||||
switch(m_expressionContext)
|
||||
{
|
||||
case ExpressionContext::Term:
|
||||
@ -701,17 +757,15 @@ void TypeInference::endVisit(FunctionCall const& _functionCall)
|
||||
}
|
||||
case ExpressionContext::Type:
|
||||
{
|
||||
Type argTuple = helper.tupleType(argTypes);
|
||||
Type genericFunctionType = helper.functionType(argTuple, m_typeSystem.freshTypeVariable(false, {}));
|
||||
Type argTuple = helper.kindType(helper.tupleType(argTypes));
|
||||
Type genericFunctionType = helper.functionType(argTuple, m_typeSystem.freshKindVariable(false, {}));
|
||||
unify(genericFunctionType, functionType, _functionCall.location());
|
||||
|
||||
functionCallAnnotation.type = m_env->resolve(std::get<1>(helper.destFunctionType(m_env->resolve(genericFunctionType))));
|
||||
break;
|
||||
}
|
||||
case ExpressionContext::Sort:
|
||||
m_errorReporter.typeError(0000_error, _functionCall.location(), "Function call in sort context.");
|
||||
functionCallAnnotation.type = m_typeSystem.freshTypeVariable(false, {});
|
||||
break;
|
||||
solAssert(false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -69,7 +69,7 @@ bool TypeRegistration::visit(TypeClassInstantiation const& _typeClassInstantiati
|
||||
|
||||
TypeName const& typeName = _typeClassInstantiation.typeConstructor();
|
||||
|
||||
TypeExpression::Constructor typeConstructor = [&]() -> TypeExpression::Constructor {
|
||||
TypeConstant::Constructor typeConstructor = [&]() -> TypeConstant::Constructor {
|
||||
if (auto const* elementaryTypeName = dynamic_cast<ElementaryTypeName const*>(&typeName))
|
||||
{
|
||||
switch(elementaryTypeName->typeName().token())
|
||||
@ -149,7 +149,7 @@ bool TypeRegistration::visit(TypeClassInstantiation const& _typeClassInstantiati
|
||||
bool TypeRegistration::visit(TypeDefinition const& _typeDefinition)
|
||||
{
|
||||
m_typeSystem.declareTypeConstructor(
|
||||
TypeExpression::Constructor{&_typeDefinition},
|
||||
TypeConstant::Constructor{&_typeDefinition},
|
||||
_typeDefinition.name(),
|
||||
_typeDefinition.arguments() ? _typeDefinition.arguments()->parameters().size() : 0
|
||||
);
|
||||
|
@ -33,7 +33,7 @@ public:
|
||||
struct Annotation
|
||||
{
|
||||
Type type;
|
||||
std::map<TypeExpression::Constructor, TypeClassInstantiation const*> instantiations;
|
||||
std::map<TypeConstant::Constructor, TypeClassInstantiation const*> instantiations;
|
||||
};
|
||||
TypeRegistration(Analysis& _analysis);
|
||||
|
||||
|
@ -2143,7 +2143,7 @@ public:
|
||||
Expression(_id, _location), m_left(std::move(_left)), m_operator(_operator), m_right(std::move(_right))
|
||||
{
|
||||
// TODO: assert against colon for non-experimental solidity
|
||||
solAssert(TokenTraits::isBinaryOp(_operator) || TokenTraits::isCompareOp(_operator) || _operator == Token::Colon, "");
|
||||
solAssert(TokenTraits::isBinaryOp(_operator) || TokenTraits::isCompareOp(_operator) || _operator == Token::Colon || _operator == Token::RightArrow, "");
|
||||
}
|
||||
void accept(ASTVisitor& _visitor) override;
|
||||
void accept(ASTConstVisitor& _visitor) const override;
|
||||
|
@ -65,6 +65,8 @@ string TypeClass::toString() const
|
||||
return "type";
|
||||
case BuiltinClass::Kind:
|
||||
return "kind";
|
||||
case BuiltinClass::Constraint:
|
||||
return "contraint";
|
||||
}
|
||||
solAssert(false);
|
||||
},
|
||||
@ -82,7 +84,7 @@ bool Sort::operator==(Sort const& _rhs) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sort::operator<(Sort const& _rhs) const
|
||||
bool Sort::operator<=(Sort const& _rhs) const
|
||||
{
|
||||
for (auto c: classes)
|
||||
if (!_rhs.classes.count(c))
|
||||
@ -105,7 +107,7 @@ Sort Sort::operator-(Sort const& _rhs) const
|
||||
return result;
|
||||
}
|
||||
|
||||
bool TypeExpression::operator<(TypeExpression const& _rhs) const
|
||||
bool TypeConstant::operator<(TypeConstant const& _rhs) const
|
||||
{
|
||||
if (constructor < _rhs.constructor)
|
||||
return true;
|
||||
@ -125,7 +127,7 @@ bool TypeExpression::operator<(TypeExpression const& _rhs) const
|
||||
std::string experimental::canonicalTypeName(Type _type)
|
||||
{
|
||||
return std::visit(util::GenericVisitor{
|
||||
[&](TypeExpression const& _type) {
|
||||
[&](TypeConstant const& _type) {
|
||||
std::stringstream stream;
|
||||
auto printTypeArguments = [&]() {
|
||||
if (!_type.arguments.empty())
|
||||
@ -153,6 +155,9 @@ std::string experimental::canonicalTypeName(Type _type)
|
||||
case BuiltinType::Type:
|
||||
stream << "type";
|
||||
break;
|
||||
case BuiltinType::Sort:
|
||||
stream << "sort";
|
||||
break;
|
||||
case BuiltinType::Void:
|
||||
stream << "void";
|
||||
break;
|
||||
@ -185,7 +190,7 @@ std::string experimental::canonicalTypeName(Type _type)
|
||||
std::string TypeEnvironment::typeToString(Type const& _type) const
|
||||
{
|
||||
return std::visit(util::GenericVisitor{
|
||||
[&](TypeExpression const& _type) {
|
||||
[&](TypeConstant const& _type) {
|
||||
std::stringstream stream;
|
||||
auto printTypeArguments = [&]() {
|
||||
if (!_type.arguments.empty())
|
||||
@ -194,7 +199,7 @@ std::string TypeEnvironment::typeToString(Type const& _type) const
|
||||
for (auto type: _type.arguments | ranges::views::drop_last(1))
|
||||
stream << typeToString(type) << ", ";
|
||||
stream << typeToString(_type.arguments.back());
|
||||
stream << ") ";
|
||||
stream << ")";
|
||||
}
|
||||
};
|
||||
std::visit(util::GenericVisitor{
|
||||
@ -277,9 +282,9 @@ vector<TypeEnvironment::UnificationFailure> TypeEnvironment::unify(Type _a, Type
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_left.sort() < _right.sort())
|
||||
if (_left.sort() <= _right.sort())
|
||||
failures += instantiate(_left, _right);
|
||||
else if (_right.sort() < _left.sort())
|
||||
else if (_right.sort() <= _left.sort())
|
||||
failures += instantiate(_right, _left);
|
||||
else
|
||||
{
|
||||
@ -295,7 +300,7 @@ vector<TypeEnvironment::UnificationFailure> TypeEnvironment::unify(Type _a, Type
|
||||
[&](auto, TypeVariable _var) {
|
||||
failures += instantiate(_var, _a);
|
||||
},
|
||||
[&](TypeExpression _left, TypeExpression _right) {
|
||||
[&](TypeConstant _left, TypeConstant _right) {
|
||||
if(_left.constructor != _right.constructor)
|
||||
return unificationFailure();
|
||||
if (_left.arguments.size() != _right.arguments.size())
|
||||
@ -323,13 +328,16 @@ TypeSystem::TypeSystem()
|
||||
Sort typeSort{{TypeClass{BuiltinClass::Type}}};
|
||||
m_typeConstructors[BuiltinType::Type] = TypeConstructorInfo{
|
||||
"type",
|
||||
{Arity{vector<Sort>{{kindSort}}, TypeClass{BuiltinClass::Kind}}}
|
||||
{Arity{vector<Sort>{{typeSort}}, TypeClass{BuiltinClass::Kind}}}
|
||||
};
|
||||
m_typeConstructors[BuiltinType::Sort] = TypeConstructorInfo{
|
||||
"constraint",
|
||||
{Arity{vector<Sort>{{kindSort}}, TypeClass{BuiltinClass::Constraint}}}
|
||||
};
|
||||
m_typeConstructors[BuiltinType::Function] = TypeConstructorInfo{
|
||||
"fun",
|
||||
{
|
||||
Arity{vector<Sort>{{kindSort, kindSort}}, TypeClass{BuiltinClass::Kind}},
|
||||
Arity{vector<Sort>{{typeSort, typeSort}}, TypeClass{BuiltinClass::Type}}
|
||||
Arity{vector<Sort>{{typeSort, typeSort}}, TypeClass{BuiltinClass::Type}},
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -354,10 +362,10 @@ experimental::Type TypeSystem::freshKindVariable(bool _generic, Sort _sort)
|
||||
|
||||
vector<TypeEnvironment::UnificationFailure> TypeEnvironment::instantiate(TypeVariable _variable, Type _type)
|
||||
{
|
||||
Sort sort = m_typeSystem.sort(_type);
|
||||
if (!(_variable.sort() < sort))
|
||||
Sort typeSort = sort(_type);
|
||||
if (!(_variable.sort() <= typeSort))
|
||||
{
|
||||
return {UnificationFailure{SortMismatch{_type, _variable.sort() - sort}}};
|
||||
return {UnificationFailure{SortMismatch{_type, _variable.sort() - typeSort}}};
|
||||
}
|
||||
solAssert(m_typeVariables.emplace(_variable.index(), _type).second);
|
||||
return {};
|
||||
@ -377,8 +385,8 @@ experimental::Type TypeEnvironment::resolve(Type _type) const
|
||||
experimental::Type TypeEnvironment::resolveRecursive(Type _type) const
|
||||
{
|
||||
return std::visit(util::GenericVisitor{
|
||||
[&](TypeExpression const& _type) -> Type {
|
||||
return TypeExpression{
|
||||
[&](TypeConstant const& _type) -> Type {
|
||||
return TypeConstant{
|
||||
_type.constructor,
|
||||
_type.arguments | ranges::views::transform([&](Type _argType) {
|
||||
return resolveRecursive(_argType);
|
||||
@ -391,14 +399,14 @@ experimental::Type TypeEnvironment::resolveRecursive(Type _type) const
|
||||
}, resolve(_type));
|
||||
}
|
||||
|
||||
Sort TypeSystem::sort(Type _type) const
|
||||
Sort TypeEnvironment::sort(Type _type) const
|
||||
{
|
||||
return std::visit(util::GenericVisitor{
|
||||
[&](TypeExpression const& _expression) -> Sort
|
||||
[&](TypeConstant const& _expression) -> Sort
|
||||
{
|
||||
auto const& constructorInfo = m_typeConstructors.at(_expression.constructor);
|
||||
auto argumentSorts = _expression.arguments | ranges::views::transform([&](Type _type) {
|
||||
return sort(_type);
|
||||
auto const& constructorInfo = m_typeSystem.constructorInfo(_expression.constructor);
|
||||
auto argumentSorts = _expression.arguments | ranges::views::transform([&](Type _argumentType) {
|
||||
return sort(resolve(_argumentType));
|
||||
}) | ranges::to<vector<Sort>>;
|
||||
Sort sort;
|
||||
for (auto const& arity: constructorInfo.arities)
|
||||
@ -407,12 +415,13 @@ Sort TypeSystem::sort(Type _type) const
|
||||
bool hasArity = true;
|
||||
for (auto&& [argumentSort, arityArgumentSort]: ranges::zip_view(argumentSorts, arity.argumentSorts))
|
||||
{
|
||||
if (!(argumentSort < arityArgumentSort))
|
||||
if (!(arityArgumentSort <= argumentSort))
|
||||
{
|
||||
hasArity = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasArity)
|
||||
sort.classes.insert(arity.typeClass);
|
||||
}
|
||||
@ -422,7 +431,7 @@ Sort TypeSystem::sort(Type _type) const
|
||||
}, _type);
|
||||
}
|
||||
|
||||
void TypeSystem::declareTypeConstructor(TypeExpression::Constructor _typeConstructor, std::string _name, size_t _arguments)
|
||||
void TypeSystem::declareTypeConstructor(TypeConstant::Constructor _typeConstructor, std::string _name, size_t _arguments)
|
||||
{
|
||||
Sort baseSort{{TypeClass{BuiltinClass::Type}}};
|
||||
bool newlyInserted = m_typeConstructors.emplace(std::make_pair(_typeConstructor, TypeConstructorInfo{
|
||||
@ -433,12 +442,23 @@ void TypeSystem::declareTypeConstructor(TypeExpression::Constructor _typeConstru
|
||||
solAssert(newlyInserted, "Type constructor already declared.");
|
||||
}
|
||||
|
||||
experimental::Type TypeSystem::type(TypeExpression::Constructor _constructor, std::vector<Type> _arguments) const
|
||||
void TypeSystem::declareTypeClass(TypeConstant::Constructor _classDeclaration, std::string _name)
|
||||
{
|
||||
bool newlyInserted = m_typeConstructors.emplace(std::make_pair(_classDeclaration, TypeConstructorInfo{
|
||||
_name,
|
||||
{Arity{vector<Sort>{}, TypeClass{BuiltinClass::Kind}}}
|
||||
})).second;
|
||||
// TODO: proper error handling.
|
||||
solAssert(newlyInserted, "Type class already declared.");
|
||||
|
||||
}
|
||||
|
||||
experimental::Type TypeSystem::type(TypeConstant::Constructor _constructor, std::vector<Type> _arguments) const
|
||||
{
|
||||
// TODO: proper error handling
|
||||
auto const& info = m_typeConstructors.at(_constructor);
|
||||
solAssert(info.arguments() == _arguments.size(), "Invalid arity.");
|
||||
return TypeExpression{_constructor, _arguments};
|
||||
return TypeConstant{_constructor, _arguments};
|
||||
}
|
||||
|
||||
experimental::Type TypeEnvironment::fresh(Type _type, bool _generalize)
|
||||
@ -446,8 +466,8 @@ experimental::Type TypeEnvironment::fresh(Type _type, bool _generalize)
|
||||
std::unordered_map<uint64_t, Type> mapping;
|
||||
auto freshImpl = [&](Type _type, bool _generalize, auto _recurse) -> Type {
|
||||
return std::visit(util::GenericVisitor{
|
||||
[&](TypeExpression const& _type) -> Type {
|
||||
return TypeExpression{
|
||||
[&](TypeConstant const& _type) -> Type {
|
||||
return TypeConstant{
|
||||
_type.constructor,
|
||||
_type.arguments | ranges::views::transform([&](Type _argType) {
|
||||
return _recurse(_argType, _generalize, _recurse);
|
||||
@ -475,7 +495,7 @@ experimental::Type TypeEnvironment::fresh(Type _type, bool _generalize)
|
||||
return freshImpl(_type, _generalize, freshImpl);
|
||||
}
|
||||
|
||||
void TypeSystem::instantiateClass(TypeExpression::Constructor _typeConstructor, Arity _arity)
|
||||
void TypeSystem::instantiateClass(TypeConstant::Constructor _typeConstructor, Arity _arity)
|
||||
{
|
||||
// TODO: proper error handling
|
||||
auto& typeConstructorInfo = m_typeConstructors.at(_typeConstructor);
|
||||
@ -514,8 +534,8 @@ vector<experimental::Type> TypeSystemHelpers::destTupleType(Type _tupleType) con
|
||||
Type tail = arguments.back();
|
||||
while(true)
|
||||
{
|
||||
auto const* tailTypeExpression = get_if<TypeExpression>(&tail);
|
||||
if (!tailTypeExpression)
|
||||
auto const* tailTypeConstant = get_if<TypeConstant>(&tail);
|
||||
if (!tailTypeConstant)
|
||||
break;
|
||||
|
||||
auto [tailConstructor, tailArguments] = destTypeExpression(tail);
|
||||
@ -535,19 +555,31 @@ experimental::Type TypeSystemHelpers::functionType(experimental::Type _argType,
|
||||
return typeSystem.type(BuiltinType::Function, {_argType, _resultType});
|
||||
}
|
||||
|
||||
tuple<TypeExpression::Constructor, vector<experimental::Type>> TypeSystemHelpers::destTypeExpression(Type _type) const
|
||||
tuple<TypeConstant::Constructor, vector<experimental::Type>> TypeSystemHelpers::destTypeExpression(Type _type) const
|
||||
{
|
||||
using ResultType = tuple<TypeExpression::Constructor, vector<Type>>;
|
||||
using ResultType = tuple<TypeConstant::Constructor, vector<Type>>;
|
||||
return std::visit(util::GenericVisitor{
|
||||
[&](TypeExpression const& _type) -> ResultType {
|
||||
[&](TypeConstant const& _type) -> ResultType {
|
||||
return std::make_tuple(_type.constructor, _type.arguments);
|
||||
},
|
||||
[](auto) -> ResultType {
|
||||
[](auto const&) -> ResultType {
|
||||
solAssert(false);
|
||||
}
|
||||
}, _type);
|
||||
}
|
||||
|
||||
bool TypeSystemHelpers::isTypeExpression(Type _type) const
|
||||
{
|
||||
return std::visit(util::GenericVisitor{
|
||||
[&](TypeConstant const&) -> bool {
|
||||
return true;
|
||||
},
|
||||
[](auto const&) -> bool {
|
||||
return false;
|
||||
}
|
||||
}, _type);
|
||||
}
|
||||
|
||||
tuple<experimental::Type, experimental::Type> TypeSystemHelpers::destFunctionType(Type _functionType) const
|
||||
{
|
||||
auto [constructor, arguments] = destTypeExpression(_functionType);
|
||||
@ -557,12 +589,21 @@ tuple<experimental::Type, experimental::Type> TypeSystemHelpers::destFunctionTyp
|
||||
return make_tuple(arguments.front(), arguments.back());
|
||||
}
|
||||
|
||||
bool TypeSystemHelpers::isFunctionType(Type _type) const
|
||||
{
|
||||
if (!isTypeExpression(_type))
|
||||
return false;
|
||||
auto constructor = get<0>(destTypeExpression(_type));
|
||||
auto const* builtinType = get_if<BuiltinType>(&constructor);
|
||||
return builtinType && *builtinType == BuiltinType::Function;
|
||||
}
|
||||
|
||||
vector<experimental::Type> TypeSystemHelpers::typeVars(Type _type) const
|
||||
{
|
||||
vector<Type> typeVars;
|
||||
auto typeVarsImpl = [&](Type _type, auto _recurse) -> void {
|
||||
std::visit(util::GenericVisitor{
|
||||
[&](TypeExpression const& _type) {
|
||||
[&](TypeConstant const& _type) {
|
||||
for (auto arg: _type.arguments)
|
||||
_recurse(arg, _recurse);
|
||||
},
|
||||
@ -585,11 +626,19 @@ experimental::Type TypeSystemHelpers::kindType(Type _type) const
|
||||
experimental::Type TypeSystemHelpers::destKindType(Type _type) const
|
||||
{
|
||||
auto [constructor, arguments] = destTypeExpression(_type);
|
||||
solAssert(constructor == TypeExpression::Constructor{BuiltinType::Type});
|
||||
solAssert(constructor == TypeConstant::Constructor{BuiltinType::Type});
|
||||
solAssert(arguments.size() == 1);
|
||||
return arguments.front();
|
||||
}
|
||||
|
||||
bool TypeSystemHelpers::isKindType(Type _type) const
|
||||
{
|
||||
if (!isTypeExpression(_type))
|
||||
return false;
|
||||
auto constructor = get<0>(destTypeExpression(_type));
|
||||
return constructor == TypeConstant::Constructor{BuiltinType::Type};
|
||||
}
|
||||
|
||||
std::string TypeSystemHelpers::sortToString(Sort _sort) const
|
||||
{
|
||||
switch (_sort.classes.size())
|
||||
|
@ -36,16 +36,17 @@ namespace solidity::frontend::experimental
|
||||
class TypeSystem;
|
||||
class TypeEnvironment;
|
||||
|
||||
struct TypeExpression;
|
||||
struct TypeConstant;
|
||||
struct TypeVariable;
|
||||
|
||||
using Type = std::variant<TypeExpression, TypeVariable>;
|
||||
using Type = std::variant<TypeConstant, TypeVariable>;
|
||||
|
||||
std::string canonicalTypeName(Type _type);
|
||||
|
||||
enum class BuiltinType
|
||||
{
|
||||
Type,
|
||||
Sort,
|
||||
Void,
|
||||
Function,
|
||||
Unit,
|
||||
@ -54,18 +55,18 @@ enum class BuiltinType
|
||||
Integer
|
||||
};
|
||||
|
||||
struct TypeExpression
|
||||
struct TypeConstant
|
||||
{
|
||||
using Constructor = std::variant<BuiltinType, Declaration const*>;
|
||||
Constructor constructor;
|
||||
std::vector<Type> arguments;
|
||||
bool operator<(TypeExpression const& _rhs) const;
|
||||
bool operator==(TypeExpression const& _rhs) const
|
||||
bool operator<(TypeConstant const& _rhs) const;
|
||||
bool operator==(TypeConstant const& _rhs) const
|
||||
{
|
||||
// TODO
|
||||
return !(*this < _rhs) && !(_rhs < *this);
|
||||
}
|
||||
bool operator!=(TypeExpression const& _rhs) const
|
||||
bool operator!=(TypeConstant const& _rhs) const
|
||||
{
|
||||
return !operator==(_rhs);
|
||||
}
|
||||
@ -74,7 +75,8 @@ struct TypeExpression
|
||||
enum class BuiltinClass
|
||||
{
|
||||
Type,
|
||||
Kind
|
||||
Kind,
|
||||
Constraint
|
||||
};
|
||||
|
||||
struct TypeClass
|
||||
@ -91,7 +93,7 @@ struct Sort
|
||||
std::set<TypeClass> classes;
|
||||
bool operator==(Sort const& _rhs) const;
|
||||
bool operator!=(Sort const& _rhs) const { return !operator==(_rhs); }
|
||||
bool operator<(Sort const& _rhs) const;
|
||||
bool operator<=(Sort const& _rhs) const;
|
||||
Sort operator+(Sort const& _rhs) const;
|
||||
Sort operator-(Sort const& _rhs) const;
|
||||
};
|
||||
@ -145,6 +147,7 @@ public:
|
||||
using UnificationFailure = std::variant<TypeMismatch, SortMismatch>;
|
||||
[[nodiscard]] std::vector<UnificationFailure> unify(Type _a, Type _b);
|
||||
std::string typeToString(Type const& _type) const;
|
||||
Sort sort(Type _type) const;
|
||||
private:
|
||||
TypeEnvironment(TypeEnvironment&& _env): m_typeSystem(_env.m_typeSystem), m_typeVariables(std::move(_env.m_typeVariables)) {}
|
||||
[[nodiscard]] std::vector<TypeEnvironment::UnificationFailure> instantiate(TypeVariable _variable, Type _type);
|
||||
@ -155,33 +158,6 @@ private:
|
||||
class TypeSystem
|
||||
{
|
||||
public:
|
||||
TypeSystem();
|
||||
TypeSystem(TypeSystem const&) = delete;
|
||||
TypeSystem const& operator=(TypeSystem const&) = delete;
|
||||
Type type(TypeExpression::Constructor _typeConstructor, std::vector<Type> _arguments) const;
|
||||
std::string typeName(TypeExpression::Constructor _typeConstructor) const
|
||||
{
|
||||
// TODO: proper error handling
|
||||
return m_typeConstructors.at(_typeConstructor).name;
|
||||
}
|
||||
void declareTypeConstructor(TypeExpression::Constructor _typeConstructor, std::string _name, size_t _arguments);
|
||||
size_t constructorArguments(TypeExpression::Constructor _typeConstructor) const
|
||||
{
|
||||
// TODO: error handling
|
||||
return m_typeConstructors.at(_typeConstructor).arguments();
|
||||
}
|
||||
void instantiateClass(TypeExpression::Constructor _typeConstructor, Arity _arity);
|
||||
|
||||
Type freshTypeVariable(bool _generic, Sort _sort);
|
||||
Type freshKindVariable(bool _generic, Sort _sort);
|
||||
|
||||
TypeEnvironment const& env() const { return m_globalTypeEnvironment; }
|
||||
TypeEnvironment& env() { return m_globalTypeEnvironment; }
|
||||
Sort sort(Type _type) const;
|
||||
|
||||
Type freshVariable(bool _generic, Sort _sort);
|
||||
private:
|
||||
size_t m_numTypeVariables = 0;
|
||||
struct TypeConstructorInfo
|
||||
{
|
||||
std::string name;
|
||||
@ -192,21 +168,57 @@ private:
|
||||
return arities.front().argumentSorts.size();
|
||||
}
|
||||
};
|
||||
std::map<TypeExpression::Constructor, TypeConstructorInfo> m_typeConstructors;
|
||||
TypeSystem();
|
||||
TypeSystem(TypeSystem const&) = delete;
|
||||
TypeSystem const& operator=(TypeSystem const&) = delete;
|
||||
Type type(TypeConstant::Constructor _typeConstructor, std::vector<Type> _arguments) const;
|
||||
std::string typeName(TypeConstant::Constructor _typeConstructor) const
|
||||
{
|
||||
// TODO: proper error handling
|
||||
return m_typeConstructors.at(_typeConstructor).name;
|
||||
}
|
||||
void declareTypeConstructor(TypeConstant::Constructor _typeConstructor, std::string _name, size_t _arguments);
|
||||
size_t constructorArguments(TypeConstant::Constructor _typeConstructor) const
|
||||
{
|
||||
// TODO: error handling
|
||||
return m_typeConstructors.at(_typeConstructor).arguments();
|
||||
}
|
||||
TypeConstructorInfo const& constructorInfo(TypeConstant::Constructor _typeConstructor) const
|
||||
{
|
||||
// TODO: error handling
|
||||
return m_typeConstructors.at(_typeConstructor);
|
||||
}
|
||||
|
||||
void declareTypeClass(TypeConstant::Constructor _classDeclaration, std::string _name);
|
||||
void instantiateClass(TypeConstant::Constructor _typeConstructor, Arity _arity);
|
||||
|
||||
Type freshTypeVariable(bool _generic, Sort _sort);
|
||||
Type freshKindVariable(bool _generic, Sort _sort);
|
||||
|
||||
TypeEnvironment const& env() const { return m_globalTypeEnvironment; }
|
||||
TypeEnvironment& env() { return m_globalTypeEnvironment; }
|
||||
|
||||
Type freshVariable(bool _generic, Sort _sort);
|
||||
private:
|
||||
size_t m_numTypeVariables = 0;
|
||||
std::map<TypeConstant::Constructor, TypeConstructorInfo> m_typeConstructors;
|
||||
TypeEnvironment m_globalTypeEnvironment{*this};
|
||||
};
|
||||
|
||||
struct TypeSystemHelpers
|
||||
{
|
||||
TypeSystem const& typeSystem;
|
||||
std::tuple<TypeExpression::Constructor, std::vector<Type>> destTypeExpression(Type _functionType) const;
|
||||
std::tuple<TypeConstant::Constructor, std::vector<Type>> destTypeExpression(Type _type) const;
|
||||
bool isTypeExpression(Type _type) const;
|
||||
Type tupleType(std::vector<Type> _elements) const;
|
||||
std::vector<Type> destTupleType(Type _tupleType) const;
|
||||
Type functionType(Type _argType, Type _resultType) const;
|
||||
std::tuple<Type, Type> destFunctionType(Type _functionType) const;
|
||||
bool isFunctionType(Type _type) const;
|
||||
std::vector<Type> typeVars(Type _type) const;
|
||||
std::string sortToString(Sort _sort) const;
|
||||
Type kindType(Type _type) const;
|
||||
bool isKindType(Type _type) const;
|
||||
Type destKindType(Type _type) const;
|
||||
};
|
||||
|
||||
|
@ -2098,9 +2098,17 @@ ASTPointer<Expression> Parser::parseBinaryExpression(
|
||||
|
||||
int Parser::tokenPrecedence(Token _token) const
|
||||
{
|
||||
if (m_experimentalSolidityEnabledInCurrentSourceUnit && _token == Token::Colon)
|
||||
if (m_experimentalSolidityEnabledInCurrentSourceUnit)
|
||||
{
|
||||
return 1000;
|
||||
switch(_token)
|
||||
{
|
||||
case Token::Colon:
|
||||
return 1000;
|
||||
case Token::RightArrow:
|
||||
return 999;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return TokenTraits::precedence(m_scanner->currentToken());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user