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);
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;
}

View File

@ -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);
}

View File

@ -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
);

View File

@ -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);

View File

@ -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;

View File

@ -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())

View File

@ -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;
};

View File

@ -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());
}