42 Graph<QualifiedName> createTypeDependencyGraph(
const std::vector<ast::Type*>& programTypes) {
43 Graph<QualifiedName> typeDependencyGraph;
44 for (
const auto* astType : programTypes) {
45 if (
auto type = as<ast::SubsetType>(astType)) {
46 typeDependencyGraph.insert(
type->getQualifiedName(),
type->getBaseType());
47 }
else if (isA<ast::RecordType>(astType)) {
49 }
else if (
auto type = as<ast::UnionType>(astType)) {
50 for (
const auto& subtype :
type->getTypes()) {
51 typeDependencyGraph.insert(
type->getQualifiedName(), subtype);
53 }
else if (isA<ast::AlgebraicDataType>(astType)) {
56 fatal(
"unsupported type construct: %s",
typeid(astType).name());
59 return typeDependencyGraph;
65 std::set<QualifiedName> analyseCyclicTypes(
66 const Graph<QualifiedName>& dependencyGraph,
const std::vector<ast::Type*>& programTypes) {
67 std::set<QualifiedName> cyclicTypes;
68 for (
const auto& astType : programTypes) {
69 QualifiedName typeName = astType->getQualifiedName();
71 if (dependencyGraph.reaches(typeName, typeName)) {
72 cyclicTypes.insert(std::move(typeName));
81 std::map<QualifiedName, std::set<QualifiedName>> analysePrimitiveTypesInUnion(
82 const Graph<QualifiedName>& dependencyGraph,
const std::vector<ast::Type*>& programTypes,
83 const TypeEnvironment& env) {
84 std::map<QualifiedName, std::set<QualifiedName>> primitiveTypesInUnions;
86 for (
const auto& astType : programTypes) {
87 auto* unionType = as<ast::UnionType>(astType);
88 if (unionType ==
nullptr) {
91 QualifiedName unionName = unionType->getQualifiedName();
93 auto iteratorToUnion = primitiveTypesInUnions.find(unionName);
96 if (iteratorToUnion == primitiveTypesInUnions.end()) {
97 iteratorToUnion = primitiveTypesInUnions.insert({unionName, {}}).first;
100 auto& associatedTypes = iteratorToUnion->second;
103 for (
auto&
type : env.getPrimitiveTypes()) {
104 if (dependencyGraph.reaches(unionName,
type.getName())) {
105 associatedTypes.insert(
type.getName());
109 return primitiveTypesInUnions;
115 const Program& program = translationUnit.getProgram();
117 auto rawProgramTypes = program.getTypes();
118 Graph<QualifiedName> typeDependencyGraph{createTypeDependencyGraph(rawProgramTypes)};
120 cyclicTypes = analyseCyclicTypes(typeDependencyGraph, rawProgramTypes);
123 std::map<QualifiedName, const ast::Type*> nameToType;
126 std::vector<ast::Type*> programTypes;
127 for (
auto*
type : program.getTypes()) {
131 programTypes.push_back(
type);
132 nameToType.insert({
type->getQualifiedName(),
type});
135 for (
const auto* astType : programTypes) {
136 createType(astType->getQualifiedName(), nameToType);
142 const QualifiedName& typeName,
const std::map<QualifiedName, const ast::Type*>& nameToType) {
149 auto iterToType = nameToType.find(typeName);
150 if (iterToType == nameToType.end()) {
153 const auto& astType = iterToType->second;
155 if (isA<ast::SubsetType>(astType)) {
159 if (baseType ==
nullptr) {
165 }
else if (isA<ast::UnionType>(astType)) {
167 std::vector<const Type*> elements;
168 for (
const auto& element : as<ast::UnionType>(astType)->getTypes()) {
169 auto* elementType =
createType(element, nameToType);
170 if (elementType ==
nullptr) {
173 elements.push_back(elementType);
177 }
else if (
auto astRecordType = as<ast::RecordType>(astType)) {
181 std::vector<const Type*> elements;
182 for (
const auto* field : astRecordType->getFields()) {
183 if (field->getTypeName() == typeName) {
184 elements.push_back(&recordType);
189 auto* elementType =
createType(field->getTypeName(), nameToType);
190 if (elementType ==
nullptr) {
193 elements.push_back(elementType);
196 recordType.setFields(std::move(elements));
199 }
else if (isA<ast::AlgebraicDataType>(astType)) {
203 std::vector<AlgebraicDataType::Branch> elements;
206 for (
auto* branch : as<ast::AlgebraicDataType>(astType)->getBranches()) {
207 std::vector<const Type*> branchTypes;
209 for (
auto* attr : branch->getFields()) {
211 if (
type ==
nullptr)
return nullptr;
212 branchTypes.push_back(
type);
214 elements.push_back({branch->getConstructor(), std::move(branchTypes)});
217 adt.setBranches(std::move(elements));
221 fatal(
"unsupported type construct: %s",
typeid(*astType).name());