Repository: microsoft/knossos-ksc

Issue:
Python doesn't handle types in structured names properly
For example, it breaks on https://github.com/microsoft/knossos-ksc/commit/36cf7d45796839b033f60828f81fb41731b39a2b. Perhaps it is expecting the applied type to be the argument type of the derived function (it should be expecting it to be the argument type of the base function).

This is blocking SUF/BOG-AD https://github.com/microsoft/knossos-ksc/pull/565/

```
============================================================= FAILURES =============================================================
______________________________________________ test_type_propagate_prelude_and_primer ______________________________________________

    def test_type_propagate_prelude_and_primer():
        symtab = dict()
        decls_prelude = list(parse_ks_filename("src/runtime/prelude.ks"))
>       type_propagate_decls(decls_prelude, symtab)

test/python/test_type_propagation.py:11:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
src/python/ksc/type_propagate.py:348: in type_propagate_decls
    type_propagate(decl, symtab)
/usr/lib/python3.8/functools.py:875: in wrapper
    return dispatch(args[0].__class__)(*args, **kw)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

ex = <ksc.expr.Def object at 0x7f1e18747e50>
symtab = {StructuredName(('not', Type.Bool)): Type.Bool, StructuredName(('fwd', StructuredName(('not', Type.Bool)))): None, StructuredName(('rev', StructuredName(('not', Type.Bool)))): None, StructuredName(('neg', Type.Float)): Type.Float, ...}

    @type_propagate.register(Def)
    def _(ex, symtab):
        # (def name return_type args body)
        declared_return_type = ex.return_type != None

        # Name to look up is function "signature": name and argtypes
        argtypes = tuple(a.type_ for a in ex.args)
        argtype = make_tuple_if_many(argtypes)
        old_ty, sname = ex.name.add_type(argtype)

        if old_ty is not None and old_ty != argtype:
>           raise KSTypeError(f"In definition of '{ex.name}', explicit type in structured name\n" +
                                f"does not match argument types {argtype}")
E           ksc.type_propagate.KSTypeError: In definition of '[fwd [neg Float]]', explicit type in structured name
E           does not match argument types (Tuple Float Float)

src/python/ksc/type_propagate.py:180: KSTypeError
____________________________________________________ test_type_propagate_works _____________________________________________________

    def test_type_propagate_works():
        decls = list(parse_ks_string("""
        (def foo Float (a : Float) 1.0)
        """, __file__))
        type_propagate_decls(decls, {})
        assert decls[0].return_type == Type.Float

        symtab = dict()
        decls_prelude = list(parse_ks_filename("src/runtime/prelude.ks"))
>       type_propagate_decls(decls_prelude, symtab)

test/python/test_type_propagation.py:25:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
src/python/ksc/type_propagate.py:348: in type_propagate_decls
    type_propagate(decl, symtab)
/usr/lib/python3.8/functools.py:875: in wrapper
    return dispatch(args[0].__class__)(*args, **kw)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

ex = <ksc.expr.Def object at 0x7f1e186be370>
symtab = {StructuredName(('not', Type.Bool)): Type.Bool, StructuredName(('fwd', StructuredName(('not', Type.Bool)))): None, StructuredName(('rev', StructuredName(('not', Type.Bool)))): None, StructuredName(('neg', Type.Float)): Type.Float, ...}

    @type_propagate.register(Def)
    def _(ex, symtab):
        # (def name return_type args body)
        declared_return_type = ex.return_type != None

        # Name to look up is function "signature": name and argtypes
        argtypes = tuple(a.type_ for a in ex.args)
        argtype = make_tuple_if_many(argtypes)
        old_ty, sname = ex.name.add_type(argtype)

        if old_ty is not None and old_ty != argtype:
>           raise KSTypeError(f"In definition of '{ex.name}', explicit type in structured name\n" +
                                f"does not match argument types {argtype}")
E           ksc.type_propagate.KSTypeError: In definition of '[fwd [neg Float]]', explicit type in structured name
E           does not match argument types (Tuple Float Float)

src/python/ksc/type_propagate.py:180: KSTypeError
```
Python doesn't handle types in structured names properly
For example, it breaks on https://github.com/microsoft/knossos-ksc/commit/36cf7d45796839b033f60828f81fb41731b39a2b. Perhaps it is expecting the applied type to be the argument type of the derived function (it should be expecting it to be the argument type of the base function).

This is blocking SUF/BOG-AD https://github.com/microsoft/knossos-ksc/pull/565/

```
============================================================= FAILURES =============================================================
______________________________________________ test_type_propagate_prelude_and_primer ______________________________________________

    def test_type_propagate_prelude_and_primer():
        symtab = dict()
        decls_prelude = list(parse_ks_filename("src/runtime/prelude.ks"))
>       type_propagate_decls(decls_prelude, symtab)

test/python/test_type_propagation.py:11:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
src/python/ksc/type_propagate.py:348: in type_propagate_decls
    type_propagate(decl, symtab)
/usr/lib/python3.8/functools.py:875: in wrapper
    return dispatch(args[0].__class__)(*args, **kw)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

ex = <ksc.expr.Def object at 0x7f1e18747e50>
symtab = {StructuredName(('not', Type.Bool)): Type.Bool, StructuredName(('fwd', StructuredName(('not', Type.Bool)))): None, StructuredName(('rev', StructuredName(('not', Type.Bool)))): None, StructuredName(('neg', Type.Float)): Type.Float, ...}

    @type_propagate.register(Def)
    def _(ex, symtab):
        # (def name return_type args body)
        declared_return_type = ex.return_type != None

        # Name to look up is function "signature": name and argtypes
        argtypes = tuple(a.type_ for a in ex.args)
        argtype = make_tuple_if_many(argtypes)
        old_ty, sname = ex.name.add_type(argtype)

        if old_ty is not None and old_ty != argtype:
>           raise KSTypeError(f"In definition of '{ex.name}', explicit type in structured name\n" +
                                f"does not match argument types {argtype}")
E           ksc.type_propagate.KSTypeError: In definition of '[fwd [neg Float]]', explicit type in structured name
E           does not match argument types (Tuple Float Float)

src/python/ksc/type_propagate.py:180: KSTypeError
____________________________________________________ test_type_propagate_works _____________________________________________________

    def test_type_propagate_works():
        decls = list(parse_ks_string("""
        (def foo Float (a : Float) 1.0)
        """, __file__))
        type_propagate_decls(decls, {})
        assert decls[0].return_type == Type.Float

        symtab = dict()
        decls_prelude = list(parse_ks_filename("src/runtime/prelude.ks"))
>       type_propagate_decls(decls_prelude, symtab)

test/python/test_type_propagation.py:25:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
src/python/ksc/type_propagate.py:348: in type_propagate_decls
    type_propagate(decl, symtab)
/usr/lib/python3.8/functools.py:875: in wrapper
    return dispatch(args[0].__class__)(*args, **kw)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

ex = <ksc.expr.Def object at 0x7f1e186be370>
symtab = {StructuredName(('not', Type.Bool)): Type.Bool, StructuredName(('fwd', StructuredName(('not', Type.Bool)))): None, StructuredName(('rev', StructuredName(('not', Type.Bool)))): None, StructuredName(('neg', Type.Float)): Type.Float, ...}

    @type_propagate.register(Def)
    def _(ex, symtab):
        # (def name return_type args body)
        declared_return_type = ex.return_type != None

        # Name to look up is function "signature": name and argtypes
        argtypes = tuple(a.type_ for a in ex.args)
        argtype = make_tuple_if_many(argtypes)
        old_ty, sname = ex.name.add_type(argtype)

        if old_ty is not None and old_ty != argtype:
>           raise KSTypeError(f"In definition of '{ex.name}', explicit type in structured name\n" +
                                f"does not match argument types {argtype}")
E           ksc.type_propagate.KSTypeError: In definition of '[fwd [neg Float]]', explicit type in structured name
E           does not match argument types (Tuple Float Float)

src/python/ksc/type_propagate.py:180: KSTypeError
```


Discussion:
Sorry, I thought I'd fixed that.
Fix coming.
Sorry, I thought I'd fixed that.
Fix coming.

Resolving patch:
diff --git a/src/python/ksc/type_propagate.py b/src/python/ksc/type_propagate.py
--- a/src/python/ksc/type_propagate.py
+++ b/src/python/ksc/type_propagate.py
@@ -176,7 +176,7 @@ def _(ex, symtab):
     argtype = make_tuple_if_many(argtypes)
     old_ty, sname = ex.name.add_type(argtype)
 
-    if old_ty is not None and old_ty != argtype:
+    if old_ty is not None and old_ty != argtype and not sname.is_derivation():
         raise KSTypeError(f"In definition of '{ex.name}', explicit type in structured name\n" +
                             f"does not match argument types {argtype}")
 


Test patch: