예제 #1
0
    def f(t):
        if isinstance(t, Nom):
            return
        if isinstance(t, Var):
            ref = t.ref
            if isinstance(ref, Link):
                return f(ref.ty)
            if isinstance(ref, (Unbound, Bound)):
                return
            if isinstance(ref, Gen):
                free_var_set.add(ty)
                return
            raise TypeError(type(ref))
        if isinstance(t, App):
            f(t.f)
            f(t.arg)
            return
        if isinstance(t, Arrow):
            f(t.arg)
            f(t.ret)
            return
        if isinstance(t, Forall):
            f(t.ty)
            return

        raise TypeError(type(ty))
예제 #2
0
 def f(t):
     if isinstance(t, Var):
         ref = t.ref
         if isinstance(ref, Link):
             return f(ref.ty)
         if isinstance(ref, (Gen, Bound)):
             return
         if isinstance(ref, Unbound):
             if ref.id is tvar_id:
                 error("recursive types")
             elif ref.level > tvar_level:
                 t.ref = Unbound(ref.id, tvar_level)
             return
         raise TypeError(type(ref))
     if isinstance(t, App):
         f(t.f)
         f(t.arg)
         return
     if isinstance(t, Arrow):
         f(t.arg)
         f(t.ret)
         return
     if isinstance(t, Forall):
         f(t.ty)
         return
     if isinstance(t, Nom):
         return
     raise TypeError(type(t))
예제 #3
0
 def f(t: Ty):
     if isinstance(t, Var):
         ref = t.ref
         if isinstance(ref, Link):
             f(ref.ty)
             return
         if isinstance(ref, Gen):
             error("impossible")
         if isinstance(ref, Bound):
             return
         if isinstance(ref, Unbound):
             if ref.level > level:
                 other_id = ref.id
                 t.ref = Bound(other_id)
                 if other_id not in var_id_lst:
                     var_id_lst.append(other_id)
             return
         raise TypeError(type(t))
     if isinstance(t, App):
         f(t.f)
         f(t.arg)
         return
     if isinstance(t, Arrow):
         f(t.arg)
         f(t.ret)
         return
     if isinstance(t, Forall):
         f(t.ty)
         return
     if isinstance(t, Nom):
         return
     raise TypeError(type(t))
예제 #4
0
def infer(env: Env, level: int, term: Expr):
    if isinstance(term, EVar):
        try:
            return env.type_of_name(term.v)
        except KeyError:
            error("variable {} undefined".format(term.v))
    if isinstance(term, EFun):
        fn_env = env.new_scope()
        var_lst = []
        pn, ann = term.param
        if ann:
            var_lst_sec, arg_ty = inst_ty_ann(level + 1, *ann)
            var_lst.extend(var_lst_sec)
        else:
            arg_ty = Var(Unbound(object(), level + 1))
            var_lst.append(arg_ty)
        fn_env.enter(pn, arg_ty)
        inferred_ret_ty = infer(fn_env, level + 1, term.body)
        if is_annotated(term.body):
            ret_ty = inferred_ret_ty
        else:
            ret_ty = inst(level + 1, inferred_ret_ty)

        if not all(map(is_mono, var_lst)):
            error("polymorphc parameter inferred: {}".format(''.join(map(ppt, var_lst))))
        ret_ty = generalise(level, Arrow(arg_ty, ret_ty))
        return ret_ty

    if isinstance(term, ELet):
        var_name = term.id
        bound = term.bound
        body = term.body
        var_ty = infer(env, level + 1, bound)
        new_env = env.new_scope()
        new_env.enter(var_name, var_ty)
        return infer(new_env, level, body)

    if isinstance(term, EApp):
        fn_expr = term.f
        arg = term.arg
        fn_ty = inst(level + 1, infer(env, level + 1, fn_expr))
        param_ty, ret_ty = match_fun_ty(fn_ty)
        infer_arg(env, level + 1, param_ty, arg)
        ret_ty = generalise(level, inst(level + 1, ret_ty))
        return ret_ty

    if isinstance(term, EAnn):
        _, ty = inst_ty_ann(level, *term.ann)
        expr_ty = infer(env, level, term.expr)
        subsume(level, ty, expr_ty)
        return ty
    if isinstance(term, EOmit):
        ty = Var(Unbound(object(), level))
        return ty
    if isinstance(term, EInt):
        return Nom("int")
    raise TypeError(type(term))
예제 #5
0
def ppt_io(t: Ty, io: StringIO, miss: MissingDict):
    if isinstance(t, Forall):
        s1 = ' '.join(map(lambda x: miss[x], t.bounds))
        io.write('forall ')
        io.write(s1)
        io.write('. ')
        ppt_io(t.ty, io, miss)
        return
    if isinstance(t, Nom):
        io.write(t.name)
        return
    if isinstance(t, Var):
        ref = t.ref
        if isinstance(ref, Bound):
            return io.write(miss[ref.id])
        if isinstance(ref, Unbound):
            io.write('^')
            return io.write(miss[ref.id])
        if isinstance(ref, Link):
            return ppt_io(ref.ty, io, miss)
        if isinstance(ref, Gen):
            io.write('gen<')
            return io.write(miss[ref.id])
        raise TypeError(type(ref))
    if isinstance(t, App):
        io.write('(')
        ppt_io(t.f, io, miss)
        io.write(' ')
        ppt_io(t.arg, io, miss)
        io.write(')')
        return
    if isinstance(t, Arrow):
        io.write('(')
        ppt_io(t.arg, io, miss)
        io.write(' -> ')
        ppt_io(t.ret, io, miss)
        io.write(')')
        return
    raise TypeError(type(t))
예제 #6
0
 def f(id_ty_map: Dict[object, Ty], t):
     if isinstance(t, Nom):
         return t
     if isinstance(t, Var):
         ref = t.ref
         if isinstance(ref, Link):
             return f(id_ty_map, ref.ty)
         if isinstance(ref, Bound):
             return id_ty_map.get(ref.id) or t
         return t
     if isinstance(t, App):
         return App(f(id_ty_map, t.f), f(id_ty_map, t.arg))
     if isinstance(t, Arrow):
         return Arrow(f(id_ty_map, t.arg), f(id_ty_map, t.ret))
     if isinstance(t, Forall):
         bounds = t.bounds
         return Forall(bounds, f({k: v for k, v in id_ty_map.items() if k not in bounds}, t.ty))
     raise TypeError(type(t))