%%% Intersection type checking from ICFP'00 paper %%% No refinement restriction %%% No polymorphism %%% Included Top (t) %%% Author: Frank Pfenning %%% Extended: Brigitte Pientka % Types tp : type. %name tp A. % bp Tue Feb 26 20:36:02 2002 bool: tp. zero : tp. % bp Wed Feb 27 11:51:24 2002 bit : tp. nat : tp. pos : tp. => : tp -> tp -> tp. %infix right 10 =>. & : tp -> tp -> tp. %infix right 9 &. t : tp. %{ % Declarative Subtyping <= : tp -> tp -> type. %infix none 8 <=. %name <= S. %mode <= *A *B. refl : A <= A. trans : A <= B -> B <= C -> A <= C. z<=n : zero <= nat. p<=n : pos <= nat. n<=b : nat <= bit. &<=1 : A1 & A2 <= A1. &<=2 : A1 & A2 <= A2. <=& : A <= B1 -> A <= B2 -> A <= B1 & B2. <=t : A <= t. <==> : B1 <= A1 -> A2 <= B2 -> A1 => A2 <= B1 => B2. }% % Ordinary Types ord : tp -> type. %mode ord +A. ord_bo: ord bool. ord_b : ord bit. ord_n : ord nat. ord_p : ord pos. ord_z : ord zero. ord_=> : ord (A => B). % t and & are not ordinary. %terminates [] (ord _). % Extracting conjuncts conj : tp -> tp -> type. %mode conj +A -Ao. conj0 : conj Ao Ao <- ord Ao. conjl : conj (A & B) Ao <- conj A Ao. conjr : conj (A & B) Bo <- conj B Bo. %terminates A (conj A _). % Algorithmic Subtyping % Duplicated for the termination checker only! <| : tp -> tp -> type. %infix none 8 <|. |> : tp -> tp -> type. %infix none 8 |>. %mode <| +A +B. %mode |> +A +B. bo<|bo: bool <| bool. b<|b : bit <| bit. n<|n : nat <| nat. p<|p : pos <| pos. p<|n : pos <| nat. z<|z : zero <| zero. z<|n : zero <| nat. n<|b : nat <| bit. p<|b : pos <| bit. &1<|o : A1 & A2 <| Bo <- ord Bo <- A1 <| Bo. &2<|o : A1 & A2 <| Bo <- ord Bo <- A2 <| Bo. <|& : A <| B1 & B2 <- A <| B1 <- A <| B2. <|t : A <| t. =><|=> : A1 |> B1 -> A2 <| B2 -> A1 => A2 <| B1 => B2. b|>b : bit |> bit. n|>n : nat |> nat. p|>p : pos |> pos. n|>p : nat |> pos. z|>z : zero |> zero. n|>z : nat |> zero. b|>b : bit |> nat. b|>p : bit |> pos. o|>&1 : Bo |> A1 & A2 <- ord Bo <- Bo |> A1. o|>&2 : Bo |> A1 & A2 <- ord Bo <- Bo |> A2. &|> : B1 & B2 |> A <- B1 |> A <- B2 |> A. t|> : t |> A. =>|>=> : B1 <| A1 -> B2 |> A2 -> B1 => B2 |> A1 => A2. %terminates [(A A') (B B')] (|> A' B') (<| A B). % Note to Brigitte % %terminates [(A A') (B B')] (<| A B) (<| B' A'). % Terms term : type. %name term M x. % Type ascription # : term -> tp -> term. %infix none 8 #. % integers z: term. s: term -> term. casen : term -> term -> (term -> term) -> term. % Functions lam : (term -> term) -> term. app : term -> term -> term. if : term -> term -> term -> term. true: term. false: term. % Bits e : term. 0 : term -> term. %postfix 10 0. 1 : term -> term. %postfix 10 1. case : term -> term -> (term -> term) -> (term -> term) -> term. % Let and recursion let : term -> (term -> term) -> term. fix : (term -> term) -> term. % Values value : term -> type. %name value W. %mode value +M. val_lam : value (lam [x] M x). val_e : value (e). val_0 : value (M 0) <- value M. val_1 : value (M 1) <- value M. val_t: value true. val_f: value false. val_z: value z. val_s: value (s E) <- value E. %terminates M (value M). nonvalue : term -> type. %mode nonvalue +M. nv_app : nonvalue (app M N). nv_0 : nonvalue (M 0) <- nonvalue M. nv_1 : nonvalue (M 1) <- nonvalue M. nv_case : nonvalue (case M Me M0 M1). nv_casen : nonvalue (casen M Mz Ms). nv_let : nonvalue (let M N). nv_fix : nonvalue (fix M). nv_if : nonvalue (if M M1 M2). %terminates M (nonvalue M). % Typing Rules; Values %{ of : term -> tp -> type. %name of D. %mode of +M *A. of<= : of M A -> A <= B -> of M B. of& : of V A -> of V B -> value V -> of V (A & B). of_true: of true bool. of_false: of false bool. of_if : of (if M M1 M2) T <- of M bool <- of M1 T <- of M2 T. of_lam : ({x} of x A -> of (M x) B) -> of (lam [x] M x) (A => B). of_app : of M (A => B) -> of N A -> of (app M N) B. of_e : of e nat. of_ez : of e zero. of_0b : of M bit -> of (M 0) bit. of_0p : of M pos -> of (M 0) pos. of_1b : of M bit -> of (M 1) bit. of_1p : of M nat -> of (M 1) pos. of_case_b : of M bit -> of Me A -> ({x} of x bit -> of (M0 x) A) -> ({y} of y bit -> of (M1 y) A) -> of (case M Me ([x] M0 x) ([y] M1 y)) A. of_case_n : of M nat -> of Me A -> ({x} of x pos -> of (M0 x) A) -> ({y} of y nat -> of (M1 y) A) -> of (case M Me ([x] M0 x) ([y] M1 y)) A. of_case_p : of M pos -> ({x} of x pos -> of (M0 x) A) -> ({y} of y nat -> of (M1 y) A) -> of (case M Me ([x] M0 x) ([y] M1 y)) A. % bp Wed Feb 27 11:54:12 2002 of_case_z : of M zero -> of Me A -> of (case M Me ([x] M0 x) ([y] M1 y)) A. of_fix : of (fix M) A <- ({x:term} of x A -> of (M x) A). of_let : of (let M N) A <- of M B <- ({x:term} of x B -> of (N x) A). }% % Bi-Directional Type Checking synth : term -> tp -> type. %name synth S s. check : term -> tp -> type. %name check C c. %mode synth +I -A. %mode check +C +A. % there is a bug -- if -- bp Mon Feb 18 13:54:00 2002 fixed % tabled synth. %tabled check. % Coercions s_# : synth (C # A) A <- check C A. c_s : check I Ao <- ord Ao <- synth I A' <- A' <| Ao. cnv_& : check I (A & B) <- nonvalue I <- synth I A' <- A' <| A & B. cnv_t : check I t <- nonvalue I. % <- synth I A' % redundant? % <- A' <| t. % always succeeds %% Intersections c_& : check CV (A & B) <- value CV <- check CV A <- check CV B. c_t : check CV t <- value CV. % checkable CV? % Functions s_app : synth (app I C) B <- synth I A' <- conj A' (A => B) <- check C A. c_lam : check (lam [x] C x) (A => B) <- ({x:term} value x -> synth x A -> check (C x) B). c_true: check true bool. c_false: check false bool. c_if : check (if M M1 M2) A <- check M bool <- check M1 A <- check M2 A. % e : nat [& bit] c_b : check e bit. c_e : check e nat. c_z : check e zero. % bp Wed Feb 27 11:58:16 2002 % no c_p % _ 0 : bit -> bit & pos -> pos [& nat -> bit] s_0_b : check (C 0) bit <- check C bit. s_0_n : check (C 0) nat <- check C pos. s_0_p : check (C 0) pos <- check C pos. % _ 1 : bit -> bit & nat -> pos [& pos -> pos] s_1_b : check (C 1) bit <- check C bit. s_1_n : check (C 1) nat <- check C nat. s_1_p : check (C 1) pos <- check C nat. c_case_b : check (case I Ce ([x] C0 x) ([y] C1 y)) A <- synth I B' <- conj B' bit <- check Ce A <- ({x} value x -> synth x bit -> check (C0 x) A) <- ({y} value y -> synth y bit -> check (C1 y) A). c_case_n : check (case I Ce ([x] C0 x) ([y] C1 y)) A <- synth I B' <- conj B' nat <- check Ce A <- ({x} value x -> synth x pos -> check (C0 x) A) <- ({y} value y -> synth y nat -> check (C1 y) A). c_case_p : check (case I Ce ([x] C0 x) ([y] C1 y)) A <- synth I B' <- conj B' pos <- check Ce t % to be pedantic <- ({x} value x -> synth x pos -> check (C0 x) A) <- ({y} value y -> synth y nat -> check (C1 y) A). c_case_z : check (case I Ce ([x] C0 x) ([y] C1 y)) A <- synth I B' <- conj B' zero <- check Ce A. % Definitions c_let : check (let I C) A <- synth I B <- ({x:term} value x -> synth x B -> check (C x) A). % Recursion c_fix : check (fix C) A <- ({x:term} nonvalue x -> synth x A -> check (C x) A). % Note to Carsten: cannot termination check this!! % %terminates {(I C) A} (synth I _) (check C A). % %terminates {(I C) (A' A)} (synth I A') (check C A). % Need to comment out offending clause and use spec below % %terminates (I C) (synth I A') (check C A).