This commit is contained in:
Daniel Kirchner 2023-06-24 18:38:55 +02:00
parent bd4be335d4
commit f9d6e805ba
8 changed files with 224 additions and 96 deletions

View File

@ -41,7 +41,12 @@ bool DebugWarner::visitNode(ASTNode const& _node)
auto const& typeInferenceAnnotation = m_analysis.annotation<TypeInference>(_node); auto const& typeInferenceAnnotation = m_analysis.annotation<TypeInference>(_node);
if (typeInferenceAnnotation.type) 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; return true;
} }

View File

@ -328,9 +328,27 @@ bool TypeInference::visit(BinaryOperation const& _binaryOperation)
unify(*leftAnnotation.type, *rightAnnotation.type, _binaryOperation.location()); unify(*leftAnnotation.type, *rightAnnotation.type, _binaryOperation.location());
operationAnnotation.type = leftAnnotation.type; 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 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.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(), "Invalid binary operations in type context.");
operationAnnotation.type = helper.kindType(m_typeSystem.freshTypeVariable(false, {})); operationAnnotation.type = helper.kindType(m_typeSystem.freshTypeVariable(false, {}));
} }
return false; return false;
@ -358,12 +376,17 @@ bool TypeInference::visit(VariableDeclaration const& _variableDeclaration)
_variableDeclaration.typeExpression()->accept(*this); _variableDeclaration.typeExpression()->accept(*this);
auto& typeExpressionAnnotation = annotation(*_variableDeclaration.typeExpression()); auto& typeExpressionAnnotation = annotation(*_variableDeclaration.typeExpression());
solAssert(typeExpressionAnnotation.type); solAssert(typeExpressionAnnotation.type);
if (helper.isKindType(*typeExpressionAnnotation.type))
variableAnnotation.type = m_env->fresh(helper.destKindType(*typeExpressionAnnotation.type), false); 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; return false;
} }
variableAnnotation.type = m_typeSystem.freshTypeVariable(false, {}); variableAnnotation.type = m_typeSystem.freshTypeVariable(false, {});
return false; return false;
case ExpressionContext::Type: case ExpressionContext::Type:
if (_variableDeclaration.typeExpression()) if (_variableDeclaration.typeExpression())
@ -469,12 +492,12 @@ bool TypeInference::visit(Identifier const& _identifier)
if (dynamic_cast<VariableDeclaration const*>(referencedDeclaration)) if (dynamic_cast<VariableDeclaration const*>(referencedDeclaration))
{ {
helper.destKindType(*declarationAnnotation.type); // TODO: helper.destKindType(*declarationAnnotation.type);
identifierAnnotation.type = declarationAnnotation.type; identifierAnnotation.type = declarationAnnotation.type;
} }
else if (dynamic_cast<TypeDefinition const*>(referencedDeclaration)) else if (dynamic_cast<TypeDefinition const*>(referencedDeclaration))
{ {
helper.destKindType(*declarationAnnotation.type); // TODO: helper.destKindType(*declarationAnnotation.type);
identifierAnnotation.type = m_env->fresh(*declarationAnnotation.type, true); identifierAnnotation.type = m_env->fresh(*declarationAnnotation.type, true);
} }
else else
@ -511,12 +534,27 @@ void TypeInference::endVisit(TupleExpression const& _tupleExpression)
auto& expressionAnnotation = annotation(_tupleExpression); auto& expressionAnnotation = annotation(_tupleExpression);
solAssert(!expressionAnnotation.type); solAssert(!expressionAnnotation.type);
TypeSystemHelpers helper{m_typeSystem};
auto componentTypes = _tupleExpression.components() | ranges::views::transform([&](auto _expr) -> Type { auto componentTypes = _tupleExpression.components() | ranges::views::transform([&](auto _expr) -> Type {
auto& componentAnnotation = annotation(*_expr); auto& componentAnnotation = annotation(*_expr);
solAssert(componentAnnotation.type); solAssert(componentAnnotation.type);
switch(m_expressionContext)
{
case ExpressionContext::Term:
return *componentAnnotation.type; 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>>; }) | ranges::to<vector<Type>>;
TypeSystemHelpers helper{m_typeSystem};
switch (m_expressionContext) switch (m_expressionContext)
{ {
case ExpressionContext::Term: case ExpressionContext::Term:
@ -658,12 +696,12 @@ bool TypeInference::visit(TypeDefinition const& _typeDefinition)
TypeSystemHelpers helper{m_typeSystem}; TypeSystemHelpers helper{m_typeSystem};
if (arguments.empty()) 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 else
typeDefinitionAnnotation.type = typeDefinitionAnnotation.type =
helper.functionType( helper.functionType(
helper.kindType(helper.tupleType(arguments)), 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; return false;
} }
@ -679,15 +717,33 @@ void TypeInference::endVisit(FunctionCall const& _functionCall)
Type functionType = *expressionAnnotation.type; Type functionType = *expressionAnnotation.type;
TypeSystemHelpers helper{m_typeSystem};
std::vector<Type> argTypes; std::vector<Type> argTypes;
for(auto arg: _functionCall.arguments()) for(auto arg: _functionCall.arguments())
{ {
auto& argAnnotation = annotation(*arg); auto& argAnnotation = annotation(*arg);
solAssert(argAnnotation.type); solAssert(argAnnotation.type);
switch(m_expressionContext)
{
case ExpressionContext::Term:
argTypes.emplace_back(*argAnnotation.type); 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) switch(m_expressionContext)
{ {
case ExpressionContext::Term: case ExpressionContext::Term:
@ -701,17 +757,15 @@ void TypeInference::endVisit(FunctionCall const& _functionCall)
} }
case ExpressionContext::Type: case ExpressionContext::Type:
{ {
Type argTuple = helper.tupleType(argTypes); Type argTuple = helper.kindType(helper.tupleType(argTypes));
Type genericFunctionType = helper.functionType(argTuple, m_typeSystem.freshTypeVariable(false, {})); Type genericFunctionType = helper.functionType(argTuple, m_typeSystem.freshKindVariable(false, {}));
unify(genericFunctionType, functionType, _functionCall.location()); unify(genericFunctionType, functionType, _functionCall.location());
functionCallAnnotation.type = m_env->resolve(std::get<1>(helper.destFunctionType(m_env->resolve(genericFunctionType)))); functionCallAnnotation.type = m_env->resolve(std::get<1>(helper.destFunctionType(m_env->resolve(genericFunctionType))));
break; break;
} }
case ExpressionContext::Sort: case ExpressionContext::Sort:
m_errorReporter.typeError(0000_error, _functionCall.location(), "Function call in sort context."); solAssert(false);
functionCallAnnotation.type = m_typeSystem.freshTypeVariable(false, {});
break;
} }

View File

@ -69,7 +69,7 @@ bool TypeRegistration::visit(TypeClassInstantiation const& _typeClassInstantiati
TypeName const& typeName = _typeClassInstantiation.typeConstructor(); TypeName const& typeName = _typeClassInstantiation.typeConstructor();
TypeExpression::Constructor typeConstructor = [&]() -> TypeExpression::Constructor { TypeConstant::Constructor typeConstructor = [&]() -> TypeConstant::Constructor {
if (auto const* elementaryTypeName = dynamic_cast<ElementaryTypeName const*>(&typeName)) if (auto const* elementaryTypeName = dynamic_cast<ElementaryTypeName const*>(&typeName))
{ {
switch(elementaryTypeName->typeName().token()) switch(elementaryTypeName->typeName().token())
@ -149,7 +149,7 @@ bool TypeRegistration::visit(TypeClassInstantiation const& _typeClassInstantiati
bool TypeRegistration::visit(TypeDefinition const& _typeDefinition) bool TypeRegistration::visit(TypeDefinition const& _typeDefinition)
{ {
m_typeSystem.declareTypeConstructor( m_typeSystem.declareTypeConstructor(
TypeExpression::Constructor{&_typeDefinition}, TypeConstant::Constructor{&_typeDefinition},
_typeDefinition.name(), _typeDefinition.name(),
_typeDefinition.arguments() ? _typeDefinition.arguments()->parameters().size() : 0 _typeDefinition.arguments() ? _typeDefinition.arguments()->parameters().size() : 0
); );

View File

@ -33,7 +33,7 @@ public:
struct Annotation struct Annotation
{ {
Type type; Type type;
std::map<TypeExpression::Constructor, TypeClassInstantiation const*> instantiations; std::map<TypeConstant::Constructor, TypeClassInstantiation const*> instantiations;
}; };
TypeRegistration(Analysis& _analysis); TypeRegistration(Analysis& _analysis);

View File

@ -2143,7 +2143,7 @@ public:
Expression(_id, _location), m_left(std::move(_left)), m_operator(_operator), m_right(std::move(_right)) Expression(_id, _location), m_left(std::move(_left)), m_operator(_operator), m_right(std::move(_right))
{ {
// TODO: assert against colon for non-experimental solidity // 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(ASTVisitor& _visitor) override;
void accept(ASTConstVisitor& _visitor) const override; void accept(ASTConstVisitor& _visitor) const override;

View File

@ -65,6 +65,8 @@ string TypeClass::toString() const
return "type"; return "type";
case BuiltinClass::Kind: case BuiltinClass::Kind:
return "kind"; return "kind";
case BuiltinClass::Constraint:
return "contraint";
} }
solAssert(false); solAssert(false);
}, },
@ -82,7 +84,7 @@ bool Sort::operator==(Sort const& _rhs) const
return true; return true;
} }
bool Sort::operator<(Sort const& _rhs) const bool Sort::operator<=(Sort const& _rhs) const
{ {
for (auto c: classes) for (auto c: classes)
if (!_rhs.classes.count(c)) if (!_rhs.classes.count(c))
@ -105,7 +107,7 @@ Sort Sort::operator-(Sort const& _rhs) const
return result; return result;
} }
bool TypeExpression::operator<(TypeExpression const& _rhs) const bool TypeConstant::operator<(TypeConstant const& _rhs) const
{ {
if (constructor < _rhs.constructor) if (constructor < _rhs.constructor)
return true; return true;
@ -125,7 +127,7 @@ bool TypeExpression::operator<(TypeExpression const& _rhs) const
std::string experimental::canonicalTypeName(Type _type) std::string experimental::canonicalTypeName(Type _type)
{ {
return std::visit(util::GenericVisitor{ return std::visit(util::GenericVisitor{
[&](TypeExpression const& _type) { [&](TypeConstant const& _type) {
std::stringstream stream; std::stringstream stream;
auto printTypeArguments = [&]() { auto printTypeArguments = [&]() {
if (!_type.arguments.empty()) if (!_type.arguments.empty())
@ -153,6 +155,9 @@ std::string experimental::canonicalTypeName(Type _type)
case BuiltinType::Type: case BuiltinType::Type:
stream << "type"; stream << "type";
break; break;
case BuiltinType::Sort:
stream << "sort";
break;
case BuiltinType::Void: case BuiltinType::Void:
stream << "void"; stream << "void";
break; break;
@ -185,7 +190,7 @@ std::string experimental::canonicalTypeName(Type _type)
std::string TypeEnvironment::typeToString(Type const& _type) const std::string TypeEnvironment::typeToString(Type const& _type) const
{ {
return std::visit(util::GenericVisitor{ return std::visit(util::GenericVisitor{
[&](TypeExpression const& _type) { [&](TypeConstant const& _type) {
std::stringstream stream; std::stringstream stream;
auto printTypeArguments = [&]() { auto printTypeArguments = [&]() {
if (!_type.arguments.empty()) if (!_type.arguments.empty())
@ -277,9 +282,9 @@ vector<TypeEnvironment::UnificationFailure> TypeEnvironment::unify(Type _a, Type
} }
else else
{ {
if (_left.sort() < _right.sort()) if (_left.sort() <= _right.sort())
failures += instantiate(_left, _right); failures += instantiate(_left, _right);
else if (_right.sort() < _left.sort()) else if (_right.sort() <= _left.sort())
failures += instantiate(_right, _left); failures += instantiate(_right, _left);
else else
{ {
@ -295,7 +300,7 @@ vector<TypeEnvironment::UnificationFailure> TypeEnvironment::unify(Type _a, Type
[&](auto, TypeVariable _var) { [&](auto, TypeVariable _var) {
failures += instantiate(_var, _a); failures += instantiate(_var, _a);
}, },
[&](TypeExpression _left, TypeExpression _right) { [&](TypeConstant _left, TypeConstant _right) {
if(_left.constructor != _right.constructor) if(_left.constructor != _right.constructor)
return unificationFailure(); return unificationFailure();
if (_left.arguments.size() != _right.arguments.size()) if (_left.arguments.size() != _right.arguments.size())
@ -323,13 +328,16 @@ TypeSystem::TypeSystem()
Sort typeSort{{TypeClass{BuiltinClass::Type}}}; Sort typeSort{{TypeClass{BuiltinClass::Type}}};
m_typeConstructors[BuiltinType::Type] = TypeConstructorInfo{ m_typeConstructors[BuiltinType::Type] = TypeConstructorInfo{
"type", "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{ m_typeConstructors[BuiltinType::Function] = TypeConstructorInfo{
"fun", "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) vector<TypeEnvironment::UnificationFailure> TypeEnvironment::instantiate(TypeVariable _variable, Type _type)
{ {
Sort sort = m_typeSystem.sort(_type); Sort typeSort = sort(_type);
if (!(_variable.sort() < sort)) 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); solAssert(m_typeVariables.emplace(_variable.index(), _type).second);
return {}; return {};
@ -377,8 +385,8 @@ experimental::Type TypeEnvironment::resolve(Type _type) const
experimental::Type TypeEnvironment::resolveRecursive(Type _type) const experimental::Type TypeEnvironment::resolveRecursive(Type _type) const
{ {
return std::visit(util::GenericVisitor{ return std::visit(util::GenericVisitor{
[&](TypeExpression const& _type) -> Type { [&](TypeConstant const& _type) -> Type {
return TypeExpression{ return TypeConstant{
_type.constructor, _type.constructor,
_type.arguments | ranges::views::transform([&](Type _argType) { _type.arguments | ranges::views::transform([&](Type _argType) {
return resolveRecursive(_argType); return resolveRecursive(_argType);
@ -391,14 +399,14 @@ experimental::Type TypeEnvironment::resolveRecursive(Type _type) const
}, resolve(_type)); }, resolve(_type));
} }
Sort TypeSystem::sort(Type _type) const Sort TypeEnvironment::sort(Type _type) const
{ {
return std::visit(util::GenericVisitor{ return std::visit(util::GenericVisitor{
[&](TypeExpression const& _expression) -> Sort [&](TypeConstant const& _expression) -> Sort
{ {
auto const& constructorInfo = m_typeConstructors.at(_expression.constructor); auto const& constructorInfo = m_typeSystem.constructorInfo(_expression.constructor);
auto argumentSorts = _expression.arguments | ranges::views::transform([&](Type _type) { auto argumentSorts = _expression.arguments | ranges::views::transform([&](Type _argumentType) {
return sort(_type); return sort(resolve(_argumentType));
}) | ranges::to<vector<Sort>>; }) | ranges::to<vector<Sort>>;
Sort sort; Sort sort;
for (auto const& arity: constructorInfo.arities) for (auto const& arity: constructorInfo.arities)
@ -407,12 +415,13 @@ Sort TypeSystem::sort(Type _type) const
bool hasArity = true; bool hasArity = true;
for (auto&& [argumentSort, arityArgumentSort]: ranges::zip_view(argumentSorts, arity.argumentSorts)) for (auto&& [argumentSort, arityArgumentSort]: ranges::zip_view(argumentSorts, arity.argumentSorts))
{ {
if (!(argumentSort < arityArgumentSort)) if (!(arityArgumentSort <= argumentSort))
{ {
hasArity = false; hasArity = false;
break; break;
} }
} }
if (hasArity) if (hasArity)
sort.classes.insert(arity.typeClass); sort.classes.insert(arity.typeClass);
} }
@ -422,7 +431,7 @@ Sort TypeSystem::sort(Type _type) const
}, _type); }, _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}}}; Sort baseSort{{TypeClass{BuiltinClass::Type}}};
bool newlyInserted = m_typeConstructors.emplace(std::make_pair(_typeConstructor, TypeConstructorInfo{ 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."); 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 // TODO: proper error handling
auto const& info = m_typeConstructors.at(_constructor); auto const& info = m_typeConstructors.at(_constructor);
solAssert(info.arguments() == _arguments.size(), "Invalid arity."); solAssert(info.arguments() == _arguments.size(), "Invalid arity.");
return TypeExpression{_constructor, _arguments}; return TypeConstant{_constructor, _arguments};
} }
experimental::Type TypeEnvironment::fresh(Type _type, bool _generalize) 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; std::unordered_map<uint64_t, Type> mapping;
auto freshImpl = [&](Type _type, bool _generalize, auto _recurse) -> Type { auto freshImpl = [&](Type _type, bool _generalize, auto _recurse) -> Type {
return std::visit(util::GenericVisitor{ return std::visit(util::GenericVisitor{
[&](TypeExpression const& _type) -> Type { [&](TypeConstant const& _type) -> Type {
return TypeExpression{ return TypeConstant{
_type.constructor, _type.constructor,
_type.arguments | ranges::views::transform([&](Type _argType) { _type.arguments | ranges::views::transform([&](Type _argType) {
return _recurse(_argType, _generalize, _recurse); return _recurse(_argType, _generalize, _recurse);
@ -475,7 +495,7 @@ experimental::Type TypeEnvironment::fresh(Type _type, bool _generalize)
return freshImpl(_type, _generalize, freshImpl); 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 // TODO: proper error handling
auto& typeConstructorInfo = m_typeConstructors.at(_typeConstructor); auto& typeConstructorInfo = m_typeConstructors.at(_typeConstructor);
@ -514,8 +534,8 @@ vector<experimental::Type> TypeSystemHelpers::destTupleType(Type _tupleType) con
Type tail = arguments.back(); Type tail = arguments.back();
while(true) while(true)
{ {
auto const* tailTypeExpression = get_if<TypeExpression>(&tail); auto const* tailTypeConstant = get_if<TypeConstant>(&tail);
if (!tailTypeExpression) if (!tailTypeConstant)
break; break;
auto [tailConstructor, tailArguments] = destTypeExpression(tail); auto [tailConstructor, tailArguments] = destTypeExpression(tail);
@ -535,19 +555,31 @@ experimental::Type TypeSystemHelpers::functionType(experimental::Type _argType,
return typeSystem.type(BuiltinType::Function, {_argType, _resultType}); 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{ return std::visit(util::GenericVisitor{
[&](TypeExpression const& _type) -> ResultType { [&](TypeConstant const& _type) -> ResultType {
return std::make_tuple(_type.constructor, _type.arguments); return std::make_tuple(_type.constructor, _type.arguments);
}, },
[](auto) -> ResultType { [](auto const&) -> ResultType {
solAssert(false); solAssert(false);
} }
}, _type); }, _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 tuple<experimental::Type, experimental::Type> TypeSystemHelpers::destFunctionType(Type _functionType) const
{ {
auto [constructor, arguments] = destTypeExpression(_functionType); auto [constructor, arguments] = destTypeExpression(_functionType);
@ -557,12 +589,21 @@ tuple<experimental::Type, experimental::Type> TypeSystemHelpers::destFunctionTyp
return make_tuple(arguments.front(), arguments.back()); 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<experimental::Type> TypeSystemHelpers::typeVars(Type _type) const
{ {
vector<Type> typeVars; vector<Type> typeVars;
auto typeVarsImpl = [&](Type _type, auto _recurse) -> void { auto typeVarsImpl = [&](Type _type, auto _recurse) -> void {
std::visit(util::GenericVisitor{ std::visit(util::GenericVisitor{
[&](TypeExpression const& _type) { [&](TypeConstant const& _type) {
for (auto arg: _type.arguments) for (auto arg: _type.arguments)
_recurse(arg, _recurse); _recurse(arg, _recurse);
}, },
@ -585,11 +626,19 @@ experimental::Type TypeSystemHelpers::kindType(Type _type) const
experimental::Type TypeSystemHelpers::destKindType(Type _type) const experimental::Type TypeSystemHelpers::destKindType(Type _type) const
{ {
auto [constructor, arguments] = destTypeExpression(_type); auto [constructor, arguments] = destTypeExpression(_type);
solAssert(constructor == TypeExpression::Constructor{BuiltinType::Type}); solAssert(constructor == TypeConstant::Constructor{BuiltinType::Type});
solAssert(arguments.size() == 1); solAssert(arguments.size() == 1);
return arguments.front(); 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 std::string TypeSystemHelpers::sortToString(Sort _sort) const
{ {
switch (_sort.classes.size()) switch (_sort.classes.size())

View File

@ -36,16 +36,17 @@ namespace solidity::frontend::experimental
class TypeSystem; class TypeSystem;
class TypeEnvironment; class TypeEnvironment;
struct TypeExpression; struct TypeConstant;
struct TypeVariable; struct TypeVariable;
using Type = std::variant<TypeExpression, TypeVariable>; using Type = std::variant<TypeConstant, TypeVariable>;
std::string canonicalTypeName(Type _type); std::string canonicalTypeName(Type _type);
enum class BuiltinType enum class BuiltinType
{ {
Type, Type,
Sort,
Void, Void,
Function, Function,
Unit, Unit,
@ -54,18 +55,18 @@ enum class BuiltinType
Integer Integer
}; };
struct TypeExpression struct TypeConstant
{ {
using Constructor = std::variant<BuiltinType, Declaration const*>; using Constructor = std::variant<BuiltinType, Declaration const*>;
Constructor constructor; Constructor constructor;
std::vector<Type> arguments; std::vector<Type> arguments;
bool operator<(TypeExpression const& _rhs) const; bool operator<(TypeConstant const& _rhs) const;
bool operator==(TypeExpression const& _rhs) const bool operator==(TypeConstant const& _rhs) const
{ {
// TODO // TODO
return !(*this < _rhs) && !(_rhs < *this); return !(*this < _rhs) && !(_rhs < *this);
} }
bool operator!=(TypeExpression const& _rhs) const bool operator!=(TypeConstant const& _rhs) const
{ {
return !operator==(_rhs); return !operator==(_rhs);
} }
@ -74,7 +75,8 @@ struct TypeExpression
enum class BuiltinClass enum class BuiltinClass
{ {
Type, Type,
Kind Kind,
Constraint
}; };
struct TypeClass struct TypeClass
@ -91,7 +93,7 @@ struct Sort
std::set<TypeClass> classes; std::set<TypeClass> classes;
bool operator==(Sort const& _rhs) const; bool operator==(Sort const& _rhs) const;
bool operator!=(Sort const& _rhs) const { return !operator==(_rhs); } 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;
Sort operator-(Sort const& _rhs) const; Sort operator-(Sort const& _rhs) const;
}; };
@ -145,6 +147,7 @@ public:
using UnificationFailure = std::variant<TypeMismatch, SortMismatch>; using UnificationFailure = std::variant<TypeMismatch, SortMismatch>;
[[nodiscard]] std::vector<UnificationFailure> unify(Type _a, Type _b); [[nodiscard]] std::vector<UnificationFailure> unify(Type _a, Type _b);
std::string typeToString(Type const& _type) const; std::string typeToString(Type const& _type) const;
Sort sort(Type _type) const;
private: private:
TypeEnvironment(TypeEnvironment&& _env): m_typeSystem(_env.m_typeSystem), m_typeVariables(std::move(_env.m_typeVariables)) {} 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); [[nodiscard]] std::vector<TypeEnvironment::UnificationFailure> instantiate(TypeVariable _variable, Type _type);
@ -155,33 +158,6 @@ private:
class TypeSystem class TypeSystem
{ {
public: 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 struct TypeConstructorInfo
{ {
std::string name; std::string name;
@ -192,21 +168,57 @@ private:
return arities.front().argumentSorts.size(); 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}; TypeEnvironment m_globalTypeEnvironment{*this};
}; };
struct TypeSystemHelpers struct TypeSystemHelpers
{ {
TypeSystem const& typeSystem; 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; Type tupleType(std::vector<Type> _elements) const;
std::vector<Type> destTupleType(Type _tupleType) const; std::vector<Type> destTupleType(Type _tupleType) const;
Type functionType(Type _argType, Type _resultType) const; Type functionType(Type _argType, Type _resultType) const;
std::tuple<Type, Type> destFunctionType(Type _functionType) const; std::tuple<Type, Type> destFunctionType(Type _functionType) const;
bool isFunctionType(Type _type) const;
std::vector<Type> typeVars(Type _type) const; std::vector<Type> typeVars(Type _type) const;
std::string sortToString(Sort _sort) const; std::string sortToString(Sort _sort) const;
Type kindType(Type _type) const; Type kindType(Type _type) const;
bool isKindType(Type _type) const;
Type destKindType(Type _type) const; Type destKindType(Type _type) const;
}; };

View File

@ -2098,9 +2098,17 @@ ASTPointer<Expression> Parser::parseBinaryExpression(
int Parser::tokenPrecedence(Token _token) const int Parser::tokenPrecedence(Token _token) const
{ {
if (m_experimentalSolidityEnabledInCurrentSourceUnit && _token == Token::Colon) if (m_experimentalSolidityEnabledInCurrentSourceUnit)
{ {
switch(_token)
{
case Token::Colon:
return 1000; return 1000;
case Token::RightArrow:
return 999;
default:
break;
}
} }
return TokenTraits::precedence(m_scanner->currentToken()); return TokenTraits::precedence(m_scanner->currentToken());
} }