major overhaul of WeakToStrong/StrongToWeak; it can now handle the whole tutorial
authorAdam Megacz <megacz@cs.berkeley.edu>
Wed, 16 Mar 2011 08:54:16 +0000 (01:54 -0700)
committerAdam Megacz <megacz@cs.berkeley.edu>
Wed, 16 Mar 2011 08:54:56 +0000 (01:54 -0700)
src/Extraction-prefix.hs
src/Extraction.v
src/HaskStrongToWeak.v
src/HaskWeakToStrong.v

index b144116..3dec80f 100644 (file)
@@ -1,11 +1,14 @@
 {-# OPTIONS_GHC -fno-warn-unused-binds  #-}
 module CoqPass ( coqPassCoreToString, coqPassCoreToCore )
 where
 {-# OPTIONS_GHC -fno-warn-unused-binds  #-}
 module CoqPass ( coqPassCoreToString, coqPassCoreToCore )
 where
+import qualified Unique
+import qualified UniqSupply
 import qualified MkCore
 import qualified TysWiredIn
 import qualified TysPrim
 import qualified Outputable
 import qualified PrelNames
 import qualified MkCore
 import qualified TysWiredIn
 import qualified TysPrim
 import qualified Outputable
 import qualified PrelNames
+import qualified OccName
 import qualified Name
 import qualified Literal
 import qualified Type
 import qualified Name
 import qualified Literal
 import qualified Type
@@ -82,6 +85,11 @@ sanitizeForLatex ('$':x) = "\\$"++(sanitizeForLatex x)
 sanitizeForLatex ('#':x) = "\\#"++(sanitizeForLatex x)
 sanitizeForLatex (c:x)   = c:(sanitizeForLatex x)
 
 sanitizeForLatex ('#':x) = "\\#"++(sanitizeForLatex x)
 sanitizeForLatex (c:x)   = c:(sanitizeForLatex x)
 
+kindToCoreKind :: Kind -> TypeRep.Kind
+kindToCoreKind KindStar          = TypeRep.liftedTypeKind
+kindToCoreKind (KindArrow k1 k2) = Coercion.mkArrowKind (kindToCoreKind k1) (kindToCoreKind k2)
+kindToCoreKind _                 = Prelude.error "kindToCoreKind does not know how to handle that"
+
 coreKindToKind :: TypeRep.Kind -> Kind
 coreKindToKind k =
   case Coercion.splitKindFunTy_maybe k of
 coreKindToKind :: TypeRep.Kind -> Kind
 coreKindToKind k =
   case Coercion.splitKindFunTy_maybe k of
index 53b1185..66a69da 100644 (file)
@@ -25,7 +25,7 @@ Require Import HaskProof.
 Require Import HaskCoreToWeak.
 Require Import HaskWeakToStrong.
 Require Import HaskStrongToProof.
 Require Import HaskCoreToWeak.
 Require Import HaskWeakToStrong.
 Require Import HaskStrongToProof.
-Require Import HaskProofToStrong.
+(*Require Import HaskProofToStrong.*)
 Require Import HaskProofToLatex.
 Require Import HaskStrongToWeak.
 Require Import HaskWeakToCore.
 Require Import HaskProofToLatex.
 Require Import HaskStrongToWeak.
 Require Import HaskWeakToCore.
@@ -58,6 +58,17 @@ Extract Constant shift  => "shiftAscii".
 Unset Extraction Optimize.
 Unset Extraction AutoInline.
 
 Unset Extraction Optimize.
 Unset Extraction AutoInline.
 
+
+Variable Name : Type.  Extract Inlined Constant Name => "Name.Name".
+Variable mkSystemName : Unique -> string -> nat -> Name.
+  Extract Inlined Constant mkSystemName => "(\u s d -> Name.mkSystemName u (OccName.mkOccName (OccName.varNameDepth (nat2int d)) s))".
+Variable mkTyVar : Name -> Kind -> CoreVar.
+  Extract Inlined Constant mkTyVar => "(\n k -> Var.mkTyVar n (kindToCoreKind k))".
+Variable mkCoVar : Name -> CoreType -> CoreType -> CoreVar.
+  Extract Inlined Constant mkCoVar => "(\n t1 t2 -> Var.mkCoVar n (Coercion.mkCoKind t1 t2))".
+Variable mkExVar : Name -> CoreType -> CoreVar.
+  Extract Inlined Constant mkExVar => "Id.mkLocalId".
+
 Section core2proof.
   Context (ce:@CoreExpr CoreVar).
 
 Section core2proof.
   Context (ce:@CoreExpr CoreVar).
 
@@ -84,6 +95,9 @@ Section core2proof.
       | WCoerVar _   => Prelude_error "top-level xi got a coercion variable"
     end.
 
       | WCoerVar _   => Prelude_error "top-level xi got a coercion variable"
     end.
 
+
+  (* core-to-string (-dcoqpass) *)
+
   Definition header : string :=
     "\documentclass[9pt]{article}"+++eol+++
     "\usepackage{amsmath}"+++eol+++
   Definition header : string :=
     "\documentclass[9pt]{article}"+++eol+++
     "\usepackage{amsmath}"+++eol+++
@@ -102,7 +116,7 @@ Section core2proof.
     eol+++"\end{document}"+++
     eol.
 
     eol+++"\end{document}"+++
     eol.
 
-  Definition handleExpr' (ce:@CoreExpr CoreVar) : ???string :=
+  Definition coreToStringExpr' (ce:@CoreExpr CoreVar) : ???string :=
     addErrorMessage ("input CoreSyn: " +++ ce)
     (addErrorMessage ("input CoreType: " +++ coreTypeOfCoreExpr ce) (
       coreExprToWeakExpr ce >>= fun we =>
     addErrorMessage ("input CoreSyn: " +++ ce)
     (addErrorMessage ("input CoreType: " +++ coreTypeOfCoreExpr ce) (
       coreExprToWeakExpr ce >>= fun we =>
@@ -112,29 +126,90 @@ Section core2proof.
               (addErrorMessage ("WeakType: " +++ t)
                 ((weakTypeToTypeOfKind φ t ★) >>= fun τ =>
                   addErrorMessage ("HaskType: " +++ τ)
               (addErrorMessage ("WeakType: " +++ t)
                 ((weakTypeToTypeOfKind φ t ★) >>= fun τ =>
                   addErrorMessage ("HaskType: " +++ τ)
-                  ((weakExprToStrongExpr Γ Δ φ ψ ξ τ nil we) >>= fun e =>
+                  ((weakExprToStrongExpr Γ Δ φ ψ ξ (fun _ => true) τ nil we) >>= fun e =>
                     OK (eol+++"$$"+++ nd_ml_toLatex (@expr2proof _ _ _ _ _ _ e)+++"$$"+++eol)
                   )))))))).
 
                     OK (eol+++"$$"+++ nd_ml_toLatex (@expr2proof _ _ _ _ _ _ e)+++"$$"+++eol)
                   )))))))).
 
-  Definition handleExpr (ce:@CoreExpr CoreVar) : string :=
-    match handleExpr' ce with
+  Definition coreToStringExpr (ce:@CoreExpr CoreVar) : string :=
+    match coreToStringExpr' ce with
       | OK x => x
       | Error s => Prelude_error s
     end.
 
       | OK x => x
       | Error s => Prelude_error s
     end.
 
-  Definition handleBind (bind:@CoreBind CoreVar) : string :=
-    match bind with
-      | CoreNonRec _ e => handleExpr e
-      | CoreRec    lbe => fold_left (fun x y => x+++eol+++eol+++y) (map (fun x => handleExpr (snd x)) lbe) ""
+  Definition coreToStringBind (binds:@CoreBind CoreVar) : string :=
+    match binds with
+      | CoreNonRec _ e => coreToStringExpr e
+      | CoreRec    lbe => fold_left (fun x y => x+++eol+++eol+++y) (map (fun x => coreToStringExpr (snd x)) lbe) ""
     end.
 
   Definition coqPassCoreToString (lbinds:list (@CoreBind CoreVar)) : string :=
     header +++
     end.
 
   Definition coqPassCoreToString (lbinds:list (@CoreBind CoreVar)) : string :=
     header +++
-    (fold_left (fun x y => x+++eol+++eol+++y) (map handleBind lbinds) "")
+    (fold_left (fun x y => x+++eol+++eol+++y) (map coreToStringBind lbinds) "")
     +++ footer.
 
     +++ footer.
 
-  Definition coqPassCoreToCore (lbinds:list (@CoreBind CoreVar)) : list (@CoreBind CoreVar) :=
-    lbinds.
+
+  (* core-to-core (-fcoqpass) *)
+  Section CoreToCore.
+
+    Definition mkWeakTypeVar (u:Unique)(k:Kind)                 : WeakTypeVar :=
+      weakTypeVar (mkTyVar (mkSystemName u "tv" O) k) k.
+    Definition mkWeakCoerVar (u:Unique)(k:Kind)(t1 t2:WeakType) : WeakCoerVar :=
+      weakCoerVar (mkCoVar (mkSystemName u "cv" O) (weakTypeToCoreType t1) (weakTypeToCoreType t2)) k t1 t2.
+    Definition mkWeakExprVar (u:Unique)(t:WeakType)             : WeakExprVar :=
+      weakExprVar (mkExVar (mkSystemName u "ev" O) (weakTypeToCoreType t)) t.
+
+    Context (hetmet_brak  : WeakExprVar).
+    Context (hetmet_esc   : WeakExprVar).
+    Context (uniqueSupply : UniqSupply).
+
+    Definition coreToCoreExpr' (ce:@CoreExpr CoreVar) : ???(@CoreExpr CoreVar) :=
+      addErrorMessage ("input CoreSyn: " +++ ce)
+      (addErrorMessage ("input CoreType: " +++ coreTypeOfCoreExpr ce) (
+        coreExprToWeakExpr ce >>= fun we =>
+          addErrorMessage ("WeakExpr: " +++ we)
+            ((addErrorMessage ("CoreType of WeakExpr: " +++ coreTypeOfCoreExpr (weakExprToCoreExpr we))
+              ((weakTypeOfWeakExpr we) >>= fun t =>
+                (addErrorMessage ("WeakType: " +++ t)
+                  ((weakTypeToTypeOfKind φ t ★) >>= fun τ =>
+
+                    ((weakExprToStrongExpr Γ Δ φ ψ ξ (fun _ => true) τ nil we) >>= fun e =>
+                      (* insert HaskStrong-to-HaskStrong manipulations here *)
+                      strongExprToWeakExpr hetmet_brak hetmet_esc mkWeakTypeVar mkWeakCoerVar mkWeakExprVar uniqueSupply e INil
+                      >>= fun q => OK (weakExprToCoreExpr q)
+(*
+                    OK (weakExprToCoreExpr we)
+*)
+                    )))))))).
+
+    Definition coreToCoreExpr (ce:@CoreExpr CoreVar) : (@CoreExpr CoreVar) :=
+      match coreToCoreExpr' ce with
+        | OK x    => x
+        | Error s => Prelude_error s
+      end.
+  
+    Definition coreToCoreBind (binds:@CoreBind CoreVar) : @CoreBind CoreVar :=
+      match binds with
+        | CoreNonRec v e => CoreNonRec v (coreToCoreExpr e)
+        | CoreRec    lbe => CoreRec (map (fun ve => match ve with (v,e) => (v,coreToCoreExpr e) end) lbe)
+      end.
+  
+    Definition coqPassCoreToCore' (lbinds:list (@CoreBind CoreVar)) : list (@CoreBind CoreVar) :=
+      map coreToCoreBind lbinds.
+
+  End CoreToCore.
+
+  Definition coqPassCoreToCore
+    (hetmet_brak  : CoreVar)
+    (hetmet_esc   : CoreVar)
+    (uniqueSupply : UniqSupply)
+    (lbinds:list (@CoreBind CoreVar)) : list (@CoreBind CoreVar) :=
+    match coreVarToWeakVar hetmet_brak with
+      | WExprVar hetmet_brak' => match coreVarToWeakVar hetmet_esc with
+                                   | WExprVar hetmet_esc' => coqPassCoreToCore' hetmet_brak' hetmet_esc' uniqueSupply lbinds
+                                   | _ => Prelude_error "IMPOSSIBLE"
+                                 end
+      | _ => Prelude_error "IMPOSSIBLE"
+    end.
 
 End core2proof.
 
 
 End core2proof.
 
index b4b0caa..e86e544 100644 (file)
@@ -14,136 +14,234 @@ Require Import HaskLiteralsAndTyCons.
 Require Import HaskWeakTypes.
 Require Import HaskWeakVars.
 Require Import HaskWeak.
 Require Import HaskWeakTypes.
 Require Import HaskWeakVars.
 Require Import HaskWeak.
+Require Import HaskWeakToCore.
 Require Import HaskStrongTypes.
 Require Import HaskStrong.
 Require Import HaskStrongTypes.
 Require Import HaskStrong.
-Require Import HaskCoreVars.
-
-Fixpoint mfresh (f:Fresh Kind (fun _ => WeakTypeVar))(lk:list Kind){Γ}(ite:IList _ (fun _ => WeakTypeVar) Γ)
-  : (Fresh Kind (fun _ => WeakTypeVar)) * ((vec WeakTypeVar (length lk)) * (IList _ (fun _ => WeakTypeVar) (app lk Γ))) :=
-  match lk as LK return (Fresh Kind (fun _ => WeakTypeVar)) * ((vec WeakTypeVar (length LK)) *
-                          (IList _ (fun _ => WeakTypeVar) (app LK Γ))) with
-  | nil    => (f,(vec_nil,ite))
-  | k::lk' =>
-    let (f',varsite') := mfresh f lk' ite
-    in  let (vars,ite') := varsite'
-    in  let (v,f'') := next _ _ f' k
-    in (f'',((v:::vars),v::::ite'))
-  end.
 
 
-Fixpoint rawHaskTypeToWeakType (f:Fresh Kind (fun _ => WeakTypeVar)){κ}(rht:RawHaskType (fun _ => WeakTypeVar) κ)
- {struct rht} : WeakType :=
-match rht with
-  | TVar  _  v                 => WTyVarTy v
-  | TCon      tc              => WTyCon tc
-  | TCoerc _ t1 t2 t3          => WCoFunTy (rawHaskTypeToWeakType f t1) (rawHaskTypeToWeakType f t2) (rawHaskTypeToWeakType f t3)
-  | TArrow                    => WFunTyCon
-  | TApp  _ _  t1 t2             => WAppTy (rawHaskTypeToWeakType f t1) (rawHaskTypeToWeakType f t2)
-  | TAll    k rht'            => let (tv,f') := next _ _ f k in WForAllTy tv (rawHaskTypeToWeakType f' (rht' tv))
-  | TCode   t1 t2             => 
-    match (rawHaskTypeToWeakType f t1) with
-      | WTyVarTy ec => WCodeTy ec (rawHaskTypeToWeakType f t2)
-      | impossible  => impossible  (* TODO: find a way to convince Coq this can't happen *)
-    end
-  | TyFunApp    tfc tls         => WTyFunApp tfc (rawHaskTypeListToWeakType f tls)
-end
-with rawHaskTypeListToWeakType (f:Fresh Kind (fun _ => WeakTypeVar)){κ}(rht:RawHaskTypeList κ) :=
-match rht with
-  | TyFunApp_nil   => nil
-  | TyFunApp_cons  κ kl rht' rhtl' => (rawHaskTypeToWeakType f rht')::(rawHaskTypeListToWeakType f rhtl')
-end.
-
-Definition typeToWeakType (f:Fresh Kind (fun _ => WeakTypeVar))
-  {Γ}{κ}(τ:HaskType Γ κ)(φ:InstantiatedTypeEnv (fun _ => WeakTypeVar) Γ) : WeakType :=
-  rawHaskTypeToWeakType f (τ _ φ).
-
-(* This can be used to turn HaskStrong's with arbitrary expression variables into HaskStrong's which use WeakExprVar's
- * for their variables; those can subsequently be passed to the following function (strongExprToWeakExpr) *)
-(*
-Definition reindexStrongExpr {VV}{HH}{eqVV:EqDecidable VV}{eqHH:EqDecidable HH}
-  {Γ}{Δ}{ξ}{lev}(exp:@Expr VV eqVV Γ Δ ξ lev) : { ξ' : HH -> LeveledHaskType Γ & @Expr HH eqHH Γ Δ ξ' lev }.
-  Defined.
-  *)
-
-Definition updateITE {Γ:TypeEnv}{TV:Kind->Type}{κ}(tv:TV κ)(ite:InstantiatedTypeEnv TV Γ) : InstantiatedTypeEnv TV (κ::Γ)
-  := tv::::ite.
-
-Definition coercionToWeakCoercion Γ Δ κ t1 t2 ftv ite (γ:@HaskCoercion Γ Δ (@mkHaskCoercionKind Γ κ t1 t2)) : WeakCoercion :=
-  WCoUnsafe (@typeToWeakType ftv Γ κ t1 ite) (@typeToWeakType ftv Γ κ t2 ite).
-
-Section strongExprToWeakExpr.
+(* Uniques *)
+Variable UniqSupply      : Type.                   Extract Inlined Constant UniqSupply     => "UniqSupply.UniqSupply".
+Variable Unique          : Type.                   Extract Inlined Constant Unique         => "Unique.Unique".
+Variable uniqFromSupply  : UniqSupply -> Unique.   Extract Inlined Constant uniqFromSupply => "UniqSupply.uniqFromSupply".
+Variable splitUniqSupply : UniqSupply -> UniqSupply * UniqSupply.
+    Extract Inlined Constant splitUniqSupply => "UniqSupply.splitUniqSupply".
+
+Inductive UniqM {T:Type} : Type :=
+ | uniqM    : (UniqSupply -> ???(UniqSupply * T)) -> UniqM.
+ Implicit Arguments UniqM [ ].
+
+Instance UniqMonad : Monad UniqM :=
+{ returnM := fun T (x:T) => uniqM (fun u => OK (u,x))
+; bindM   := fun a b (x:UniqM a) (f:a->UniqM b) =>
+  uniqM (fun u =>
+    match x with
+      | uniqM fa =>
+        match fa u with
+          | Error s   => Error s
+          | OK (u',va) => match f va with
+                           | uniqM fb => fb u'
+                         end
+        end
+    end)
+}.
+
+Definition getU : UniqM Unique :=
+  uniqM (fun us => let (us1,us2) := splitUniqSupply us in OK (us1,(uniqFromSupply us2))).
+
+Notation "'bind' x = e ; f" := (@bindM _ _ _ _ e (fun x => f)) (x ident, at level 60, right associativity).
+Notation "'return' x" := (returnM x) (at level 100).
+Notation "'failM'  x" := (uniqM (fun _ => Error x)) (at level 100).
+
+Section HaskStrongToWeak.
 
   Context (hetmet_brak : WeakExprVar).
   Context (hetmet_esc  : WeakExprVar).
 
 
   Context (hetmet_brak : WeakExprVar).
   Context (hetmet_esc  : WeakExprVar).
 
-  Fixpoint strongExprToWeakExpr {Γ}{Δ}{ξ}{τ}
-    (ftv:Fresh Kind                (fun _ => WeakTypeVar))
-    (fcv:Fresh (WeakType*WeakType) (fun _ => WeakCoerVar))
-    (fev:Fresh WeakType            (fun _ => WeakExprVar))
-    (exp:@Expr _ CoreVarEqDecidable Γ Δ ξ τ)
-    : InstantiatedTypeEnv (fun _ => WeakTypeVar) Γ -> WeakExpr :=
-  match exp as E in @Expr _ _ G D X L return InstantiatedTypeEnv (fun _ => WeakTypeVar) G -> WeakExpr with
-  | EVar  Γ' _ ξ' ev              => fun ite => WEVar (weakExprVar ev (@typeToWeakType ftv Γ' ★  (unlev (ξ' ev)) ite))
-  | ELit  _ _ _ lit _             => fun ite => WELit lit
-  | EApp  Γ' _ _ _ _ _ e1 e2      => fun ite => WEApp (strongExprToWeakExpr ftv fcv fev e1 ite) (strongExprToWeakExpr ftv fcv fev e2 ite)
-  | ELam  Γ'   _ _ _ t _ cv e     => fun ite => WELam (weakExprVar cv (typeToWeakType ftv t ite)) (strongExprToWeakExpr ftv fcv fev e ite)
-  | ELet  Γ' _ _ t _ _ ev e1 e2   => fun ite => WELet (weakExprVar ev (typeToWeakType ftv t ite)) (strongExprToWeakExpr ftv fcv fev e1 ite) (strongExprToWeakExpr ftv fcv fev e2 ite)
-  | EEsc  Γ' _ _ ec t _ e         => fun ite => WEEsc  hetmet_esc (ec _ ite) (strongExprToWeakExpr ftv fcv fev e ite) (typeToWeakType ftv t ite)
-  | EBrak Γ' _ _ ec t _ e         => fun ite => WEBrak hetmet_brak (ec _ ite) (strongExprToWeakExpr ftv fcv fev e ite) (typeToWeakType ftv t ite)
-  | ENote _ _ _ _ n e             => fun ite => WENote n (strongExprToWeakExpr ftv fcv fev e ite)
-  | ETyApp  Γ Δ κ σ τ ξ l       e => fun ite => WETyApp (strongExprToWeakExpr ftv fcv fev e ite) (typeToWeakType ftv τ ite)
-  | ELetRec _ _ _ _ _ vars elrb e => fun ite => WELetRec (exprLetRec2WeakExprLetRec ftv fcv fev elrb ite)(strongExprToWeakExpr ftv fcv fev e ite)
-  | ECast Γ Δ ξ t1 t2 γ l e      => fun ite => WECast  (strongExprToWeakExpr ftv fcv fev e ite)
-                                                 (coercionToWeakCoercion _ _ _ _ _ ftv ite γ)
-  | ECoApp Γ Δ κ σ₁ σ₂ γ σ ξ l e => fun ite => WECoApp (strongExprToWeakExpr ftv fcv fev e ite)
-                                                 (coercionToWeakCoercion _ _ _ _ _ ftv ite γ)
-  | ECase Γ Δ ξ l tc tbranches atypes e alts => fun ite =>
-    let (ev,fev') := next _ _ fev (typeToWeakType ftv (unlev (caseType tc atypes @@ l)) ite) in
-     WECase
-      ev
-      (strongExprToWeakExpr ftv fcv fev' e ite)
-      (@typeToWeakType ftv Γ _ tbranches ite)
-      tc
-      (ilist_to_list (@ilmap _ _ (fun _ => WeakType) _ (fun _ t => typeToWeakType ftv t ite) atypes))
-      ((fix caseBranches
-        (tree:Tree ??{ scb : StrongCaseBranchWithVVs _ _ tc atypes
-                              & Expr (sac_Γ scb Γ)
-                                     (sac_Δ scb Γ atypes (weakCK'' Δ))
-                                     (update_ξ (weakLT'○ξ) (vec2list (vec_map
-                                       (fun x => ((fst x),(snd x @@ weakL' l))) (scbwv_varstypes scb))))
-                                     (weakLT' (tbranches@@l)) })
-        : Tree ??(WeakAltCon * list WeakTypeVar * list WeakCoerVar * list WeakExprVar * WeakExpr) :=
-        match tree with
-          | T_Leaf None     => []
-          | T_Leaf (Some x) => let (scb,e) := x in
-            let (ftv',evarsite') := mfresh ftv _ ite in
-            let fcv' :=  fcv in
-              let (evars,ite') := evarsite' in
-              [(sac_altcon scb,
-                vec2list evars,
-                nil (*FIXME*),
-                map (fun vt => weakExprVar (fst vt) (typeToWeakType ftv' (snd vt) ite')) (vec2list (scbwv_varstypes scb)),
-                strongExprToWeakExpr ftv' fcv' fev' e ite'
-              )]
-          | T_Branch b1 b2  => (caseBranches b1),,(caseBranches b2)
-        end
-      ) alts)
-  | ETyLam _ _ _ k _ _ e          => fun ite =>
-    let (tv,ftv') := next _ _ ftv k in WETyLam tv (strongExprToWeakExpr ftv' fcv fev e (updateITE tv ite))
-  | ECoLam Γ Δ κ σ σ₁ σ₂ ξ l e => fun ite =>
-    let t1' := typeToWeakType ftv σ₁ ite in 
-    let t2' := typeToWeakType ftv σ₂ ite in
-    let (cv,fcv') := next _ _ fcv (t1',t2') in WECoLam cv (strongExprToWeakExpr ftv fcv' fev e ite)
+  Context (mkWeakTypeVar_ : Unique -> Kind                         -> WeakTypeVar).
+  Context (mkWeakCoerVar_ : Unique -> Kind -> WeakType -> WeakType -> WeakCoerVar).
+  Context (mkWeakExprVar_ : Unique ->         WeakType             -> WeakExprVar).
+
+  Definition mkWeakTypeVar (k:Kind)                 : UniqM WeakTypeVar := bind u = getU ; return mkWeakTypeVar_ u k.
+  Definition mkWeakCoerVar (k:Kind)(t1 t2:WeakType) : UniqM WeakCoerVar := bind u = getU ; return mkWeakCoerVar_ u k t1 t2.
+  Definition mkWeakExprVar (t:WeakType)             : UniqM WeakExprVar := bind u = getU ; return mkWeakExprVar_ u t.
+
+  Fixpoint mfresh (lk:list Kind){Γ}(ite:IList _ (fun _ => WeakTypeVar) Γ)
+    : UniqM (((vec WeakTypeVar (length lk)) * (IList _ (fun _ => WeakTypeVar) (app lk Γ)))) :=
+    match lk as LK return UniqM ((vec WeakTypeVar (length LK)) * (IList _ (fun _ => WeakTypeVar) (app LK Γ))) with
+    | nil    => return (vec_nil,ite)
+    | k::lk' => bind v = mkWeakTypeVar k
+              ; bind vars_ite' = mfresh lk' ite
+              ; return ((v:::(fst vars_ite')),v::::(snd vars_ite'))
+    end.
+
+  Fixpoint rawHaskTypeToWeakType {κ}(rht:RawHaskType (fun _ => WeakTypeVar) κ) {struct rht} : UniqM WeakType :=
+  match rht with
+    | TVar  _  v                => return WTyVarTy v
+    | TCon      tc              => return WTyCon tc
+    | TCoerc _ t1 t2 t3         => bind t1' = rawHaskTypeToWeakType t1
+                                 ; bind t2' = rawHaskTypeToWeakType t2
+                                 ; bind t3' = rawHaskTypeToWeakType t3
+                                 ; return WCoFunTy t1' t2' t3'
+    | TArrow                    => return WFunTyCon
+    | TApp  _ _  t1 t2          => bind t1' = rawHaskTypeToWeakType t1
+                                 ; bind t2' = rawHaskTypeToWeakType t2
+                                 ; return WAppTy t1' t2'
+    | TAll    k rht'            => bind tv = mkWeakTypeVar k
+                                 ; bind t' = rawHaskTypeToWeakType (rht' tv)
+                                 ; return WForAllTy tv t'
+    | TCode   t1 t2             => bind t1' = rawHaskTypeToWeakType t1
+                                 ; bind t2' = rawHaskTypeToWeakType t2
+                                 ; match t1' with
+                                     | WTyVarTy ec => return WCodeTy ec t2'
+                                     | _           => failM  "impossible"
+                                   end
+    | TyFunApp    tfc tls       => bind tls' = rawHaskTypeListToWeakType tls
+                                 ; return WTyFunApp tfc tls'
   end
   end
-  with exprLetRec2WeakExprLetRec {Γ}{Δ}{ξ}{τ}{vars}
-    (ftv:Fresh Kind                (fun _ => WeakTypeVar))
-    (fcv:Fresh (WeakType*WeakType) (fun _ => WeakCoerVar))
-    (fev:Fresh WeakType            (fun _ => WeakExprVar))
-    (elrb:@ELetRecBindings _ CoreVarEqDecidable Γ Δ ξ τ vars)
-    : InstantiatedTypeEnv (fun _ => WeakTypeVar) Γ -> Tree ??(WeakExprVar * WeakExpr) :=
-  match elrb as E in ELetRecBindings G D X L V
-     return InstantiatedTypeEnv (fun _ => WeakTypeVar) G -> Tree ??(WeakExprVar * WeakExpr) with
-  | ELR_nil    _ _ _ _           => fun ite => []
-  | ELR_leaf   _ _ ξ' cv v e    => fun ite => [((weakExprVar v (typeToWeakType ftv (unlev (ξ' v)) ite)),(strongExprToWeakExpr ftv fcv fev e ite))]
-  | ELR_branch _ _ _ _ _ _ b1 b2 => fun ite => (exprLetRec2WeakExprLetRec ftv fcv fev b1 ite),, (exprLetRec2WeakExprLetRec ftv fcv fev b2 ite)
+  with rawHaskTypeListToWeakType {κ}(rht:RawHaskTypeList κ) : UniqM (list WeakType) :=
+  match rht with
+    | TyFunApp_nil                   => return nil
+    | TyFunApp_cons  κ kl rht' rhtl' => bind t  = rawHaskTypeToWeakType rht'
+                                      ; bind tl = rawHaskTypeListToWeakType rhtl'
+                                      ; return t::tl
+  end.
+  
+  Definition typeToWeakType {Γ}{κ}(τ:HaskType Γ κ)(φ:InstantiatedTypeEnv (fun _ => WeakTypeVar) Γ) : UniqM WeakType :=
+    rawHaskTypeToWeakType (τ _ φ).
+  
+  Definition updateITE {Γ:TypeEnv}{TV:Kind->Type}{κ}(tv:TV κ)(ite:InstantiatedTypeEnv TV Γ) : InstantiatedTypeEnv TV (κ::Γ)
+    := tv::::ite.
+  
+  Definition coercionToWeakCoercion Γ Δ κ t1 t2 ite (γ:@HaskCoercion Γ Δ (@mkHaskCoercionKind Γ κ t1 t2))
+    : UniqM WeakCoercion
+    := bind t1' = @typeToWeakType Γ κ t1 ite
+     ; bind t2' = @typeToWeakType Γ κ t2 ite
+     ; return WCoUnsafe t1' t2'.
+  
+  Fixpoint seqM {a}(l:list (UniqM a)) : UniqM (list a) :=
+    match l with
+      | nil  => return nil
+      | x::y => bind x' = x
+              ; bind y' = seqM y
+              ; return x'::y'
+    end.
+  
+  Context {VV}{eqVV:EqDecidable VV}{toStringVV:ToString VV}.
+  
+  Definition update_χ (χ:VV->???WeakExprVar)(vv:VV)(ev':WeakExprVar) : VV->???WeakExprVar :=
+    fun vv' =>
+      if eqd_dec vv vv'
+      then OK ev'
+      else χ vv'.
+
+  Fixpoint update_χ' (χ:VV->???WeakExprVar)(varsexprs:list (VV * WeakExprVar)) : VV->???WeakExprVar :=
+    match varsexprs with
+      | nil => χ
+      | (vv,wev)::rest => update_χ (update_χ' χ rest) vv wev
+    end.
+
+  Fixpoint exprToWeakExpr {Γ}{Δ}{ξ}{τ}(χ:VV->???WeakExprVar)(exp:@Expr _ eqVV Γ Δ ξ τ)
+    : InstantiatedTypeEnv (fun _ => WeakTypeVar) Γ
+    -> UniqM WeakExpr :=
+    match exp as E in @Expr _ _ G D X L return InstantiatedTypeEnv (fun _ => WeakTypeVar) G -> UniqM WeakExpr with
+    | EVar  Γ' _ ξ' ev              => fun ite => match χ ev with OK v => return WEVar v | Error s => failM s end
+    | EGlobal Γ' _ ξ' t wev         => fun ite => return WEVar wev
+    | ELam  Γ'   _ _ tv _ _ cv e    => fun ite => bind tv' = typeToWeakType tv ite
+                                                ; bind ev' = mkWeakExprVar tv'
+                                                ; bind e'  = exprToWeakExpr (update_χ χ cv ev') e ite
+                                                ; return WELam ev' e'
+    | ELet  Γ' _ _ t _ _ ev e1 e2   => fun ite => bind tv' = typeToWeakType t ite
+                                                ; bind e1' = exprToWeakExpr χ e1 ite
+                                                ; bind ev' = mkWeakExprVar tv'
+                                                ; bind e2' = exprToWeakExpr (update_χ χ ev ev') e2 ite
+                                                ; return WELet ev' e1' e2'
+    | ELit  _ _ _ lit _             => fun ite => return WELit lit
+    | EApp  Γ' _ _ _ _ _ e1 e2      => fun ite => bind e1' = exprToWeakExpr χ e1 ite
+                                                ; bind e2' = exprToWeakExpr χ e2 ite
+                                                ; return WEApp e1' e2'
+    | EEsc  Γ' _ _ ec t _ e         => fun ite => bind t' = typeToWeakType t ite
+                                                ; bind e' = exprToWeakExpr χ e ite
+                                                ; return WEEsc hetmet_esc (ec _ ite) e' t'
+    | EBrak Γ' _ _ ec t _ e         => fun ite => bind t' = typeToWeakType t ite
+                                                ; bind e' = exprToWeakExpr χ e ite
+                                                ; return WEBrak hetmet_brak (ec _ ite) e' t'
+    | ENote _ _ _ _ n e             => fun ite => bind e' = exprToWeakExpr χ e ite
+                                                ; return WENote n e'
+    | ETyApp  Γ Δ κ σ τ ξ l       e => fun ite => bind t' = typeToWeakType τ ite
+                                                ; bind e' = exprToWeakExpr χ e ite
+                                                ; return WETyApp e' t'
+    | ECoApp Γ Δ κ σ₁ σ₂ γ σ ξ l e  => fun ite => bind e' = exprToWeakExpr χ e ite
+                                                ; bind c' = coercionToWeakCoercion _ _ _ _ _ ite γ
+                                                ; return WECoApp e' c'
+    | ECast Γ Δ ξ t1 t2 γ l e      => fun ite  => bind e' = exprToWeakExpr χ e ite
+                                                ; bind c' = coercionToWeakCoercion _ _ _ _ _ ite γ
+                                                ; return WECast e' c'
+    | ETyLam _ _ _ k _ _ e          => fun ite => bind tv = mkWeakTypeVar k
+                                                ; bind e' = exprToWeakExpr χ e (updateITE tv ite)
+                                                ; return WETyLam tv e'
+    | ECoLam Γ Δ κ σ σ₁ σ₂ ξ l e    => fun ite => bind t1' = typeToWeakType σ₁ ite
+                                                ; bind t2' = typeToWeakType σ₂ ite
+                                                ; bind cv  = mkWeakCoerVar κ t1' t2'
+                                                ; bind e'  = exprToWeakExpr χ e ite
+                                                ; return WECoLam cv e'
+    | ECase Γ Δ ξ l tc tbranches atypes escrut alts => 
+         fun ite => bind tscrut'    = typeToWeakType (caseType tc atypes) ite
+                  ; bind vscrut'    = mkWeakExprVar tscrut'
+                  ; bind tbranches' = @typeToWeakType Γ _ tbranches ite
+                  ; bind escrut'    = exprToWeakExpr χ escrut ite
+                  ; bind branches'  =
+                      ((fix caseBranches (tree:Tree ??{scb : StrongCaseBranchWithVVs VV _ _ _ & Expr _ _ _ _  })
+                            : UniqM (Tree ??(WeakAltCon*list WeakTypeVar*list WeakCoerVar*list WeakExprVar*WeakExpr)) :=
+                            match tree with
+                              | T_Leaf None           => return []
+                              | T_Leaf (Some x)       => let (scb,e) := x in
+                                let varstypes := vec2list (scbwv_varstypes scb) in
+                                      bind evars_ite = mfresh _ ite
+                                    ; bind exprvars  = seqM (map (fun vt:VV * HaskType _ ★
+                                                                        => bind tleaf = typeToWeakType (snd vt) (snd evars_ite)
+                                                                         ; bind v' = mkWeakExprVar tleaf
+                                                                         ; return ((fst vt),v'))
+                                                                varstypes)
+                                    ; let χ' := update_χ' χ exprvars in
+                                      bind e'' = exprToWeakExpr χ' e (snd evars_ite)
+                                    ; return [(sac_altcon scb, vec2list (fst evars_ite), nil, (map (@snd _ _) exprvars), e'')]
+                              | T_Branch b1 b2        => bind b1' = caseBranches b1
+                                                       ; bind b2' = caseBranches b2
+                                                       ; return (b1',,b2')
+                            end) alts)
+                  ; bind tys = seqM (ilist_to_list (@ilmap _ _
+                                  (fun _ => UniqM WeakType) _ (fun _ t => typeToWeakType t ite) atypes))
+                  ; return WECase vscrut' escrut' tbranches' tc tys branches'
+
+    | ELetRec _ _ _ _ _ vars elrb e => fun ite => bind vars' = seqM (map (fun vt:VV * HaskType _ ★
+                                                                        => bind tleaf = typeToWeakType (snd vt) ite
+                                                                         ; bind v' = mkWeakExprVar tleaf
+                                                                         ; return ((fst vt),v'))
+                                                                (leaves vars))
+                                                ; let χ' := update_χ' χ vars' in
+                                                  bind elrb' = exprLetRec2WeakExprLetRec χ' elrb ite
+                                                ; bind e'    = exprToWeakExpr χ' e ite
+                                                ; return WELetRec elrb' e'
+    end
+    with exprLetRec2WeakExprLetRec  {Γ}{Δ}{ξ}{τ}(χ:VV->???WeakExprVar){vars}(elrb:@ELetRecBindings _ eqVV Γ Δ ξ τ vars)
+      : InstantiatedTypeEnv (fun _ => WeakTypeVar) Γ -> UniqM (Tree ??(WeakExprVar * WeakExpr)) :=
+    match elrb as E in ELetRecBindings G D X L V
+       return InstantiatedTypeEnv (fun _ => WeakTypeVar) G -> UniqM (Tree ??(WeakExprVar * WeakExpr)) with
+    | ELR_nil    _ _ _ _           => fun ite => return []
+    | ELR_leaf   _ _ ξ' cv v e     => fun ite => bind t'  = typeToWeakType (unlev (ξ' v)) ite
+                                               ; bind e'  = exprToWeakExpr χ e ite
+                                               ; bind v'  = match χ v with Error s => failM s | OK y => return y end
+                                               ; return [(v',e')]
+    | ELR_branch _ _ _ _ _ _ b1 b2 => fun ite => bind b1' = exprLetRec2WeakExprLetRec χ b1 ite
+                                               ; bind b2' = exprLetRec2WeakExprLetRec χ b2 ite
+                                               ; return b1',,b2'
   end.
   end.
-End strongExprToWeakExpr.
+
+
+  Fixpoint strongExprToWeakExpr (us:UniqSupply){Γ}{Δ}{ξ}{τ}(exp:@Expr _ eqVV Γ Δ ξ τ)
+    (ite:InstantiatedTypeEnv (fun _ => WeakTypeVar) Γ)
+    : ???WeakExpr :=
+    match exprToWeakExpr (fun v => Error ("unbound variable " +++ v)) exp ite with
+      uniqM f => f us >>= fun x => OK (snd x)
+      end.
+
+End HaskStrongToWeak.
\ No newline at end of file
index 2593a5c..38a4304 100644 (file)
@@ -19,6 +19,9 @@ Require Import HaskStrongTypes.
 Require Import HaskStrong.
 Require Import HaskCoreVars.
 
 Require Import HaskStrong.
 Require Import HaskCoreVars.
 
+(* can remove *)
+Require Import HaskStrongToWeak.
+
 Open Scope string_scope.
 Definition TyVarResolver Γ   := forall wt:WeakTypeVar, ???(HaskTyVar Γ wt).
 Definition CoVarResolver Γ Δ := forall wt:WeakCoerVar, ???(HaskCoVar Γ Δ).
 Open Scope string_scope.
 Definition TyVarResolver Γ   := forall wt:WeakTypeVar, ???(HaskTyVar Γ wt).
 Definition CoVarResolver Γ Δ := forall wt:WeakCoerVar, ???(HaskCoVar Γ Δ).
@@ -454,12 +457,23 @@ match lk as LK return ???(IList Kind (HaskType Γ) LK) with
               end
 end.
 
               end
 end.
 
+Fixpoint update_ig (ig:CoreVar -> bool) (vars:list CoreVar) : CoreVar -> bool :=
+  match vars with
+    | nil => ig
+    | v::vars' =>
+      fun v' =>
+        if eqd_dec v v'
+          then false
+            else update_ig ig vars' v'
+  end.
+
 Definition weakExprToStrongExpr : forall
     (Γ:TypeEnv)
     (Δ:CoercionEnv Γ)
     (φ:TyVarResolver Γ)
     (ψ:CoVarResolver Γ Δ)
     (ξ:CoreVar -> LeveledHaskType Γ ★)
 Definition weakExprToStrongExpr : forall
     (Γ:TypeEnv)
     (Δ:CoercionEnv Γ)
     (φ:TyVarResolver Γ)
     (ψ:CoVarResolver Γ Δ)
     (ξ:CoreVar -> LeveledHaskType Γ ★)
+    (ig:CoreVar -> bool)
     (τ:HaskType Γ ★)
     (lev:HaskLevel Γ),
     WeakExpr -> ???(@Expr _ CoreVarEqDecidable Γ Δ ξ (τ @@ lev) ).
     (τ:HaskType Γ ★)
     (lev:HaskLevel Γ),
     WeakExpr -> ???(@Expr _ CoreVarEqDecidable Γ Δ ξ (τ @@ lev) ).
@@ -470,13 +484,16 @@ Definition weakExprToStrongExpr : forall
     (φ:TyVarResolver Γ)
     (ψ:CoVarResolver Γ Δ)
     (ξ:CoreVar -> LeveledHaskType Γ ★)
     (φ:TyVarResolver Γ)
     (ψ:CoVarResolver Γ Δ)
     (ξ:CoreVar -> LeveledHaskType Γ ★)
+    (ig:CoreVar -> bool)
     (τ:HaskType Γ ★)
     (lev:HaskLevel Γ)
     (we:WeakExpr) : ???(@Expr _ CoreVarEqDecidable Γ Δ ξ (τ @@ lev) )  :=
     addErrorMessage ("in weakExprToStrongExpr " +++ we)
     match we with
 
     (τ:HaskType Γ ★)
     (lev:HaskLevel Γ)
     (we:WeakExpr) : ???(@Expr _ CoreVarEqDecidable Γ Δ ξ (τ @@ lev) )  :=
     addErrorMessage ("in weakExprToStrongExpr " +++ we)
     match we with
 
-    | WEVar   v                         => castExpr we ("WEVar "+++(v:CoreVar)) (τ @@ lev) (EVar Γ Δ ξ v)
+    | WEVar   v                         => if ig v
+                                              then OK (EGlobal Γ Δ ξ (τ@@lev) v)
+                                              else castExpr we ("WEVar "+++(v:CoreVar)) (τ @@ lev) (EVar Γ Δ ξ v)
 
     | WELit   lit                       => castExpr we ("WELit "+++lit) (τ @@ lev) (ELit Γ Δ ξ lit lev)
 
 
     | WELit   lit                       => castExpr we ("WELit "+++lit) (τ @@ lev) (ELit Γ Δ ξ lit lev)
 
@@ -484,53 +501,53 @@ Definition weakExprToStrongExpr : forall
                                              weakTypeOfWeakExpr ebody >>= fun tbody =>
                                                weakTypeToTypeOfKind φ tbody ★ >>= fun tbody' =>
                                                  let ξ' := update_ξ ξ (((ev:CoreVar),tv@@lev)::nil) in
                                              weakTypeOfWeakExpr ebody >>= fun tbody =>
                                                weakTypeToTypeOfKind φ tbody ★ >>= fun tbody' =>
                                                  let ξ' := update_ξ ξ (((ev:CoreVar),tv@@lev)::nil) in
-                                                   weakExprToStrongExpr Γ Δ φ ψ ξ' tbody' lev ebody >>= fun ebody' =>
+                                                 let ig' := update_ig ig ((ev:CoreVar)::nil) in
+                                                   weakExprToStrongExpr Γ Δ φ ψ ξ' ig' tbody' lev ebody >>= fun ebody' =>
                                                      castExpr we "WELam" (τ@@lev) (ELam Γ Δ ξ tv tbody' lev ev ebody')
 
     | WEBrak  _ ec e tbody              => φ (`ec) >>= fun ec' =>
                                              weakTypeToTypeOfKind φ tbody ★ >>= fun tbody' =>
                                                      castExpr we "WELam" (τ@@lev) (ELam Γ Δ ξ tv tbody' lev ev ebody')
 
     | WEBrak  _ ec e tbody              => φ (`ec) >>= fun ec' =>
                                              weakTypeToTypeOfKind φ tbody ★ >>= fun tbody' =>
-                                               weakExprToStrongExpr Γ Δ φ ψ ξ tbody' ((ec')::lev) e >>= fun e' =>
+                                               weakExprToStrongExpr Γ Δ φ ψ ξ ig tbody' ((ec')::lev) e >>= fun e' =>
                                                  castExpr we "WEBrak" (τ@@lev) (EBrak Γ Δ ξ ec' tbody' lev e')
 
     | WEEsc   _ ec e tbody              => φ ec >>= fun ec'' =>
                                            weakTypeToTypeOfKind φ tbody ★ >>= fun tbody' =>
                                            match lev with
                                              | nil       => Error "ill-leveled escapification"
                                                  castExpr we "WEBrak" (τ@@lev) (EBrak Γ Δ ξ ec' tbody' lev e')
 
     | WEEsc   _ ec e tbody              => φ ec >>= fun ec'' =>
                                            weakTypeToTypeOfKind φ tbody ★ >>= fun tbody' =>
                                            match lev with
                                              | nil       => Error "ill-leveled escapification"
-                                             | ec'::lev' => weakExprToStrongExpr Γ Δ φ ψ ξ (<[ ec' |- tbody' ]>) lev' e
+                                             | ec'::lev' => weakExprToStrongExpr Γ Δ φ ψ ξ ig (<[ ec' |- tbody' ]>) lev' e
                                                >>= fun e' => castExpr we "WEEsc" (τ@@lev) (EEsc Γ Δ ξ ec' tbody' lev' e')
                                            end
 
     | WECSP   _ ec e tbody              => Error "FIXME: CSP not supported beyond HaskWeak stage"
 
                                                >>= fun e' => castExpr we "WEEsc" (τ@@lev) (EEsc Γ Δ ξ ec' tbody' lev' e')
                                            end
 
     | WECSP   _ ec e tbody              => Error "FIXME: CSP not supported beyond HaskWeak stage"
 
-    | WENote  n e                       => weakExprToStrongExpr Γ Δ φ ψ ξ τ lev e >>= fun e' => OK (ENote _ _ _ _ n e')
+    | WENote  n e                       => weakExprToStrongExpr Γ Δ φ ψ ξ ig τ lev e >>= fun e' => OK (ENote _ _ _ _ n e')
 
     | WELet   v ve  ebody               => weakTypeToTypeOfKind φ v ★  >>= fun tv =>
 
     | WELet   v ve  ebody               => weakTypeToTypeOfKind φ v ★  >>= fun tv =>
-                                             weakExprToStrongExpr Γ Δ φ ψ ξ tv lev ve >>= fun ve' =>
-                                               weakExprToStrongExpr Γ Δ φ ψ (update_ξ ξ (((v:CoreVar),tv@@lev)::nil)) τ lev ebody
+                                             weakExprToStrongExpr Γ Δ φ ψ ξ ig tv lev ve >>= fun ve' =>
+                                               weakExprToStrongExpr Γ Δ φ ψ (update_ξ ξ (((v:CoreVar),tv@@lev)::nil))
+                                                    (update_ig ig ((v:CoreVar)::nil)) τ lev ebody
                                                >>= fun ebody' =>
                                                  OK (ELet _ _ _ tv _ lev (v:CoreVar) ve' ebody')
 
     | WEApp   e1 e2                     => weakTypeOfWeakExpr e2 >>= fun t2 =>
                                              weakTypeToTypeOfKind φ t2 ★ >>= fun t2' =>
                                                >>= fun ebody' =>
                                                  OK (ELet _ _ _ tv _ lev (v:CoreVar) ve' ebody')
 
     | WEApp   e1 e2                     => weakTypeOfWeakExpr e2 >>= fun t2 =>
                                              weakTypeToTypeOfKind φ t2 ★ >>= fun t2' =>
-                                               weakExprToStrongExpr Γ Δ φ ψ ξ t2' lev e2 >>= fun e2' =>
-                                                 weakExprToStrongExpr Γ Δ φ ψ ξ (t2'--->τ) lev e1 >>= fun e1' =>
+                                               weakExprToStrongExpr Γ Δ φ ψ ξ ig t2' lev e2 >>= fun e2' =>
+                                                 weakExprToStrongExpr Γ Δ φ ψ ξ ig (t2'--->τ) lev e1 >>= fun e1' =>
                                                    OK (EApp _ _ _ _ _ _ e1' e2')
 
     | WETyLam tv e                      => let φ' := upφ tv φ in
                                              weakTypeOfWeakExpr e >>= fun te =>
                                                weakTypeToTypeOfKind φ' te ★ >>= fun τ' =>
                                                  weakExprToStrongExpr _ (weakCE Δ) φ'
                                                    OK (EApp _ _ _ _ _ _ e1' e2')
 
     | WETyLam tv e                      => let φ' := upφ tv φ in
                                              weakTypeOfWeakExpr e >>= fun te =>
                                                weakTypeToTypeOfKind φ' te ★ >>= fun τ' =>
                                                  weakExprToStrongExpr _ (weakCE Δ) φ'
-                                                    (fun x => (ψ x) >>= fun y => OK (weakCV y)) (weakLT○ξ) τ' (weakL lev) e
-                                                 >>= fun e' =>
-                                                   castExpr we "WETyLam1" _ e' >>= fun e'' =>
-                                                     castExpr we "WETyLam2" _ (ETyLam Γ Δ ξ tv (mkTAll' τ') lev e'')
+                                                   (fun x => (ψ x) >>= fun y => OK (weakCV y)) (weakLT○ξ) ig _ (weakL lev) e
+                                                     >>= fun e' => castExpr we "WETyLam2" _ (ETyLam Γ Δ ξ tv (mkTAll' τ') lev e')
 
     | WETyApp e t                       => weakTypeOfWeakExpr e >>= fun te =>
                                            match te with
                                              | WForAllTy wtv te' =>
                                                let φ' := upφ wtv φ in
                                                  weakTypeToTypeOfKind φ' te' ★ >>= fun te'' =>
 
     | WETyApp e t                       => weakTypeOfWeakExpr e >>= fun te =>
                                            match te with
                                              | WForAllTy wtv te' =>
                                                let φ' := upφ wtv φ in
                                                  weakTypeToTypeOfKind φ' te' ★ >>= fun te'' =>
-                                                   weakExprToStrongExpr Γ Δ φ ψ ξ (mkTAll te'') lev e >>= fun e' =>
+                                                   weakExprToStrongExpr Γ Δ φ ψ ξ ig (mkTAll te'') lev e >>= fun e' =>
                                                      weakTypeToTypeOfKind φ t (wtv:Kind) >>= fun t' =>
                                                        castExpr we "WETyApp" _ (ETyApp Γ Δ wtv (mkTAll' te'') t' ξ lev e')
                                              | _                 => Error ("weakTypeToType: WETyApp body with type "+++te)
                                                      weakTypeToTypeOfKind φ t (wtv:Kind) >>= fun t' =>
                                                        castExpr we "WETyApp" _ (ETyApp Γ Δ wtv (mkTAll' te'') t' ξ lev e')
                                              | _                 => Error ("weakTypeToType: WETyApp body with type "+++te)
@@ -544,7 +561,7 @@ Definition weakExprToStrongExpr : forall
                                                    haskTypeOfSomeKind κ t1'' =>
                                                    weakTypeToTypeOfKind φ t2 κ >>= fun t2'' =>
                                                      weakTypeToTypeOfKind φ t3 ★ >>= fun t3'' =>
                                                    haskTypeOfSomeKind κ t1'' =>
                                                    weakTypeToTypeOfKind φ t2 κ >>= fun t2'' =>
                                                      weakTypeToTypeOfKind φ t3 ★ >>= fun t3'' =>
-                                                       weakExprToStrongExpr Γ Δ φ ψ ξ (t1'' ∼∼ t2'' ⇒ τ) lev e >>= fun e' =>
+                                                       weakExprToStrongExpr Γ Δ φ ψ ξ ig (t1'' ∼∼ t2'' ⇒ τ) lev e >>= fun e' =>
                                                          castExpr we "WECoApp" _ e' >>= fun e'' =>
                                                            OK (ECoApp Γ Δ κ t1'' t2''
                                                              (weakCoercionToHaskCoercion _ _ _ co) τ ξ lev e'')
                                                          castExpr we "WECoApp" _ e' >>= fun e'' =>
                                                            OK (ECoApp Γ Δ κ t1'' t2''
                                                              (weakCoercionToHaskCoercion _ _ _ co) τ ξ lev e'')
@@ -557,37 +574,43 @@ Definition weakExprToStrongExpr : forall
                                              weakTypeToTypeOfKind φ te ★ >>= fun te' =>
                                                weakTypeToTypeOfKind φ t1 cv >>= fun t1' =>
                                                  weakTypeToTypeOfKind φ t2 cv >>= fun t2' =>
                                              weakTypeToTypeOfKind φ te ★ >>= fun te' =>
                                                weakTypeToTypeOfKind φ t1 cv >>= fun t1' =>
                                                  weakTypeToTypeOfKind φ t2 cv >>= fun t2' =>
-                                                   weakExprToStrongExpr Γ (_ :: Δ) φ (weakψ ψ) ξ te' lev e >>= fun e' =>
+                                                   weakExprToStrongExpr Γ (_ :: Δ) φ (weakψ ψ) ξ ig te' lev e >>= fun e' =>
                                                      castExpr we "WECoLam" _ (ECoLam Γ Δ cv te' t1' t2' ξ lev e')
 
     | WECast  e co                      => let (t1,t2) := weakCoercionTypes co in
                                              weakTypeToTypeOfKind φ t1 ★ >>= fun t1' =>
                                                weakTypeToTypeOfKind φ t2 ★ >>= fun t2' =>
                                                      castExpr we "WECoLam" _ (ECoLam Γ Δ cv te' t1' t2' ξ lev e')
 
     | WECast  e co                      => let (t1,t2) := weakCoercionTypes co in
                                              weakTypeToTypeOfKind φ t1 ★ >>= fun t1' =>
                                                weakTypeToTypeOfKind φ t2 ★ >>= fun t2' =>
-                                                   weakExprToStrongExpr Γ Δ φ ψ ξ t1' lev e >>= fun e' =>
+                                                   weakExprToStrongExpr Γ Δ φ ψ ξ ig t1' lev e >>= fun e' =>
                                                      castExpr we "WECast" _ 
                                                        (ECast Γ Δ ξ t1' t2' (weakCoercionToHaskCoercion _ _ _ co) lev e')
 
     | WELetRec rb   e                   =>
                                                      castExpr we "WECast" _ 
                                                        (ECast Γ Δ ξ t1' t2' (weakCoercionToHaskCoercion _ _ _ co) lev e')
 
     | WELetRec rb   e                   =>
-      let ξ' := update_ξ ξ (map (fun x => ((fst x),(snd x @@ lev))) _)
-      in let binds := 
+      let ξ' := update_ξ ξ (map (fun x => ((fst x),(snd x @@ lev))) _) in
+      let ig' := update_ig ig (map (fun x:(WeakExprVar*_) => (fst x):CoreVar) (leaves rb)) in
+      let binds := 
         (fix binds (t:Tree ??(WeakExprVar * WeakExpr))
           : ???(ELetRecBindings Γ Δ ξ' lev (varsTypes t φ)) :=
         match t with
           | T_Leaf None           => let case_nil := tt in OK (ELR_nil _ _ _ _)
         (fix binds (t:Tree ??(WeakExprVar * WeakExpr))
           : ???(ELetRecBindings Γ Δ ξ' lev (varsTypes t φ)) :=
         match t with
           | T_Leaf None           => let case_nil := tt in OK (ELR_nil _ _ _ _)
-          | T_Leaf (Some (wev,e)) => let case_some := tt in (fun e' => _) (fun τ => weakExprToStrongExpr Γ Δ φ ψ ξ' τ lev e)
+          | T_Leaf (Some (wev,e)) => let case_some := tt in (fun e' => _) (fun τ => weakExprToStrongExpr Γ Δ φ ψ ξ' ig' τ lev e)
           | T_Branch b1 b2        =>
             binds b1 >>= fun b1' =>
               binds b2 >>= fun b2' =>
                 OK (ELR_branch Γ Δ ξ' lev _ _ b1' b2')
         end) rb
       in binds >>= fun binds' =>
           | T_Branch b1 b2        =>
             binds b1 >>= fun b1' =>
               binds b2 >>= fun b2' =>
                 OK (ELR_branch Γ Δ ξ' lev _ _ b1' b2')
         end) rb
       in binds >>= fun binds' =>
-           weakExprToStrongExpr Γ Δ φ ψ ξ' τ lev e >>= fun e' =>       
+           weakExprToStrongExpr Γ Δ φ ψ ξ' ig' τ lev e >>= fun e' =>       
              OK (ELetRec Γ Δ ξ lev τ _ binds' e')
 
              OK (ELetRec Γ Δ ξ lev τ _ binds' e')
 
-    | WECase vscrut ve tbranches tc avars alts =>
-        weakTypeToTypeOfKind φ (vscrut:WeakType) ★  >>= fun tv =>
-          weakExprToStrongExpr Γ Δ φ ψ ξ tv lev ve >>= fun ve' =>
-            let ξ' := update_ξ ξ (((vscrut:CoreVar),tv@@lev)::nil) in
+    | WECase vscrut escrut tbranches tc avars alts =>
+        weakTypeOfWeakExpr escrut >>= fun tscrut =>
+          weakTypeToTypeOfKind φ tscrut ★ >>= fun tscrut' =>
+(*
+            let ξ'  := update_ξ  ξ  (((vscrut:CoreVar),tscrut'@@lev)::nil) in
+            let ig' := update_ig ig ((vscrut:CoreVar)::nil) in
+*)
+            let ξ'  := ξ in
+            let ig' := ig in
               mkAvars avars (tyConKind tc) φ >>= fun avars' =>
                 weakTypeToTypeOfKind φ tbranches ★  >>= fun tbranches' =>
                   (fix mkTree (t:Tree ??(WeakAltCon*list WeakTypeVar*list WeakCoerVar*list WeakExprVar*WeakExpr)) : ???(Tree
               mkAvars avars (tyConKind tc) φ >>= fun avars' =>
                 weakTypeToTypeOfKind φ tbranches ★  >>= fun tbranches' =>
                   (fix mkTree (t:Tree ??(WeakAltCon*list WeakTypeVar*list WeakCoerVar*list WeakExprVar*WeakExpr)) : ???(Tree
@@ -602,19 +625,25 @@ Definition weakExprToStrongExpr : forall
                             let scb := @Build_StrongCaseBranchWithVVs CoreVar CoreVarEqDecidable tc Γ avars' sac exprvars' in
                               weakExprToStrongExpr (sac_Γ scb Γ) (sac_Δ scb Γ avars' (weakCK'' Δ)) (sacpj_φ sac _ φ)
                               (sacpj_ψ sac _ _ avars' ψ)
                             let scb := @Build_StrongCaseBranchWithVVs CoreVar CoreVarEqDecidable tc Γ avars' sac exprvars' in
                               weakExprToStrongExpr (sac_Γ scb Γ) (sac_Δ scb Γ avars' (weakCK'' Δ)) (sacpj_φ sac _ φ)
                               (sacpj_ψ sac _ _ avars' ψ)
-                              (scbwv_ξ scb ξ' lev) (weakT' tbranches') (weakL' lev) ebranch >>= fun ebranch' =>
+                              (scbwv_ξ scb ξ' lev)
+                              (update_ig ig' (map (@fst _ _) (vec2list (scbwv_varstypes scb))))
+                              (weakT' tbranches') (weakL' lev) ebranch >>= fun ebranch' =>
                                 let case_case := tt in OK [ _ ]
                       | T_Branch b1 b2        =>
                         mkTree b1 >>= fun b1' =>
                           mkTree b2 >>= fun b2' =>
                             OK (b1',,b2')
                     end) alts >>= fun tree =>
                                 let case_case := tt in OK [ _ ]
                       | T_Branch b1 b2        =>
                         mkTree b1 >>= fun b1' =>
                           mkTree b2 >>= fun b2' =>
                             OK (b1',,b2')
                     end) alts >>= fun tree =>
-                  castExpr we "ECaseScrut" _ (EVar Γ Δ ξ' vscrut) >>= fun escrut =>
-                      castExpr we "ECase" _ (ECase Γ Δ ξ' lev tc tbranches' avars' escrut tree)
-                        >>= fun ecase' => OK (ELet _ _ _ tv _ lev (vscrut:CoreVar) ve' ecase')
-
-
 
 
+                  weakExprToStrongExpr Γ Δ φ ψ ξ ig (caseType tc avars') lev escrut >>= fun escrut' =>
+                    castExpr we "ECase" (τ@@lev) (ECase Γ Δ ξ' lev tc tbranches' avars' escrut' tree)
+(*
+                  weakExprToStrongExpr Γ Δ φ ψ ξ ig tscrut' lev escrut >>= fun escrut' =>
+                    castExpr we "ECaseScrut" (caseType tc avars' @@  lev) (EVar Γ Δ ξ' vscrut) >>= fun evscrut' =>
+                      castExpr we "ECase" (τ@@lev)
+                      (ELet Γ Δ ξ tscrut' tbranches' lev (vscrut:CoreVar) escrut'
+                        (ECase Γ Δ ξ' lev tc tbranches' avars' evscrut' tree))
+*)
     end)).
 
     destruct case_some.
     end)).
 
     destruct case_some.