module DDC.Core.Check.Judge.Sub
( makeSub)
where
import DDC.Type.Transform.SubstituteT
import DDC.Core.Annot.AnTEC
import DDC.Core.Check.Judge.Eq
import DDC.Core.Check.Judge.Inst
import DDC.Core.Check.Base
makeSub :: (Eq n, Ord n, Show n, Pretty n)
=> Config n
-> a
-> Context n
-> Exp (AnTEC a n) n
-> Type n
-> Type n
-> Error a n
-> CheckM a n
( Exp (AnTEC a n) n
, Context n)
makeSub config a ctx0 xL tL tR err
| TCon tc1 <- tL
, TCon tc2 <- tR
, equivTyCon tc1 tc2
= do
ctrace $ vcat
[ text "* SubCon"
, text " LEFT: " <> ppr tL
, text " RIGHT: " <> ppr tR
, indent 2 $ ppr ctx0
, empty ]
return (xL, ctx0)
| TVar u1 <- tL
, TVar u2 <- tR
, u1 == u2
= do
ctrace $ vcat
[ text "* SubVar"
, text " LEFT: " <> ppr tL
, text " RIGHT: " <> ppr tR
, indent 2 $ ppr ctx0
, empty ]
return (xL, ctx0)
| Just iL <- takeExists tL
, Just iR <- takeExists tR
, iL == iR
= do
ctrace $ vcat
[ text "* SubExVar"
, text " LEFT: " <> ppr tL
, text " RIGHT: " <> ppr tR
, indent 2 $ ppr ctx0
, empty ]
return (xL, ctx0)
| isTExists tL
= do ctx1 <- makeInst config a ctx0 tR tL err
ctrace $ vcat
[ text "* SubInstL"
, text " LEFT: " <> ppr tL
, text " RIGHT: " <> ppr tR
, indent 2 $ ppr ctx0
, indent 2 $ ppr ctx1
, empty ]
return (xL, ctx1)
| isTExists tR
= do ctx1 <- makeInst config a ctx0 tL tR err
ctrace $ vcat
[ text "* SubInstR"
, text " LEFT: " <> ppr tL
, text " RIGHT: " <> ppr tR
, indent 2 $ ppr ctx0
, indent 2 $ ppr ctx1
, empty ]
return (xL, ctx1)
| Just (tL1, tL2) <- takeTFun tL
, Just (tR1, tR2) <- takeTFun tR
= do
(_, ctx1) <- makeSub config a ctx0 xL tR1 tL1 err
let tL2' = applyContext ctx1 tL2
let tR2' = applyContext ctx1 tR2
(_, ctx2) <- makeSub config a ctx1 xL tL2' tR2' err
ctrace $ vcat
[ text "* SubArr"
, text " LEFT: " <> ppr tL
, text " RIGHT: " <> ppr tR
, indent 2 $ ppr ctx0
, indent 2 $ ppr ctx1
, indent 2 $ ppr ctx2
, empty ]
return (xL, ctx2)
| TApp tL1 tL2 <- tL
, TApp tR1 tR2 <- tR
= do
ctx1 <- makeEq config a ctx0 tL1 tR1 err
let tL2' = applyContext ctx1 tL2
let tR2' = applyContext ctx1 tR2
ctx2 <- makeEq config a ctx1 tL2' tR2' err
ctrace $ vcat
[ text "* SubApp"
, text " LEFT: " <> ppr tL
, text " RIGHT: " <> ppr tR
, indent 2 $ ppr ctx0
, indent 2 $ ppr ctx1
, indent 2 $ ppr ctx2
, empty ]
return (xL, ctx2)
| TForall b t1 <- tL
= do
iA <- newExists (typeOfBind b)
let tA = typeOfExists iA
let t1' = substituteT b tA t1
let (ctx1, pos1) = markContext ctx0
let ctx2 = pushExists iA ctx1
(xL1, ctx3) <- makeSub config a ctx2 xL t1' tR err
let ctx4 = popToPos pos1 ctx3
ctrace $ vcat
[ text "* SubForall"
, text " LEFT: " <> ppr tL
, text " RIGHT: " <> ppr tR
, indent 2 $ ppr ctx0
, indent 2 $ ppr ctx4
, empty ]
let AnTEC _ e0 c0 _
= annotOfExp xL
let aFn = AnTEC t1' (substituteT b tA e0) (substituteT b tA c0) a
let aArg = AnTEC (typeOfBind b) (tBot kEffect) (tBot kClosure) a
let xL2 = XApp aFn xL1 (XType aArg tA)
return (xL2, ctx4)
| otherwise
= do ctrace $ vcat
[ text "DDC.Core.Check.Exp.Inst.makeSub: no match"
, text " LEFT: " <> text (show tL)
, text " RIGHT: " <> text (show tR) ]
throw err