Skip to content

Commit

Permalink
Merge 1bd2df1 into 5f9c908
Browse files Browse the repository at this point in the history
  • Loading branch information
mlin committed May 12, 2019
2 parents 5f9c908 + 1bd2df1 commit 3ebad7e
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 18 deletions.
27 changes: 15 additions & 12 deletions WDL/Tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -1463,30 +1463,33 @@ def _resolve_struct_typedef(


def _resolve_struct_typedefs(
pos: Err.SourcePosition, ty: T.Base, struct_typedefs: Env.StructTypeDefs
pos: Err.SourcePosition,
ty: T.Base,
struct_typedefs: Env.StructTypeDefs,
members_dict_ids: Optional[List[int]] = None,
):
members_dict_ids = members_dict_ids or []
# resolve all StructInstance within a potentially compound type
if isinstance(ty, T.StructInstance):
_resolve_struct_typedef(pos, ty, struct_typedefs)
if id(ty.members) in members_dict_ids:
# circular struct types!
raise StopIteration
members_dict_ids = [id(ty.members)] + (members_dict_ids or [])
for p in ty.parameters:
_resolve_struct_typedefs(pos, p, struct_typedefs)
_resolve_struct_typedefs(pos, p, struct_typedefs, members_dict_ids=members_dict_ids)


def _initialize_struct_typedefs(struct_typedefs: Env.StructTypeDefs):
# bootstrap struct typechecking: resolve all StructInstance members of the
# struct types
# struct types; also detect & error circular struct definitions
for b in struct_typedefs:
assert isinstance(b, Env.Binding)
for member_ty in b.rhs.members.values():
if isinstance(member_ty, T.StructInstance):
_resolve_struct_typedef(b.rhs.pos, member_ty, struct_typedefs)
# make a dummy allusion to each StructTypeDef.type_id, which will detect any
# circular definitions (see Type._struct_type_id)
for b in struct_typedefs:
try:
b.rhs.type_id
except StopIteration:
raise Err.CircularDependencies(b.rhs)
try:
_resolve_struct_typedefs(b.rhs.pos, member_ty, struct_typedefs)
except StopIteration:
raise Err.CircularDependencies(b.rhs)


def _add_struct_instance_to_type_env(
Expand Down
8 changes: 2 additions & 6 deletions WDL/Type.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,18 +387,14 @@ def parameters(self) -> Iterable[Base]:
return self.members.values()


def _struct_type_id(members: Dict[str, Base], members_dict_ids: Optional[List[int]] = None) -> str:
def _struct_type_id(members: Dict[str, Base]) -> str:
# generates a content hash of the struct type definition, used to recognize
# equivalent struct types going by different aliases
members_dict_ids = members_dict_ids or []
if id(members) in members_dict_ids: # circular struct definitions!
raise StopIteration
members_dict_ids = [id(members)] + members_dict_ids
ans = []
for (name, ty) in sorted(members.items()):
if isinstance(ty, StructInstance):
assert ty.members
ty = _struct_type_id(ty.members, members_dict_ids) + ("?" if ty.optional else "")
ty = _struct_type_id(ty.members) + ("?" if ty.optional else "")
else:
ty = str(ty)
ans.append(name + " : " + ty)
Expand Down
60 changes: 60 additions & 0 deletions tests/test_1doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -1724,6 +1724,66 @@ def test_decl(self):
with self.assertRaises(WDL.Error.InvalidType):
WDL.parse_document(doc)

# Test struct members with compound types including other structs
# (issue #127)
doc = r"""
version 1.0
workflow UsePerson {
Person p
}
struct Person {
String name
Array[Pair[Car,Int]] cars
}
struct Car {
String make
String model
}
"""
doc = WDL.parse_document(doc)
doc.typecheck()

doc = r"""
version 1.0
workflow UsePerson {
Person p
}
struct Person {
String name
Array[Person] circular
}
"""
doc = WDL.parse_document(doc)
with self.assertRaises(WDL.Error.CircularDependencies):
doc.typecheck()

doc = r"""
version 1.0
workflow UsePerson {
Person p
}
struct Person {
String name
Array[Car] cars
}
struct Car {
String make
String model
Person owner
}
"""
doc = WDL.parse_document(doc)
with self.assertRaises(WDL.Error.CircularDependencies):
doc.typecheck()

def test_import(self):
doc = r"""
version 1.0
Expand Down

0 comments on commit 3ebad7e

Please sign in to comment.