This commit is contained in:
Daniel Kirchner 2023-06-24 18:53:47 +02:00
parent f9d6e805ba
commit 955ada39e5
9 changed files with 354 additions and 287 deletions

View File

@ -78,6 +78,8 @@ set(sources
ast/Types.h ast/Types.h
ast/TypeProvider.cpp ast/TypeProvider.cpp
ast/TypeProvider.h ast/TypeProvider.h
ast/experimental/Type.cpp
ast/experimental/Type.h
ast/experimental/TypeSystem.cpp ast/experimental/TypeSystem.cpp
ast/experimental/TypeSystem.h ast/experimental/TypeSystem.h
codegen/ABIFunctions.cpp codegen/ABIFunctions.cpp

View File

@ -696,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(TypeConstant::Constructor{&_typeDefinition}, arguments)); typeDefinitionAnnotation.type = helper.kindType(m_typeSystem.type(TypeConstructor{&_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(TypeConstant::Constructor{&_typeDefinition}, arguments)) helper.kindType(m_typeSystem.type(TypeConstructor{&_typeDefinition}, arguments))
); );
return false; return false;
} }

View File

@ -69,7 +69,7 @@ bool TypeRegistration::visit(TypeClassInstantiation const& _typeClassInstantiati
TypeName const& typeName = _typeClassInstantiation.typeConstructor(); TypeName const& typeName = _typeClassInstantiation.typeConstructor();
TypeConstant::Constructor typeConstructor = [&]() -> TypeConstant::Constructor { TypeConstructor typeConstructor = [&]() -> TypeConstructor {
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(
TypeConstant::Constructor{&_typeDefinition}, TypeConstructor{&_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<TypeConstant::Constructor, TypeClassInstantiation const*> instantiations; std::map<TypeConstructor, TypeClassInstantiation const*> instantiations;
}; };
TypeRegistration(Analysis& _analysis); TypeRegistration(Analysis& _analysis);

View File

@ -0,0 +1,182 @@
/*
This file is part of solidity.
solidity is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
solidity is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
// SPDX-License-Identifier: GPL-3.0
#include <libsolidity/ast/experimental/Type.h>
#include <libsolidity/ast/AST.h>
#include <libsolutil/Visitor.h>
#include <range/v3/view/drop_last.hpp>
#include <range/v3/view/zip.hpp>
#include <sstream>
using namespace std;
using namespace solidity;
using namespace solidity::frontend::experimental;
std::string frontend::experimental::canonicalTypeName(Type _type)
{
return std::visit(util::GenericVisitor{
[&](TypeConstant const& _type) {
std::stringstream stream;
auto printTypeArguments = [&]() {
if (!_type.arguments.empty())
{
stream << "$";
for (auto type: _type.arguments | ranges::views::drop_last(1))
stream << canonicalTypeName(type) << "$";
stream << canonicalTypeName(_type.arguments.back());
stream << "$";
}
};
std::visit(util::GenericVisitor{
[&](Declaration const* _declaration) {
printTypeArguments();
if (auto const* typeDeclarationAnnotation = dynamic_cast<TypeDeclarationAnnotation const*>(&_declaration->annotation()))
stream << *typeDeclarationAnnotation->canonicalName;
else
// TODO: canonical name
stream << _declaration->name();
},
[&](BuiltinType _builtinType) {
printTypeArguments();
switch(_builtinType)
{
case BuiltinType::Type:
stream << "type";
break;
case BuiltinType::Sort:
stream << "sort";
break;
case BuiltinType::Void:
stream << "void";
break;
case BuiltinType::Function:
stream << "fun";
break;
case BuiltinType::Unit:
stream << "unit";
break;
case BuiltinType::Pair:
stream << "pair";
break;
case BuiltinType::Word:
stream << "word";
break;
case BuiltinType::Integer:
stream << "integer";
break;
}
}
}, _type.constructor);
return stream.str();
},
[](TypeVariable const&)-> string {
solAssert(false);
},
}, _type);
}
bool TypeClass::operator<(TypeClass const& _rhs) const
{
return std::visit(util::GenericVisitor{
[](BuiltinClass _left, BuiltinClass _right) { return _left < _right; },
[](TypeClassDefinition const* _left, TypeClassDefinition const* _right) { return _left->id() < _right->id(); },
[](BuiltinClass, TypeClassDefinition const*) { return true; },
[](TypeClassDefinition const*, BuiltinClass) { return false; },
}, declaration, _rhs.declaration);
}
bool TypeClass::operator==(TypeClass const& _rhs) const
{
return std::visit(util::GenericVisitor{
[](BuiltinClass _left, BuiltinClass _right) { return _left == _right; },
[](TypeClassDefinition const* _left, TypeClassDefinition const* _right) { return _left->id() == _right->id(); },
[](BuiltinClass, TypeClassDefinition const*) { return false; },
[](TypeClassDefinition const*, BuiltinClass) { return false; },
}, declaration, _rhs.declaration);
}
string TypeClass::toString() const
{
return std::visit(util::GenericVisitor{
[](BuiltinClass _class) -> string {
switch(_class)
{
case BuiltinClass::Type:
return "type";
case BuiltinClass::Kind:
return "kind";
case BuiltinClass::Constraint:
return "contraint";
}
solAssert(false);
},
[](TypeClassDefinition const* _declaration) { return _declaration->name(); },
}, declaration);
}
bool Sort::operator==(Sort const& _rhs) const
{
if (classes.size() != _rhs.classes.size())
return false;
for (auto [lhs, rhs]: ranges::zip_view(classes, _rhs.classes))
if (lhs != rhs)
return false;
return true;
}
bool Sort::operator<=(Sort const& _rhs) const
{
for (auto c: classes)
if (!_rhs.classes.count(c))
return false;
return true;
}
Sort Sort::operator+(Sort const& _rhs) const
{
Sort result { classes };
result.classes += _rhs.classes;
return result;
}
Sort Sort::operator-(Sort const& _rhs) const
{
Sort result { classes };
result.classes -= _rhs.classes;
return result;
}
bool TypeConstant::operator<(TypeConstant const& _rhs) const
{
if (constructor < _rhs.constructor)
return true;
if (_rhs.constructor < constructor)
return false;
solAssert(arguments.size() == _rhs.arguments.size());
for(auto [lhs, rhs]: ranges::zip_view(arguments, _rhs.arguments))
{
if (lhs < rhs)
return true;
if (rhs < lhs)
return false;
}
return false;
}

View File

@ -0,0 +1,133 @@
/*
This file is part of solidity.
solidity is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
solidity is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
// SPDX-License-Identifier: GPL-3.0
#pragma once
#include <set>
#include <string>
#include <variant>
#include <vector>
namespace solidity::frontend
{
class Declaration;
class TypeClassDefinition;
}
namespace solidity::frontend::experimental
{
class TypeSystem;
struct TypeConstant;
struct TypeVariable;
using Type = std::variant<TypeConstant, TypeVariable>;
std::string canonicalTypeName(Type _type);
enum class BuiltinType
{
Type,
Sort,
Void,
Function,
Unit,
Pair,
Word,
Integer
};
using TypeConstructor = std::variant<BuiltinType, Declaration const*>;
struct TypeConstant
{
TypeConstructor constructor;
std::vector<Type> arguments;
bool operator<(TypeConstant const& _rhs) const;
bool operator==(TypeConstant const& _rhs) const
{
// TODO
return !(*this < _rhs) && !(_rhs < *this);
}
bool operator!=(TypeConstant const& _rhs) const
{
return !operator==(_rhs);
}
};
enum class BuiltinClass
{
Type,
Kind,
Constraint
};
struct TypeClass
{
std::variant<BuiltinClass, TypeClassDefinition const*> declaration;
std::string toString() const;
bool operator<(TypeClass const& _rhs) const;
bool operator==(TypeClass const& _rhs) const;
bool operator!=(TypeClass const& _rhs) const { return !operator==(_rhs); }
};
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;
Sort operator+(Sort const& _rhs) const;
Sort operator-(Sort const& _rhs) const;
};
struct Arity
{
std::vector<Sort> argumentSorts;
TypeClass typeClass;
};
struct TypeVariable
{
size_t index() const { return m_index; }
bool generic() const { return m_generic; }
Sort const& sort() const { return m_sort; }
bool operator<(TypeVariable const& _rhs) const
{
// TODO: more robust comparison?
return m_index < _rhs.m_index;
}
bool operator==(TypeVariable const& _rhs) const
{
// TODO
return !(*this < _rhs) && !(_rhs < *this);
}
bool operator!=(TypeVariable const& _rhs) const
{
return !operator==(_rhs);
}
private:
friend class TypeSystem;
size_t m_index = 0;
Sort m_sort;
bool m_generic = false;
TypeVariable(size_t _index, Sort _sort, bool _generic):
m_index(_index), m_sort(std::move(_sort)), m_generic(_generic) {}
};
}

View File

@ -35,158 +35,6 @@ using namespace std;
using namespace solidity::frontend; using namespace solidity::frontend;
using namespace solidity::frontend::experimental; using namespace solidity::frontend::experimental;
bool TypeClass::operator<(TypeClass const& _rhs) const
{
return std::visit(util::GenericVisitor{
[](BuiltinClass _left, BuiltinClass _right) { return _left < _right; },
[](TypeClassDefinition const* _left, TypeClassDefinition const* _right) { return _left->id() < _right->id(); },
[](BuiltinClass, TypeClassDefinition const*) { return true; },
[](TypeClassDefinition const*, BuiltinClass) { return false; },
}, declaration, _rhs.declaration);
}
bool TypeClass::operator==(TypeClass const& _rhs) const
{
return std::visit(util::GenericVisitor{
[](BuiltinClass _left, BuiltinClass _right) { return _left == _right; },
[](TypeClassDefinition const* _left, TypeClassDefinition const* _right) { return _left->id() == _right->id(); },
[](BuiltinClass, TypeClassDefinition const*) { return false; },
[](TypeClassDefinition const*, BuiltinClass) { return false; },
}, declaration, _rhs.declaration);
}
string TypeClass::toString() const
{
return std::visit(util::GenericVisitor{
[](BuiltinClass _class) -> string {
switch(_class)
{
case BuiltinClass::Type:
return "type";
case BuiltinClass::Kind:
return "kind";
case BuiltinClass::Constraint:
return "contraint";
}
solAssert(false);
},
[](TypeClassDefinition const* _declaration) { return _declaration->name(); },
}, declaration);
}
bool Sort::operator==(Sort const& _rhs) const
{
if (classes.size() != _rhs.classes.size())
return false;
for (auto [lhs, rhs]: ranges::zip_view(classes, _rhs.classes))
if (lhs != rhs)
return false;
return true;
}
bool Sort::operator<=(Sort const& _rhs) const
{
for (auto c: classes)
if (!_rhs.classes.count(c))
return false;
return true;
}
Sort Sort::operator+(Sort const& _rhs) const
{
Sort result { classes };
result.classes += _rhs.classes;
return result;
}
Sort Sort::operator-(Sort const& _rhs) const
{
Sort result { classes };
result.classes -= _rhs.classes;
return result;
}
bool TypeConstant::operator<(TypeConstant const& _rhs) const
{
if (constructor < _rhs.constructor)
return true;
if (_rhs.constructor < constructor)
return false;
solAssert(arguments.size() == _rhs.arguments.size());
for(auto [lhs, rhs]: ranges::zip_view(arguments, _rhs.arguments))
{
if (lhs < rhs)
return true;
if (rhs < lhs)
return false;
}
return false;
}
std::string experimental::canonicalTypeName(Type _type)
{
return std::visit(util::GenericVisitor{
[&](TypeConstant const& _type) {
std::stringstream stream;
auto printTypeArguments = [&]() {
if (!_type.arguments.empty())
{
stream << "$";
for (auto type: _type.arguments | ranges::views::drop_last(1))
stream << canonicalTypeName(type) << "$";
stream << canonicalTypeName(_type.arguments.back());
stream << "$";
}
};
std::visit(util::GenericVisitor{
[&](Declaration const* _declaration) {
printTypeArguments();
if (auto const* typeDeclarationAnnotation = dynamic_cast<TypeDeclarationAnnotation const*>(&_declaration->annotation()))
stream << *typeDeclarationAnnotation->canonicalName;
else
// TODO: canonical name
stream << _declaration->name();
},
[&](BuiltinType _builtinType) {
printTypeArguments();
switch(_builtinType)
{
case BuiltinType::Type:
stream << "type";
break;
case BuiltinType::Sort:
stream << "sort";
break;
case BuiltinType::Void:
stream << "void";
break;
case BuiltinType::Function:
stream << "fun";
break;
case BuiltinType::Unit:
stream << "unit";
break;
case BuiltinType::Pair:
stream << "pair";
break;
case BuiltinType::Word:
stream << "word";
break;
case BuiltinType::Integer:
stream << "integer";
break;
}
}
}, _type.constructor);
return stream.str();
},
[](TypeVariable const&)-> string {
solAssert(false);
},
}, _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{
@ -431,7 +279,7 @@ Sort TypeEnvironment::sort(Type _type) const
}, _type); }, _type);
} }
void TypeSystem::declareTypeConstructor(TypeConstant::Constructor _typeConstructor, std::string _name, size_t _arguments) void TypeSystem::declareTypeConstructor(TypeConstructor _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{
@ -442,7 +290,7 @@ void TypeSystem::declareTypeConstructor(TypeConstant::Constructor _typeConstruct
solAssert(newlyInserted, "Type constructor already declared."); solAssert(newlyInserted, "Type constructor already declared.");
} }
void TypeSystem::declareTypeClass(TypeConstant::Constructor _classDeclaration, std::string _name) void TypeSystem::declareTypeClass(TypeConstructor _classDeclaration, std::string _name)
{ {
bool newlyInserted = m_typeConstructors.emplace(std::make_pair(_classDeclaration, TypeConstructorInfo{ bool newlyInserted = m_typeConstructors.emplace(std::make_pair(_classDeclaration, TypeConstructorInfo{
_name, _name,
@ -453,7 +301,7 @@ void TypeSystem::declareTypeClass(TypeConstant::Constructor _classDeclaration, s
} }
experimental::Type TypeSystem::type(TypeConstant::Constructor _constructor, std::vector<Type> _arguments) const experimental::Type TypeSystem::type(TypeConstructor _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);
@ -495,7 +343,7 @@ experimental::Type TypeEnvironment::fresh(Type _type, bool _generalize)
return freshImpl(_type, _generalize, freshImpl); return freshImpl(_type, _generalize, freshImpl);
} }
void TypeSystem::instantiateClass(TypeConstant::Constructor _typeConstructor, Arity _arity) void TypeSystem::instantiateClass(TypeConstructor _typeConstructor, Arity _arity)
{ {
// TODO: proper error handling // TODO: proper error handling
auto& typeConstructorInfo = m_typeConstructors.at(_typeConstructor); auto& typeConstructorInfo = m_typeConstructors.at(_typeConstructor);
@ -517,7 +365,9 @@ experimental::Type TypeSystemHelpers::tupleType(vector<Type> _elements) const
vector<experimental::Type> TypeSystemHelpers::destTupleType(Type _tupleType) const vector<experimental::Type> TypeSystemHelpers::destTupleType(Type _tupleType) const
{ {
auto [constructor, arguments] = destTypeExpression(_tupleType); if (!isTypeConstant(_tupleType))
return {_tupleType};
auto [constructor, arguments] = destTypeConstant(_tupleType);
if (auto const* builtinType = get_if<BuiltinType>(&constructor)) if (auto const* builtinType = get_if<BuiltinType>(&constructor))
{ {
if (*builtinType == BuiltinType::Unit) if (*builtinType == BuiltinType::Unit)
@ -534,11 +384,9 @@ vector<experimental::Type> TypeSystemHelpers::destTupleType(Type _tupleType) con
Type tail = arguments.back(); Type tail = arguments.back();
while(true) while(true)
{ {
auto const* tailTypeConstant = get_if<TypeConstant>(&tail); if (!isTypeConstant(tail))
if (!tailTypeConstant)
break; break;
auto [tailConstructor, tailArguments] = destTypeConstant(tail);
auto [tailConstructor, tailArguments] = destTypeExpression(tail);
auto const* builtinType = get_if<BuiltinType>(&tailConstructor); auto const* builtinType = get_if<BuiltinType>(&tailConstructor);
if(!builtinType || *builtinType != BuiltinType::Pair) if(!builtinType || *builtinType != BuiltinType::Pair)
break; break;
@ -555,9 +403,9 @@ experimental::Type TypeSystemHelpers::functionType(experimental::Type _argType,
return typeSystem.type(BuiltinType::Function, {_argType, _resultType}); return typeSystem.type(BuiltinType::Function, {_argType, _resultType});
} }
tuple<TypeConstant::Constructor, vector<experimental::Type>> TypeSystemHelpers::destTypeExpression(Type _type) const tuple<TypeConstructor, vector<experimental::Type>> TypeSystemHelpers::destTypeConstant(Type _type) const
{ {
using ResultType = tuple<TypeConstant::Constructor, vector<Type>>; using ResultType = tuple<TypeConstructor, vector<Type>>;
return std::visit(util::GenericVisitor{ return std::visit(util::GenericVisitor{
[&](TypeConstant const& _type) -> ResultType { [&](TypeConstant const& _type) -> ResultType {
return std::make_tuple(_type.constructor, _type.arguments); return std::make_tuple(_type.constructor, _type.arguments);
@ -568,7 +416,7 @@ tuple<TypeConstant::Constructor, vector<experimental::Type>> TypeSystemHelpers::
}, _type); }, _type);
} }
bool TypeSystemHelpers::isTypeExpression(Type _type) const bool TypeSystemHelpers::isTypeConstant(Type _type) const
{ {
return std::visit(util::GenericVisitor{ return std::visit(util::GenericVisitor{
[&](TypeConstant const&) -> bool { [&](TypeConstant const&) -> bool {
@ -582,7 +430,7 @@ bool TypeSystemHelpers::isTypeExpression(Type _type) const
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] = destTypeConstant(_functionType);
auto const* builtinType = get_if<BuiltinType>(&constructor); auto const* builtinType = get_if<BuiltinType>(&constructor);
solAssert(builtinType && *builtinType == BuiltinType::Function); solAssert(builtinType && *builtinType == BuiltinType::Function);
solAssert(arguments.size() == 2); solAssert(arguments.size() == 2);
@ -591,9 +439,9 @@ tuple<experimental::Type, experimental::Type> TypeSystemHelpers::destFunctionTyp
bool TypeSystemHelpers::isFunctionType(Type _type) const bool TypeSystemHelpers::isFunctionType(Type _type) const
{ {
if (!isTypeExpression(_type)) if (!isTypeConstant(_type))
return false; return false;
auto constructor = get<0>(destTypeExpression(_type)); auto constructor = get<0>(destTypeConstant(_type));
auto const* builtinType = get_if<BuiltinType>(&constructor); auto const* builtinType = get_if<BuiltinType>(&constructor);
return builtinType && *builtinType == BuiltinType::Function; return builtinType && *builtinType == BuiltinType::Function;
} }
@ -625,18 +473,18 @@ 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] = destTypeConstant(_type);
solAssert(constructor == TypeConstant::Constructor{BuiltinType::Type}); solAssert(constructor == TypeConstructor{BuiltinType::Type});
solAssert(arguments.size() == 1); solAssert(arguments.size() == 1);
return arguments.front(); return arguments.front();
} }
bool TypeSystemHelpers::isKindType(Type _type) const bool TypeSystemHelpers::isKindType(Type _type) const
{ {
if (!isTypeExpression(_type)) if (!isTypeConstant(_type))
return false; return false;
auto constructor = get<0>(destTypeExpression(_type)); auto constructor = get<0>(destTypeConstant(_type));
return constructor == TypeConstant::Constructor{BuiltinType::Type}; return constructor == TypeConstructor{BuiltinType::Type};
} }
std::string TypeSystemHelpers::sortToString(Sort _sort) const std::string TypeSystemHelpers::sortToString(Sort _sort) const

View File

@ -17,6 +17,7 @@
// SPDX-License-Identifier: GPL-3.0 // SPDX-License-Identifier: GPL-3.0
#pragma once #pragma once
#include <libsolidity/ast/experimental/Type.h>
#include <liblangutil/Exceptions.h> #include <liblangutil/Exceptions.h>
#include <optional> #include <optional>
@ -33,105 +34,6 @@ class TypeClassDefinition;
namespace solidity::frontend::experimental namespace solidity::frontend::experimental
{ {
class TypeSystem;
class TypeEnvironment;
struct TypeConstant;
struct TypeVariable;
using Type = std::variant<TypeConstant, TypeVariable>;
std::string canonicalTypeName(Type _type);
enum class BuiltinType
{
Type,
Sort,
Void,
Function,
Unit,
Pair,
Word,
Integer
};
struct TypeConstant
{
using Constructor = std::variant<BuiltinType, Declaration const*>;
Constructor constructor;
std::vector<Type> arguments;
bool operator<(TypeConstant const& _rhs) const;
bool operator==(TypeConstant const& _rhs) const
{
// TODO
return !(*this < _rhs) && !(_rhs < *this);
}
bool operator!=(TypeConstant const& _rhs) const
{
return !operator==(_rhs);
}
};
enum class BuiltinClass
{
Type,
Kind,
Constraint
};
struct TypeClass
{
std::variant<BuiltinClass, TypeClassDefinition const*> declaration;
std::string toString() const;
bool operator<(TypeClass const& _rhs) const;
bool operator==(TypeClass const& _rhs) const;
bool operator!=(TypeClass const& _rhs) const { return !operator==(_rhs); }
};
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;
Sort operator+(Sort const& _rhs) const;
Sort operator-(Sort const& _rhs) const;
};
struct Arity
{
std::vector<Sort> argumentSorts;
TypeClass typeClass;
};
struct TypeVariable
{
size_t index() const { return m_index; }
bool generic() const { return m_generic; }
Sort const& sort() const { return m_sort; }
bool operator<(TypeVariable const& _rhs) const
{
// TODO: more robust comparison?
return m_index < _rhs.m_index;
}
bool operator==(TypeVariable const& _rhs) const
{
// TODO
return !(*this < _rhs) && !(_rhs < *this);
}
bool operator!=(TypeVariable const& _rhs) const
{
return !operator==(_rhs);
}
private:
friend class TypeSystem;
size_t m_index = 0;
Sort m_sort;
bool m_generic = false;
TypeVariable(size_t _index, Sort _sort, bool _generic):
m_index(_index), m_sort(std::move(_sort)), m_generic(_generic) {}
};
class TypeEnvironment class TypeEnvironment
{ {
public: public:
@ -171,26 +73,26 @@ public:
TypeSystem(); TypeSystem();
TypeSystem(TypeSystem const&) = delete; TypeSystem(TypeSystem const&) = delete;
TypeSystem const& operator=(TypeSystem const&) = delete; TypeSystem const& operator=(TypeSystem const&) = delete;
Type type(TypeConstant::Constructor _typeConstructor, std::vector<Type> _arguments) const; Type type(TypeConstructor _typeConstructor, std::vector<Type> _arguments) const;
std::string typeName(TypeConstant::Constructor _typeConstructor) const std::string typeName(TypeConstructor _typeConstructor) const
{ {
// TODO: proper error handling // TODO: proper error handling
return m_typeConstructors.at(_typeConstructor).name; return m_typeConstructors.at(_typeConstructor).name;
} }
void declareTypeConstructor(TypeConstant::Constructor _typeConstructor, std::string _name, size_t _arguments); void declareTypeConstructor(TypeConstructor _typeConstructor, std::string _name, size_t _arguments);
size_t constructorArguments(TypeConstant::Constructor _typeConstructor) const size_t constructorArguments(TypeConstructor _typeConstructor) const
{ {
// TODO: error handling // TODO: error handling
return m_typeConstructors.at(_typeConstructor).arguments(); return m_typeConstructors.at(_typeConstructor).arguments();
} }
TypeConstructorInfo const& constructorInfo(TypeConstant::Constructor _typeConstructor) const TypeConstructorInfo const& constructorInfo(TypeConstructor _typeConstructor) const
{ {
// TODO: error handling // TODO: error handling
return m_typeConstructors.at(_typeConstructor); return m_typeConstructors.at(_typeConstructor);
} }
void declareTypeClass(TypeConstant::Constructor _classDeclaration, std::string _name); void declareTypeClass(TypeConstructor _classDeclaration, std::string _name);
void instantiateClass(TypeConstant::Constructor _typeConstructor, Arity _arity); void instantiateClass(TypeConstructor _typeConstructor, Arity _arity);
Type freshTypeVariable(bool _generic, Sort _sort); Type freshTypeVariable(bool _generic, Sort _sort);
Type freshKindVariable(bool _generic, Sort _sort); Type freshKindVariable(bool _generic, Sort _sort);
@ -201,15 +103,15 @@ public:
Type freshVariable(bool _generic, Sort _sort); Type freshVariable(bool _generic, Sort _sort);
private: private:
size_t m_numTypeVariables = 0; size_t m_numTypeVariables = 0;
std::map<TypeConstant::Constructor, TypeConstructorInfo> m_typeConstructors; std::map<TypeConstructor, TypeConstructorInfo> m_typeConstructors;
TypeEnvironment m_globalTypeEnvironment{*this}; TypeEnvironment m_globalTypeEnvironment{*this};
}; };
struct TypeSystemHelpers struct TypeSystemHelpers
{ {
TypeSystem const& typeSystem; TypeSystem const& typeSystem;
std::tuple<TypeConstant::Constructor, std::vector<Type>> destTypeExpression(Type _type) const; std::tuple<TypeConstructor, std::vector<Type>> destTypeConstant(Type _type) const;
bool isTypeExpression(Type _type) const; bool isTypeConstant(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;

View File

@ -172,7 +172,7 @@ bool IRGeneratorForStatements::visit(FunctionCall const& _functionCall)
auto const& expressionAnnotation = m_context.analysis.annotation<TypeInference>(memberAccess->expression()); auto const& expressionAnnotation = m_context.analysis.annotation<TypeInference>(memberAccess->expression());
solAssert(expressionAnnotation.type); solAssert(expressionAnnotation.type);
auto typeConstructor = std::get<0>(TypeSystemHelpers{m_context.analysis.typeSystem()}.destTypeExpression( auto typeConstructor = std::get<0>(TypeSystemHelpers{m_context.analysis.typeSystem()}.destTypeConstant(
m_context.analysis.typeSystem().env().resolve(*expressionAnnotation.type) m_context.analysis.typeSystem().env().resolve(*expressionAnnotation.type)
)); ));
auto const* typeClass = dynamic_cast<Identifier const*>(&memberAccess->expression()); auto const* typeClass = dynamic_cast<Identifier const*>(&memberAccess->expression());