Repository: delph-in/pydelphin

Issue:
format function for TypeDefinition seems to mess up some of the Lists
If I `iterparse` this TypeDefinition

```
main-vprn := basic-main-verb & norm-pronominal-verb &
  [ SYNSEM.LOCAL.CAT.VAL [ SUBJ < #subj >, 
                           COMPS < #comps >,
                           CLTS #clt ],
    ARG-ST < #subj . < #comps . #clt > > ].
```

and then print it back out using the `format` function, I get this:

```
main-vprn := basic-main-verb & norm-pronominal-verb &
  [ SYNSEM.LOCAL.CAT.VAL [ SUBJ < #subj >,
                           COMPS < #comps >,
                           CLTS #clt ],
    ARG-ST < #subj, #comps . < #comps . #clt > > ].     <----- Note the extra `,#comps`which used to not be there before

```

Discussion:

Patch:
diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml
index 2a5298f..0ef3a60 100644
--- a/.github/workflows/checks.yml
+++ b/.github/workflows/checks.yml
@@ -37,4 +37,4 @@ jobs:
         pytest .
     - name: Type-check with mypy
       run: |
-        mypy delphin --namespace-packages --explicit-package-bases --ignore-missing-imports
+        mypy delphin --namespace-packages --explicit-package-bases --ignore-missing-imports --implicit-optional
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e7ef17a..b11f97b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,14 @@
 # Change Log
 
+## Unreleased
+
+### Fixed
+
+* `delphin.tdl.ConsList.values()` and `delphin.tdl.DiffList.values()`
+  now treat explicit sublists as regular items instead of descending
+  into their structures ([#357])
+
+
 ## [v1.7.0]
 
 **Release date: 2022-10-13**
@@ -1556,3 +1565,4 @@ information about changes, except for
 [#343]: https://github.com/delph-in/pydelphin/issues/343
 [#344]: https://github.com/delph-in/pydelphin/issues/344
 [#352]: https://github.com/delph-in/pydelphin/issues/352
+[#357]: https://github.com/delph-in/pydelphin/issues/357
diff --git a/delphin/cli/convert.py b/delphin/cli/convert.py
index 5d50e28..4dadf80 100644
--- a/delphin/cli/convert.py
+++ b/delphin/cli/convert.py
@@ -9,9 +9,7 @@ with "-lines" to enable line-based reading/writing, in which case the
 
 import sys
 import argparse
-import warnings
 
-from delphin.exceptions import PyDelphinWarning
 from delphin.commands import convert
 from delphin import util
 
diff --git a/delphin/cli/repp.py b/delphin/cli/repp.py
index f47571c..ed0cdb8 100644
--- a/delphin/cli/repp.py
+++ b/delphin/cli/repp.py
@@ -11,9 +11,7 @@ useful for debugging REPP modules.
 
 import sys
 import argparse
-import warnings
 
-from delphin.exceptions import PyDelphinWarning
 from delphin.commands import repp
 
 
diff --git a/delphin/tdl.py b/delphin/tdl.py
index aa7a18a..ec330f4 100644
--- a/delphin/tdl.py
+++ b/delphin/tdl.py
@@ -253,6 +253,10 @@ class AVM(FeatureStructure, Term):
         return fs
 
 
+class _ImplicitAVM(AVM):
+    """AVM implicitly constructed by list syntax."""
+
+
 class ConsList(AVM):
     """
     AVM subclass for cons-lists (``< ... >``)
@@ -308,12 +312,7 @@ class ConsList(AVM):
         if self._avm is None:
             return []
         else:
-            vals = [val for _, val in _collect_list_items(self)]
-            # the < a . b > notation puts b on the last REST path,
-            # which is not returned by _collect_list_items()
-            if self.terminated and self[self._last_path] is not None:
-                vals.append(self[self._last_path])
-            return vals
+            return [val for _, val in _collect_list_items(self)]
 
     def append(self, value):
         """
@@ -330,7 +329,7 @@ class ConsList(AVM):
                 path += '.'
             self[path + LIST_HEAD] = value
             self._last_path = path + LIST_TAIL
-            self[self._last_path] = AVM()
+            self[self._last_path] = _ImplicitAVM()
         else:
             raise TDLError('Cannot append to a closed list.')
 
@@ -395,7 +394,7 @@ class DiffList(AVM):
         if values:
             # use ConsList to construct the list, but discard the class
             tmplist = ConsList(values, end=cr)
-            dl_list = AVM()
+            dl_list = _ImplicitAVM()
             dl_list._avm.update(tmplist._avm)
             dl_list._feats = tmplist._feats
             self.last = 'LIST.' + tmplist._last_path
@@ -416,16 +415,25 @@ class DiffList(AVM):
         """
         Return the list of values in the DiffList feature structure.
         """
-        return [val for _, val
-                in _collect_list_items(self.get(DIFF_LIST_LIST))]
+        if isinstance(self[DIFF_LIST_LIST], Coreference):
+            vals = []
+        else:
+            vals = [val for _, val
+                    in _collect_list_items(self.get(DIFF_LIST_LIST))]
+            vals.pop()  # last item of diff list is coreference
+        return vals
 
 
 def _collect_list_items(d):
-    if d is None or not isinstance(d, AVM) or d.get(LIST_HEAD) is None:
+    if not isinstance(d, AVM) or d.get(LIST_HEAD) is None:
         return []
     vals = [(LIST_HEAD, d[LIST_HEAD])]
-    vals.extend((LIST_TAIL + '.' + path, val)
-                for path, val in _collect_list_items(d.get(LIST_TAIL)))
+    rest = d[LIST_TAIL]
+    if isinstance(rest, _ImplicitAVM):
+        vals.extend((LIST_TAIL + '.' + path, val)
+                    for path, val in _collect_list_items(rest))
+    elif rest is not None:
+        vals.append((LIST_TAIL, rest))
     return vals
 
 


Test patch:
diff --git a/tests/tdl_test.py b/tests/tdl_test.py
index b4b88d2..5cae05c 100644
--- a/tests/tdl_test.py
+++ b/tests/tdl_test.py
@@ -960,3 +960,18 @@ def test_format_environments():
         '  :end :instance.\n'
         '  :include "another.tdl".\n'
         ':end :type.')
+
+
+def test_issue_357():
+    # https://github.com/delph-in/pydelphin/issues/357
+    t = TypeDefinition(
+        'id',
+        ConsList(
+            [TypeIdentifier('a')],
+            end=ConsList([TypeIdentifier('b')], end=TypeIdentifier('c'))
+        )
+    )
+    c = t.conjunction.terms[0]
+    assert isinstance(c, ConsList)
+    assert len(c.values()) == 2
+    assert tdl.format(t) == 'id := < a . < b . c > >.'