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