Skip to content

Commit

Permalink
Handle mutually recursive record definitions
Browse files Browse the repository at this point in the history
  • Loading branch information
tytus-metrycki committed May 12, 2020
1 parent 986d01b commit 499462e
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 9 deletions.
17 changes: 10 additions & 7 deletions src/AstTypeEnvironmentAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ namespace {
Graph<AstQualifiedName> createTypeDependencyGraph(const std::vector<AstType*>& programTypes) {
Graph<AstQualifiedName> typeDependencyGraph;
for (const auto* astType : programTypes) {
if (auto type = dynamic_cast<const AstSubsetType*>(astType)) {
if (auto type = as<AstSubsetType>(astType)) {
typeDependencyGraph.insert(type->getQualifiedName(), type->getBaseType());
} else if (dynamic_cast<const AstRecordType*>(astType) != nullptr) {
} else if (isA<AstRecordType>(astType)) {
// do nothing
} else if (auto type = dynamic_cast<const AstUnionType*>(astType)) {
} else if (auto type = as<AstUnionType>(astType)) {
for (const auto& subtype : type->getTypes()) {
typeDependencyGraph.insert(type->getQualifiedName(), subtype);
}
Expand Down Expand Up @@ -76,7 +76,7 @@ std::map<AstQualifiedName, std::set<AstQualifiedName>> analysePrimitiveTypesInUn
std::map<AstQualifiedName, std::set<AstQualifiedName>> primitiveTypesInUnions;

for (const auto& astType : programTypes) {
auto unionType = dynamic_cast<const AstUnionType*>(astType);
auto* unionType = as<AstUnionType>(astType);
if (unionType == nullptr) {
continue;
}
Expand Down Expand Up @@ -166,11 +166,12 @@ const Type* TypeEnvironmentAnalysis::createType(
}
elements.push_back(elementType);
}
return &env.createType<UnionType>(typeName, std::move(elements));
return &env.createType<UnionType>(typeName, elements);

} else if (isA<AstRecordType>(astType)) {
// Create anonymous base first.
auto& recordBase = env.createType<RecordType>(tfm::format("__%sConstant", typeName));
auto& recordType = env.createType<SubsetRecordType>(typeName, recordBase);

std::vector<const Type*> elements;
for (const auto* field : as<AstRecordType>(astType)->getFields()) {
Expand All @@ -185,9 +186,11 @@ const Type* TypeEnvironmentAnalysis::createType(
}
elements.push_back(elementType);
}
recordBase.setFields(std::move(elements));

auto& recordType = env.createType<SubsetRecordType>(typeName, recordBase);
recordBase.setFields(elements);
std::replace(elements.begin(), elements.end(), dynamic_cast<Type*>(&recordBase),
dynamic_cast<Type*>(&recordType));
recordType.setFields(std::move(elements));

return &recordType;

Expand Down
3 changes: 2 additions & 1 deletion src/AstTypeEnvironmentAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ class TypeEnvironmentAnalysis : public AstAnalysis {
std::set<AstQualifiedName> cyclicTypes;

/**
* Recursively create a type in env. (eg: Subset -> construct base and then the type itself).
* Recursively create a type in env, that is
* first create its base types and then the type itself.
*/
const Type* createType(const AstQualifiedName& typeName,
const std::map<AstQualifiedName, const AstType*>& nameToAstType);
Expand Down
5 changes: 5 additions & 0 deletions tests/semantic/extended_subtypes2/extended_subtypes2.dl
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ relY(1).
.type RecA = [a: RecA, b:Z]


// Check if mutually recursive record type definitions work
.type RecX = [y : RecY]
.type RecY = [x : RecX]


// Subtypes of unions are not allowed
.type U = number

Expand Down
2 changes: 1 addition & 1 deletion tests/semantic/extended_subtypes2/extended_subtypes2.err
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Error: Undefined base type Z in definition of type Y in file extended_subtypes2.
Error: Undefined type Z in definition of field b in file extended_subtypes2.dl at line 30
.type RecA = [a: RecA, b:Z]
-------------------------^--
Error: Subset type W can't be derived from union U in file extended_subtypes2.dl at line 36
Error: Subset type W can't be derived from union U in file extended_subtypes2.dl at line 41
.type W <: U
^------------
6 errors generated, evaluation aborted

0 comments on commit 499462e

Please sign in to comment.