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))
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))
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))
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))
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))
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))