forked from GitHub/gf-core
typechecking without Value<->Term conversion
This commit is contained in:
@@ -56,7 +56,6 @@ data ThunkState s
|
||||
| Hole {-# UNPACK #-} !MetaId
|
||||
| Narrowing {-# UNPACK #-} !MetaId Type
|
||||
| Residuation {-# UNPACK #-} !MetaId (Scope s) (Sigma s)
|
||||
| Bound Term
|
||||
|
||||
type Thunk s = STRef s (ThunkState s)
|
||||
type Env s = [(Ident,Thunk s)]
|
||||
@@ -64,8 +63,8 @@ type Scope s = [(Ident,Value s)]
|
||||
|
||||
data Value s
|
||||
= VApp QIdent [Thunk s]
|
||||
| VMeta (Thunk s) (Env s) [Thunk s]
|
||||
| VSusp (Thunk s) (Env s) (Value s -> EvalM s (Value s)) [Thunk s]
|
||||
| VMeta (Thunk s) [Thunk s]
|
||||
| VSusp (Thunk s) (Value s -> EvalM s (Value s)) [Thunk s]
|
||||
| VGen {-# UNPACK #-} !Int [Thunk s]
|
||||
| VClosure (Env s) Term
|
||||
| VProd BindType Ident (Value s) (Value s)
|
||||
@@ -95,9 +94,9 @@ data Value s
|
||||
|
||||
|
||||
showValue (VApp q tnks) = "(VApp "++unwords (show q : map (const "_") tnks) ++ ")"
|
||||
showValue (VMeta _ _ _) = "VMeta"
|
||||
showValue (VSusp _ _ _ _) = "VSusp"
|
||||
showValue (VGen _ _) = "VGen"
|
||||
showValue (VMeta _ _) = "VMeta"
|
||||
showValue (VSusp _ _ _) = "VSusp"
|
||||
showValue (VGen i _) = "(VGen "++show i++")"
|
||||
showValue (VClosure _ _) = "VClosure"
|
||||
showValue (VProd _ x v1 v2) = "VProd ("++show x++") ("++showValue v1++") ("++showValue v2++")"
|
||||
showValue (VRecType _) = "VRecType"
|
||||
@@ -108,7 +107,7 @@ showValue (VTable v1 v2) = "VTable ("++showValue v1++") ("++showValue v2++")"
|
||||
showValue (VT _ _ cs) = "(VT "++show cs++")"
|
||||
showValue (VV _ _) = "VV"
|
||||
showValue (VS v _ _) = "(VS "++showValue v++")"
|
||||
showValue (VSort _) = "VSort"
|
||||
showValue (VSort s) = "(VSort "++show s++")"
|
||||
showValue (VInt _) = "VInt"
|
||||
showValue (VFlt _) = "VFlt"
|
||||
showValue (VStr s) = "(VStr "++show s++")"
|
||||
@@ -142,7 +141,7 @@ eval env (App t1 t2) vs = do tnk <- newThunk env t2
|
||||
eval env (Abs b x t) [] = return (VClosure env (Abs b x t))
|
||||
eval env (Abs b x t) (v:vs) = eval ((x,v):env) t vs
|
||||
eval env (Meta i) vs = do tnk <- newHole i
|
||||
return (VMeta tnk env vs)
|
||||
return (VMeta tnk vs)
|
||||
eval env (ImplArg t) [] = eval env t []
|
||||
eval env (Prod b x t1 t2)[] = do v1 <- eval env t1 []
|
||||
return (VProd b x v1 (VClosure env t2))
|
||||
@@ -256,8 +255,8 @@ eval env (TSymCat d r rs) []= do rs <- forM rs $ \(i,(pv,ty)) ->
|
||||
eval env (TSymVar d r) [] = do return (VSymVar d r)
|
||||
eval env t vs = evalError ("Cannot reduce term" <+> pp t)
|
||||
|
||||
apply (VMeta m env vs0) vs = return (VMeta m env (vs0++vs))
|
||||
apply (VSusp m env k vs0) vs = return (VSusp m env k (vs0++vs))
|
||||
apply (VMeta m vs0) vs = return (VMeta m (vs0++vs))
|
||||
apply (VSusp m k vs0) vs = return (VSusp m k (vs0++vs))
|
||||
apply (VApp f vs0) vs = return (VApp f (vs0++vs))
|
||||
apply (VGen i vs0) vs = return (VGen i (vs0++vs))
|
||||
apply (VClosure env (Abs b x t)) (v:vs) = eval ((x,v):env) t vs
|
||||
@@ -345,9 +344,9 @@ patternMatch v0 ((env0,ps,args0,t):eqs) = match env0 ps eqs args0
|
||||
|
||||
match' env p ps eqs arg v args = do
|
||||
case (p,v) of
|
||||
(p, VMeta i envi vs) -> susp i envi (\v -> apply v vs >>= \v -> match' env p ps eqs arg v args)
|
||||
(p, VGen i vs ) -> return v0
|
||||
(p, VSusp i envi k vs) -> susp i envi (\v -> k v >>= \v -> apply v vs >>= \v -> match' env p ps eqs arg v args)
|
||||
(p, VMeta i vs) -> susp i (\v -> apply v vs >>= \v -> match' env p ps eqs arg v args)
|
||||
(p, VGen i vs) -> return v0
|
||||
(p, VSusp i k vs) -> susp i (\v -> k v >>= \v -> apply v vs >>= \v -> match' env p ps eqs arg v args)
|
||||
(PP q qs, VApp r tnks)
|
||||
| q == r -> match env (qs++ps) eqs (tnks++args)
|
||||
(PR pas, VR as) -> matchRec env (reverse pas) as ps eqs args
|
||||
@@ -443,18 +442,18 @@ vtableSelect v0 ty tnks tnk2 vs = do
|
||||
return (r*cnt'+r',cnt*cnt')
|
||||
value2index (VInt n) ty
|
||||
| Just max <- isTypeInts ty = return (fromIntegral n,fromIntegral max+1)
|
||||
value2index (VMeta i envi vs) ty = do
|
||||
v <- susp i envi (\v -> apply v vs)
|
||||
value2index (VMeta i vs) ty = do
|
||||
v <- susp i (\v -> apply v vs)
|
||||
value2index v ty
|
||||
value2index (VSusp i envi k vs) ty = do
|
||||
v <- susp i envi (\v -> k v >>= \v -> apply v vs)
|
||||
value2index (VSusp i k vs) ty = do
|
||||
v <- susp i (\v -> k v >>= \v -> apply v vs)
|
||||
value2index v ty
|
||||
value2index v ty = do t <- value2term [] v
|
||||
evalError ("the parameter:" <+> ppTerm Unqualified 0 t $$
|
||||
"cannot be evaluated at compile time.")
|
||||
|
||||
|
||||
susp i env ki = EvalM $ \gr k mt d r msgs -> do
|
||||
susp i ki = EvalM $ \gr k mt d r msgs -> do
|
||||
s <- readSTRef i
|
||||
case s of
|
||||
Narrowing id (QC q) -> case lookupOrigInfo gr q of
|
||||
@@ -465,13 +464,13 @@ susp i env ki = EvalM $ \gr k mt d r msgs -> do
|
||||
-> bindInt gr k mt d r msgs s 0 max
|
||||
Evaluated _ v -> case ki v of
|
||||
EvalM f -> f gr k mt d r msgs
|
||||
_ -> k (VSusp i env ki []) mt d r msgs
|
||||
_ -> k (VSusp i ki []) mt d r msgs
|
||||
where
|
||||
bindParam gr k mt d r msgs s m [] = return (Success r msgs)
|
||||
bindParam gr k mt d r msgs s m ((p, ctxt):ps) = do
|
||||
(mt',tnks) <- mkArgs mt ctxt
|
||||
let v = VApp (m,p) tnks
|
||||
writeSTRef i (Evaluated (length env) v)
|
||||
writeSTRef i (Evaluated 0 v)
|
||||
res <- case ki v of
|
||||
EvalM f -> f gr k mt' d r msgs
|
||||
writeSTRef i s
|
||||
@@ -491,7 +490,7 @@ susp i env ki = EvalM $ \gr k mt d r msgs -> do
|
||||
bindInt gr k mt d r msgs s iv max
|
||||
| iv <= max = do
|
||||
let v = VInt iv
|
||||
writeSTRef i (Evaluated (length env) v)
|
||||
writeSTRef i (Evaluated 0 v)
|
||||
res <- case ki v of
|
||||
EvalM f -> f gr k mt d r msgs
|
||||
writeSTRef i s
|
||||
@@ -503,19 +502,17 @@ susp i env ki = EvalM $ \gr k mt d r msgs -> do
|
||||
|
||||
value2term xs (VApp q tnks) =
|
||||
foldM (\e1 tnk -> fmap (App e1) (tnk2term xs tnk)) (if fst q == cPredef then Q q else QC q) tnks
|
||||
value2term xs (VMeta m env vs) = do
|
||||
value2term xs (VMeta m vs) = do
|
||||
s <- getRef m
|
||||
case s of
|
||||
Evaluated _ v -> do v <- apply v vs
|
||||
value2term xs v
|
||||
Unevaluated env t -> do v <- eval env t vs
|
||||
value2term xs v
|
||||
Bound t -> do v <- eval env t vs
|
||||
value2term xs v
|
||||
Hole i -> foldM (\e1 tnk -> fmap (App e1) (tnk2term xs tnk)) (Meta i) vs
|
||||
Residuation i _ _ -> foldM (\e1 tnk -> fmap (App e1) (tnk2term xs tnk)) (Meta i) vs
|
||||
Narrowing i _ -> foldM (\e1 tnk -> fmap (App e1) (tnk2term xs tnk)) (Meta i) vs
|
||||
value2term xs (VSusp j env k vs) = do
|
||||
value2term xs (VSusp j k vs) = do
|
||||
v <- k (VGen maxBound vs)
|
||||
value2term xs v
|
||||
value2term xs (VGen j tnks) =
|
||||
@@ -861,9 +858,9 @@ force tnk = EvalM $ \gr k mt d r msgs -> do
|
||||
writeSTRef tnk s
|
||||
return r) mt d r msgs
|
||||
Evaluated d v -> k v mt d r msgs
|
||||
Hole _ -> k (VMeta tnk [] []) mt d r msgs
|
||||
Residuation _ _ _ -> k (VMeta tnk [] []) mt d r msgs
|
||||
Narrowing _ _ -> k (VMeta tnk [] []) mt d r msgs
|
||||
Hole _ -> k (VMeta tnk []) mt d r msgs
|
||||
Residuation _ _ _ -> k (VMeta tnk []) mt d r msgs
|
||||
Narrowing _ _ -> k (VMeta tnk []) mt d r msgs
|
||||
|
||||
tnk2term xs tnk = EvalM $ \gr k mt d r msgs ->
|
||||
let join f g = do res <- f
|
||||
|
||||
@@ -253,7 +253,7 @@ param2int (VApp q tnks) ty = do
|
||||
return (r*cnt'+r',combine' cnt rs cnt' rs',cnt*cnt')
|
||||
param2int (VInt n) ty
|
||||
| Just max <- isTypeInts ty= return (fromIntegral n,[],fromIntegral max+1)
|
||||
param2int (VMeta tnk _ _) ty = do
|
||||
param2int (VMeta tnk _) ty = do
|
||||
tnk_st <- getRef tnk
|
||||
case tnk_st of
|
||||
Evaluated _ v -> param2int v ty
|
||||
|
||||
@@ -27,14 +27,14 @@ checkLType :: Grammar -> Term -> Type -> Check (Term, Type)
|
||||
checkLType gr t ty = runEvalOneM gr $ do
|
||||
vty <- eval [] ty []
|
||||
(t,_) <- tcRho [] t (Just vty)
|
||||
t <- zonkTerm t
|
||||
t <- zonkTerm [] t
|
||||
return (t,ty)
|
||||
|
||||
inferLType :: Grammar -> Term -> Check (Term, Type)
|
||||
inferLType gr t = runEvalOneM gr $ do
|
||||
(t,ty) <- inferSigma [] t
|
||||
t <- zonkTerm t
|
||||
ty <- zonkTerm =<< value2term [] ty
|
||||
t <- zonkTerm [] t
|
||||
ty <- value2term [] ty
|
||||
return (t,ty)
|
||||
|
||||
inferSigma :: Scope s -> Term -> EvalM s (Term,Sigma s)
|
||||
@@ -72,21 +72,94 @@ tcRho scope t@(App fun arg) mb_ty = do
|
||||
(t,ty) <- tcApp scope t t
|
||||
instSigma scope t ty mb_ty
|
||||
tcRho scope (Abs bt var body) Nothing = do -- ABS1
|
||||
(_,tnk) <- newResiduation scope vtypeType
|
||||
env <- scopeEnv scope
|
||||
let arg_ty = VMeta tnk env []
|
||||
(i,tnk) <- newResiduation scope vtypeType
|
||||
let arg_ty = VMeta tnk []
|
||||
(body,body_ty) <- tcRho ((var,arg_ty):scope) body Nothing
|
||||
return (Abs bt var body, (VProd bt identW arg_ty body_ty))
|
||||
let m = length scope
|
||||
n = m+1
|
||||
(b,used_bndrs) <- check m n (False,[]) body_ty
|
||||
if b
|
||||
then let v = head (allBinders \\ used_bndrs)
|
||||
in return (Abs bt var body, (VProd bt v arg_ty body_ty))
|
||||
else return (Abs bt var body, (VProd bt identW arg_ty body_ty))
|
||||
where
|
||||
check m n st (VApp f vs) = foldM (follow m n) st vs
|
||||
check m n st (VMeta i vs) = do
|
||||
s <- getRef i
|
||||
case s of
|
||||
Evaluated _ v -> do v <- apply v vs
|
||||
check m n st v
|
||||
_ -> foldM (follow m n) st vs
|
||||
check m n st@(b,xs) (VGen i vs)
|
||||
| i == m = return (True, xs)
|
||||
| otherwise = return st
|
||||
check m n st (VClosure env (Abs bt x t)) = do
|
||||
tnk <- newEvaluatedThunk (VGen n [])
|
||||
v <- eval ((x,tnk):env) t []
|
||||
check m (n+1) st v
|
||||
check m n st (VProd _ x v1 v2) = do
|
||||
st@(b,xs) <- check m n st v1
|
||||
case v2 of
|
||||
VClosure env t -> do tnk <- newEvaluatedThunk (VGen n [])
|
||||
v2 <- eval ((x,tnk):env) t []
|
||||
check m (n+1) (b,x:xs) v2
|
||||
v2 -> check m n st v2
|
||||
check m (n+1) (b,x:xs) v2
|
||||
check m n st (VRecType as) = foldM (\st (l,v) -> check m n st v) st as
|
||||
check m n st (VR as) =
|
||||
foldM (\st (lbl,tnk) -> follow m n st tnk) st as
|
||||
check m n st (VP v l vs) =
|
||||
check m n st v >>= \st -> foldM (follow m n) st vs
|
||||
check m n st (VExtR v1 v2) =
|
||||
check m n st v1 >>= \st -> check m n st v2
|
||||
check m n st (VTable v1 v2) =
|
||||
check m n st v1 >>= \st -> check m n st v2
|
||||
check m n st (VT ty env cs) =
|
||||
check m n st ty -- Traverse cs as well
|
||||
check m n st (VV ty cs) =
|
||||
check m n st ty >>= \st -> foldM (follow m n) st cs
|
||||
check m n st (VS v1 tnk vs) = do
|
||||
st <- check m n st v1
|
||||
st <- follow m n st tnk
|
||||
foldM (follow m n) st vs
|
||||
check m n st (VSort _) = return st
|
||||
check m n st (VInt _) = return st
|
||||
check m n st (VFlt _) = return st
|
||||
check m n st (VStr _) = return st
|
||||
check m n st VEmpty = return st
|
||||
check m n st (VC v1 v2) =
|
||||
check m n st v1 >>= \st -> check m n st v2
|
||||
check m n st (VGlue v1 v2) =
|
||||
check m n st v1 >>= \st -> check m n st v2
|
||||
check m n st (VPatt _ _ _) = return st
|
||||
check m n st (VPattType v) = check m n st v
|
||||
check m n st (VAlts v vs) = do
|
||||
st <- check m n st v
|
||||
foldM (\st (v1,v2) -> check m n st v1 >>= \st -> check m n st v2) st vs
|
||||
check m n st (VStrs vs) =
|
||||
foldM (check m n) st vs
|
||||
check m n st v = error (showValue v)
|
||||
|
||||
follow m n st tnk = force tnk >>= \v -> check m n st v
|
||||
|
||||
tcRho scope t@(Abs Implicit var body) (Just ty) = do -- ABS2
|
||||
(bt, _, var_ty, body_ty) <- unifyFun scope ty
|
||||
(bt, x, var_ty, body_ty) <- unifyFun scope ty
|
||||
if bt == Implicit
|
||||
then return ()
|
||||
else evalError (ppTerm Unqualified 0 t <+> "is an implicit function, but no implicit function is expected")
|
||||
body_ty <- case body_ty of
|
||||
VClosure env body_ty -> do tnk <- newEvaluatedThunk (VGen (length scope) [])
|
||||
eval ((x,tnk):env) body_ty []
|
||||
body_ty -> return body_ty
|
||||
(body, body_ty) <- tcRho ((var,var_ty):scope) body (Just body_ty)
|
||||
return (Abs Implicit var body,ty)
|
||||
tcRho scope (Abs Explicit var body) (Just ty) = do -- ABS3
|
||||
(scope,f,ty') <- skolemise scope ty
|
||||
(_,_,var_ty,body_ty) <- unifyFun scope ty'
|
||||
(_,x,var_ty,body_ty) <- unifyFun scope ty'
|
||||
body_ty <- case body_ty of
|
||||
VClosure env body_ty -> do tnk <- newEvaluatedThunk (VGen (length scope) [])
|
||||
eval ((x,tnk):env) body_ty []
|
||||
body_ty -> return body_ty
|
||||
(body, body_ty) <- tcRho ((var,var_ty):scope) body (Just body_ty)
|
||||
return (f (Abs Explicit var body),ty)
|
||||
tcRho scope (Meta i) (Just ty) = do
|
||||
@@ -95,7 +168,7 @@ tcRho scope (Meta i) (Just ty) = do
|
||||
tcRho scope (Meta _) Nothing = do
|
||||
(_,tnk) <- newResiduation scope vtypeType
|
||||
env <- scopeEnv scope
|
||||
let vty = VMeta tnk env []
|
||||
let vty = VMeta tnk []
|
||||
(i,_) <- newResiduation scope vty
|
||||
return (Meta i, vty)
|
||||
tcRho scope (Let (var, (mb_ann_ty, rhs)) body) mb_ty = do -- LET
|
||||
@@ -114,12 +187,12 @@ tcRho scope (Typed body ann_ty) mb_ty = do -- ANNOT
|
||||
env <- scopeEnv scope
|
||||
v_ann_ty <- eval env ann_ty []
|
||||
(body,_) <- tcRho scope body (Just v_ann_ty)
|
||||
instSigma scope (Typed body ann_ty) v_ann_ty mb_ty
|
||||
(res1,res2) <- instSigma scope (Typed body ann_ty) v_ann_ty mb_ty
|
||||
return (res1,res2)
|
||||
tcRho scope (FV ts) mb_ty = do
|
||||
case ts of
|
||||
[] -> do (i,tnk) <- newResiduation scope vtypeType
|
||||
env <- scopeEnv scope
|
||||
instSigma scope (FV []) (VMeta tnk env []) mb_ty
|
||||
instSigma scope (FV []) (VMeta tnk []) mb_ty
|
||||
(t:ts) -> do (t,ty) <- tcRho scope t mb_ty
|
||||
|
||||
let go [] ty = return ([],ty)
|
||||
@@ -140,12 +213,12 @@ tcRho scope t@(RecType rs) (Just ty) = do
|
||||
VSort s
|
||||
| s == cType -> return ()
|
||||
| s == cPType -> return ()
|
||||
VMeta i env vs -> case rs of
|
||||
[] -> unifyVar scope i env vs vtypePType
|
||||
_ -> return ()
|
||||
ty -> do ty <- zonkTerm =<< value2term (scopeVars scope) ty
|
||||
evalError ("The record type" <+> ppTerm Unqualified 0 t $$
|
||||
"cannot be of type" <+> ppTerm Unqualified 0 ty)
|
||||
VMeta i vs -> case rs of
|
||||
[] -> unifyVar scope i vs vtypePType
|
||||
_ -> return ()
|
||||
ty -> do ty <- value2term (scopeVars scope) ty
|
||||
evalError ("The record type" <+> ppTerm Unqualified 0 t $$
|
||||
"cannot be of type" <+> ppTerm Unqualified 0 ty)
|
||||
(rs,mb_ty) <- tcRecTypeFields scope rs (Just ty')
|
||||
return (f (RecType rs),ty)
|
||||
tcRho scope t@(Table p res) mb_ty = do
|
||||
@@ -160,7 +233,7 @@ tcRho scope (Prod bt x ty1 ty2) mb_ty = do
|
||||
instSigma scope (Prod bt x ty1 ty2) vtypeType mb_ty
|
||||
tcRho scope (S t p) mb_ty = do
|
||||
env <- scopeEnv scope
|
||||
let mk_val (_,tnk) = VMeta tnk env []
|
||||
let mk_val (_,tnk) = VMeta tnk []
|
||||
p_ty <- fmap mk_val $ newResiduation scope vtypePType
|
||||
res_ty <- case mb_ty of
|
||||
Nothing -> fmap mk_val $ newResiduation scope vtypeType
|
||||
@@ -171,7 +244,7 @@ tcRho scope (S t p) mb_ty = do
|
||||
return (S t p, res_ty)
|
||||
tcRho scope (T tt ps) Nothing = do -- ABS1/AABS1 for tables
|
||||
env <- scopeEnv scope
|
||||
let mk_val (_,tnk) = VMeta tnk env []
|
||||
let mk_val (_,tnk) = VMeta tnk []
|
||||
p_ty <- case tt of
|
||||
TRaw -> fmap mk_val $ newResiduation scope vtypePType
|
||||
TTyped ty -> do (ty, _) <- tcRho scope ty (Just vtypeType)
|
||||
@@ -214,9 +287,8 @@ tcRho scope (R rs) (Just ty) = do
|
||||
tcRho scope (P t l) mb_ty = do
|
||||
l_ty <- case mb_ty of
|
||||
Just ty -> return ty
|
||||
Nothing -> do env <- scopeEnv scope
|
||||
(i,tnk) <- newResiduation scope vtypeType
|
||||
return (VMeta tnk env [])
|
||||
Nothing -> do (i,tnk) <- newResiduation scope vtypeType
|
||||
return (VMeta tnk [])
|
||||
(t,t_ty) <- tcRho scope t (Just (VRecType [(l,l_ty)]))
|
||||
return (P t l,l_ty)
|
||||
tcRho scope (C t1 t2) mb_ty = do
|
||||
@@ -261,7 +333,7 @@ tcRho scope t@(EPatt min max p) mb_ty = do
|
||||
(scope,f,ty) <- case mb_ty of
|
||||
Nothing -> do env <- scopeEnv scope
|
||||
(i,tnk) <- newResiduation scope vtypeType
|
||||
return (scope,id,VMeta tnk env [])
|
||||
return (scope,id,VMeta tnk [])
|
||||
Just ty -> do (scope,f,ty) <- skolemise scope ty
|
||||
case ty of
|
||||
VPattType ty -> return (scope,f,ty)
|
||||
@@ -279,13 +351,16 @@ tcCases scope ((p,t):cs) p_ty mb_res_ty = do
|
||||
|
||||
tcApp scope t0 t@(App fun (ImplArg arg)) = do -- APP1
|
||||
(fun,fun_ty) <- tcApp scope t0 fun
|
||||
(bt, _, arg_ty, res_ty) <- unifyFun scope fun_ty
|
||||
(bt, x, arg_ty, res_ty) <- unifyFun scope fun_ty
|
||||
if (bt == Implicit)
|
||||
then return ()
|
||||
else evalError (ppTerm Unqualified 0 t <+> "is an implicit argument application, but no implicit argument is expected")
|
||||
(arg,_) <- tcRho scope arg (Just arg_ty)
|
||||
env <- scopeEnv scope
|
||||
varg <- eval env arg []
|
||||
res_ty <- case res_ty of
|
||||
VClosure res_env res_ty -> do env <- scopeEnv scope
|
||||
tnk <- newThunk env arg
|
||||
eval ((x,tnk):res_env) res_ty []
|
||||
res_ty -> return res_ty
|
||||
return (App fun (ImplArg arg), res_ty)
|
||||
tcApp scope t0 (App fun arg) = do -- APP2
|
||||
(fun,fun_ty) <- tcApp scope t0 fun
|
||||
@@ -349,8 +424,7 @@ tcPatt scope (PR rs) ty0 = do
|
||||
let mk_ltys [] = return []
|
||||
mk_ltys ((l,p):rs) = do (_,tnk) <- newResiduation scope vtypePType
|
||||
ltys <- mk_ltys rs
|
||||
env <- scopeEnv scope
|
||||
return ((l,p,VMeta tnk env []) : ltys)
|
||||
return ((l,p,VMeta tnk []) : ltys)
|
||||
go scope [] = return scope
|
||||
go scope ((l,p,ty):rs) = do scope <- tcPatt scope p ty
|
||||
go scope rs
|
||||
@@ -410,8 +484,8 @@ tcRecTypeFields scope ((l,ty):rs) mb_ty = do
|
||||
VSort s
|
||||
| s == cType -> return (Just sort)
|
||||
| s == cPType -> return mb_ty
|
||||
VMeta _ _ _ -> return mb_ty
|
||||
_ -> do sort <- zonkTerm =<< value2term (scopeVars scope) sort
|
||||
VMeta _ _ -> return mb_ty
|
||||
_ -> do sort <- value2term (scopeVars scope) sort
|
||||
evalError ("The record type field" <+> l <+> ':' <+> ppTerm Unqualified 0 ty $$
|
||||
"cannot be of type" <+> ppTerm Unqualified 0 sort)
|
||||
(rs,mb_ty) <- tcRecTypeFields scope rs mb_ty
|
||||
@@ -427,20 +501,20 @@ instSigma scope t ty1 (Just ty2) = do -- INST2
|
||||
|
||||
-- | Invariant: the second argument is in weak-prenex form
|
||||
subsCheckRho :: Scope s -> Term -> Sigma s -> Rho s -> EvalM s Term
|
||||
subsCheckRho scope t ty1@(VMeta i env vs) ty2 = do
|
||||
subsCheckRho scope t ty1@(VMeta i vs) ty2 = do
|
||||
mv <- getRef i
|
||||
case mv of
|
||||
Residuation _ _ _ -> do unify scope ty1 ty2
|
||||
return t
|
||||
Bound ty1 -> do vty1 <- eval env ty1 vs
|
||||
subsCheckRho scope t vty1 ty2
|
||||
subsCheckRho scope t ty1 ty2@(VMeta i env vs) = do
|
||||
Evaluated _ ty1 -> do ty1 <- apply ty1 vs
|
||||
subsCheckRho scope t ty1 ty2
|
||||
subsCheckRho scope t ty1 ty2@(VMeta i vs) = do
|
||||
mv <- getRef i
|
||||
case mv of
|
||||
Residuation _ _ _ -> do unify scope ty1 ty2
|
||||
return t
|
||||
Bound ty2 -> do vty2 <- eval env ty2 vs
|
||||
subsCheckRho scope t ty1 vty2
|
||||
Evaluated _ ty2 -> do ty2 <- apply ty2 vs
|
||||
subsCheckRho scope t ty1 ty2
|
||||
subsCheckRho scope t (VProd Implicit x ty1 ty2) rho2 = do -- Rule SPEC
|
||||
(i,tnk) <- newResiduation scope ty1
|
||||
ty2 <- case ty2 of
|
||||
@@ -551,7 +625,7 @@ unifyFun :: Scope s -> Rho s -> EvalM s (BindType, Ident, Sigma s, Rho s)
|
||||
unifyFun scope (VProd bt x arg res) =
|
||||
return (bt,x,arg,res)
|
||||
unifyFun scope tau = do
|
||||
let mk_val (_,tnk) = VMeta tnk [] []
|
||||
let mk_val (_,tnk) = VMeta tnk []
|
||||
arg <- fmap mk_val $ newResiduation scope vtypeType
|
||||
res <- fmap mk_val $ newResiduation scope vtypeType
|
||||
let bt = Explicit
|
||||
@@ -562,8 +636,7 @@ unifyTbl :: Scope s -> Rho s -> EvalM s (Sigma s, Rho s)
|
||||
unifyTbl scope (VTable arg res) =
|
||||
return (arg,res)
|
||||
unifyTbl scope tau = do
|
||||
env <- scopeEnv scope
|
||||
let mk_val (i,tnk) = VMeta tnk env []
|
||||
let mk_val (i,tnk) = VMeta tnk []
|
||||
arg <- fmap mk_val $ newResiduation scope vtypePType
|
||||
res <- fmap mk_val $ newResiduation scope vtypeType
|
||||
unify scope tau (VTable arg res)
|
||||
@@ -578,17 +651,30 @@ unify scope (VGen i vs1) (VGen j vs2)
|
||||
unify scope (VTable p1 res1) (VTable p2 res2) = do
|
||||
unify scope p1 p2
|
||||
unify scope res1 res2
|
||||
unify scope (VMeta i env1 vs1) (VMeta j env2 vs2)
|
||||
| i == j = sequence_ (zipWith (unifyThunk scope) vs1 vs2)
|
||||
| otherwise = do mv <- getRef j
|
||||
case mv of
|
||||
Bound t2 -> do v2 <- eval env2 t2 vs2
|
||||
unify scope (VMeta i env1 vs1) v2
|
||||
Residuation j _ _ -> setRef i (Bound (Meta j))
|
||||
unify scope (VMeta i vs1) (VMeta j vs2)
|
||||
| i == j = sequence_ (zipWith (unifyThunk scope) vs1 vs2)
|
||||
| otherwise = do
|
||||
mv <- getRef i
|
||||
case mv of
|
||||
Evaluated _ v1 -> do
|
||||
v1 <- apply v1 vs1
|
||||
unify scope v1 (VMeta j vs2)
|
||||
Residuation _ scope1 _ -> do
|
||||
mv <- getRef j
|
||||
case mv of
|
||||
Evaluated _ v2 -> do
|
||||
v2 <- apply v2 vs2
|
||||
unify scope (VMeta i vs1) v2
|
||||
Residuation _ scope2 _
|
||||
| m > n -> setRef i (Evaluated m (VMeta j vs2))
|
||||
| otherwise -> setRef j (Evaluated n (VMeta i vs2))
|
||||
where
|
||||
m = length scope1
|
||||
n = length scope2
|
||||
unify scope (VInt i) (VInt j)
|
||||
| i == j = return ()
|
||||
unify scope (VMeta i env vs) v = unifyVar scope i env vs v
|
||||
unify scope v (VMeta i env vs) = unifyVar scope i env vs v
|
||||
unify scope (VMeta i vs) v = unifyVar scope i vs v
|
||||
unify scope v (VMeta i vs) = unifyVar scope i vs v
|
||||
unify scope v1 v2 = do
|
||||
t1 <- value2term (scopeVars scope) v1
|
||||
t2 <- value2term (scopeVars scope) v2
|
||||
@@ -602,18 +688,78 @@ unifyThunk scope tnk1 tnk2 = do
|
||||
(Evaluated _ v1,Evaluated _ v2) -> unify scope v1 v2
|
||||
|
||||
-- | Invariant: tv1 is a flexible type variable
|
||||
unifyVar :: Scope s -> Thunk s -> Env s -> [Thunk s] -> Tau s -> EvalM s ()
|
||||
unifyVar scope tnk env vs ty2 = do -- Check whether i is bound
|
||||
unifyVar :: Scope s -> Thunk s -> [Thunk s] -> Tau s -> EvalM s ()
|
||||
unifyVar scope tnk vs ty2 = do -- Check whether i is bound
|
||||
mv <- getRef tnk
|
||||
case mv of
|
||||
Bound ty1 -> do v <- eval env ty1 vs
|
||||
unify scope v ty2
|
||||
Residuation i scope' _ -> do ty2' <- value2term (scopeVars scope') ty2
|
||||
ms2 <- getMetaVars [(scope,ty2)]
|
||||
if tnk `elem` ms2
|
||||
then evalError ("Occurs check for" <+> ppMeta i <+> "in:" $$
|
||||
nest 2 (ppTerm Unqualified 0 ty2'))
|
||||
else setRef tnk (Bound ty2')
|
||||
Evaluated _ ty1 -> do ty1 <- apply ty1 vs
|
||||
unify scope ty1 ty2
|
||||
Residuation i scope' _ -> do let m = length scope'
|
||||
n = length scope
|
||||
check m n ty2
|
||||
setRef tnk (Evaluated m ty2)
|
||||
where
|
||||
check m n (VApp f vs) = mapM_ (follow m n) vs
|
||||
check m n (VMeta i vs)
|
||||
| tnk == i = do ty1 <- value2term (scopeVars scope) (VMeta tnk vs)
|
||||
ty2 <- value2term (scopeVars scope) ty2
|
||||
evalError ("Occurs check for" <+> ppTerm Unqualified 0 ty1 <+> "in:" $$
|
||||
nest 2 (ppTerm Unqualified 0 ty2))
|
||||
| otherwise = do
|
||||
s <- getRef i
|
||||
case s of
|
||||
Evaluated _ v -> do v <- apply v vs
|
||||
check m n v
|
||||
_ -> mapM_ (follow m n) vs
|
||||
check m n (VGen i vs)
|
||||
| i > m = let (v,_) = reverse scope !! i
|
||||
in evalError ("Variable" <+> pp v <+> "has escaped")
|
||||
| otherwise = mapM_ (follow m n) vs
|
||||
check m n (VClosure env (Abs bt x t)) = do
|
||||
tnk <- newEvaluatedThunk (VGen n [])
|
||||
v <- eval ((x,tnk):env) t []
|
||||
check (m+1) (n+1) v
|
||||
check m n (VProd bt x ty1 ty2) = do
|
||||
check m n ty1
|
||||
case ty2 of
|
||||
VClosure env t -> do tnk <- newEvaluatedThunk (VGen n [])
|
||||
v <- eval ((x,tnk):env) t []
|
||||
check (m+1) (n+1) v
|
||||
_ -> check m n ty2
|
||||
check m n (VRecType as) =
|
||||
mapM_ (\(lbl,v) -> check m n v) as
|
||||
check m n (VR as) =
|
||||
mapM_ (\(lbl,tnk) -> follow m n tnk) as
|
||||
check m n (VP v l vs) =
|
||||
check m n v >> mapM_ (follow m n) vs
|
||||
check m n (VExtR v1 v2) =
|
||||
check m n v1 >> check m n v2
|
||||
check m n (VTable v1 v2) =
|
||||
check m n v1 >> check m n v2
|
||||
check m n (VT ty env cs) =
|
||||
check m n ty -- Traverse cs as well
|
||||
check m n (VV ty cs) =
|
||||
check m n ty >> mapM_ (follow m n) cs
|
||||
check m n (VS v1 tnk vs) =
|
||||
check m n v1 >> follow m n tnk >> mapM_ (follow m n) vs
|
||||
check m n (VSort _) = return ()
|
||||
check m n (VInt _) = return ()
|
||||
check m n (VFlt _) = return ()
|
||||
check m n (VStr _) = return ()
|
||||
check m n VEmpty = return ()
|
||||
check m n (VC v1 v2) =
|
||||
check m n v1 >> check m n v2
|
||||
check m n (VGlue v1 v2) =
|
||||
check m n v1 >> check m n v2
|
||||
check m n (VPatt _ _ _) = return ()
|
||||
check m n (VPattType v) =
|
||||
check m n v
|
||||
check m n (VAlts v vs) =
|
||||
check m n v >> mapM_ (\(v1,v2) -> check m n v1 >> check m n v2) vs
|
||||
check m n (VStrs vs) =
|
||||
mapM_ (check m n) vs
|
||||
|
||||
follow m n tnk = check m n =<< force tnk
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
-- Instantiation and quantification
|
||||
@@ -632,11 +778,11 @@ instantiate scope t ty = do
|
||||
|
||||
-- | Build fresh lambda abstractions for the topmost implicit arguments
|
||||
skolemise :: Scope s -> Sigma s -> EvalM s (Scope s, Term->Term, Rho s)
|
||||
skolemise scope ty@(VMeta i env vs) = do
|
||||
skolemise scope ty@(VMeta i vs) = do
|
||||
mv <- getRef i
|
||||
case mv of
|
||||
Residuation _ _ _ -> return (scope,id,ty) -- guarded constant?
|
||||
Bound ty -> do ty <- eval env ty vs
|
||||
Evaluated _ ty -> do ty <- apply ty vs
|
||||
skolemise scope ty
|
||||
skolemise scope (VProd Implicit x ty1 ty2) = do
|
||||
let v = newVar scope
|
||||
@@ -652,17 +798,112 @@ skolemise scope ty = do
|
||||
-- | Quantify over the specified type variables (all flexible)
|
||||
quantify :: Scope s -> Term -> [Thunk s] -> Rho s -> EvalM s (Term,Sigma s)
|
||||
quantify scope t tvs ty = do
|
||||
let used_bndrs = nub (bndrs ty) -- Avoid quantified type variables in use
|
||||
new_bndrs = take (length tvs) (allBinders \\ used_bndrs)
|
||||
env <- scopeEnv ([(v,vtypeType) | v <- new_bndrs]++scope)
|
||||
mapM_ (bind env) (zip tvs new_bndrs)
|
||||
let vty = foldr (\v -> VProd Implicit v vtypeType) ty new_bndrs
|
||||
return (foldr (Abs Implicit) t new_bndrs,vty)
|
||||
let m = length tvs
|
||||
n = length scope
|
||||
(used_bndrs,ty) <- check m n [] ty
|
||||
let new_bndrs = take m (allBinders \\ used_bndrs)
|
||||
mapM_ bind (zip3 [0..] tvs new_bndrs)
|
||||
let ty' = foldr (\ty -> VProd Implicit ty vtypeType) ty new_bndrs
|
||||
return (foldr (Abs Implicit) t new_bndrs,ty')
|
||||
where
|
||||
bind env (tnk, name) = setRef tnk (Bound (Vr name))
|
||||
bind (i, tnk, name) = setRef tnk (Evaluated (length scope) (VGen i []))
|
||||
|
||||
bndrs (VProd _ x v1 v2) = [x] ++ bndrs v1 ++ bndrs v2
|
||||
bndrs _ = []
|
||||
check m n xs (VApp f vs) = do
|
||||
(xs,vs) <- mapAccumM (follow m n) xs vs
|
||||
return (xs,VApp f vs)
|
||||
check m n xs (VMeta i vs) = do
|
||||
s <- getRef i
|
||||
case s of
|
||||
Evaluated _ v -> do v <- apply v vs
|
||||
check m n xs v
|
||||
_ -> do (xs,vs) <- mapAccumM (follow m n) xs vs
|
||||
return (xs,VMeta i vs)
|
||||
check m n st (VGen i vs)= do
|
||||
(st,vs) <- mapAccumM (follow m n) st vs
|
||||
return (st, VGen (m+i) vs)
|
||||
check m n st (VClosure env (Abs bt x t)) = do
|
||||
(st,env) <- mapAccumM (\st (x,tnk) -> follow m n st tnk >>= \(st,tnk) -> return (st,(x,tnk))) st env
|
||||
return (st,VClosure env (Abs bt x t))
|
||||
check m n xs (VProd bt x v1 v2) = do
|
||||
(xs,v1) <- check m n xs v1
|
||||
case v2 of
|
||||
VClosure env t -> do tnk <- newEvaluatedThunk (VGen n [])
|
||||
(st,env) <- mapAccumM (\xs (x,tnk) -> follow m n xs tnk >>= \(xs,tnk) -> return (xs,(x,tnk))) xs env
|
||||
return (x:xs,VProd bt x v1 (VClosure env t))
|
||||
v2 -> do (xs,v2) <- check m (n+1) xs v2
|
||||
return (x:xs,VProd bt x v1 v2)
|
||||
check m n xs (VRecType as) = do
|
||||
(xs,as) <- mapAccumM (\xs (l,v) -> check m n xs v >>= \(xs,v) -> return (xs,(l,v))) xs as
|
||||
return (xs,VRecType as)
|
||||
check m n xs (VR as) = do
|
||||
(xs,as) <- mapAccumM (\xs (lbl,tnk) -> follow m n xs tnk >>= \(xs,tnk) -> return (xs,(lbl,tnk))) xs as
|
||||
return (xs,VR as)
|
||||
check m n xs (VP v l vs) = do
|
||||
(xs,v) <- check m n xs v
|
||||
(xs,vs) <- mapAccumM (follow m n) xs vs
|
||||
return (xs,VP v l vs)
|
||||
check m n xs (VExtR v1 v2) = do
|
||||
(xs,v1) <- check m n xs v1
|
||||
(xs,v2) <- check m n xs v2
|
||||
return (xs,VExtR v1 v2)
|
||||
check m n xs (VTable v1 v2) = do
|
||||
(xs,v1) <- check m n xs v1
|
||||
(xs,v2) <- check m n xs v2
|
||||
return (xs,VTable v1 v2)
|
||||
check m n xs (VT ty env cs) = do
|
||||
(xs,ty) <- check m n xs ty
|
||||
(xs,env) <- mapAccumM (\xs (x,tnk) -> follow m n xs tnk >>= \(xs,tnk) -> return (xs,(x,tnk))) xs env
|
||||
return (xs,VT ty env cs)
|
||||
check m n xs (VV ty cs) = do
|
||||
(xs,ty) <- check m n xs ty
|
||||
(xs,cs) <- mapAccumM (follow m n) xs cs
|
||||
return (xs,VV ty cs)
|
||||
check m n xs (VS v1 tnk vs) = do
|
||||
(xs,v1) <- check m n xs v1
|
||||
(xs,tnk) <- follow m n xs tnk
|
||||
(xs,vs) <- mapAccumM (follow m n) xs vs
|
||||
return (xs,VS v1 tnk vs)
|
||||
check m n xs v@(VSort _) = return (xs,v)
|
||||
check m n xs v@(VInt _) = return (xs,v)
|
||||
check m n xs v@(VFlt _) = return (xs,v)
|
||||
check m n xs v@(VStr _) = return (xs,v)
|
||||
check m n xs v@VEmpty = return (xs,v)
|
||||
check m n xs (VC v1 v2) = do
|
||||
(xs,v1) <- check m n xs v1
|
||||
(xs,v2) <- check m n xs v2
|
||||
return (xs,VC v1 v2)
|
||||
check m n xs (VGlue v1 v2) = do
|
||||
(xs,v1) <- check m n xs v1
|
||||
(xs,v2) <- check m n xs v2
|
||||
return (xs,VGlue v1 v2)
|
||||
check m n xs v@(VPatt _ _ _) = return (xs,v)
|
||||
check m n xs (VPattType v) = do
|
||||
(xs,v) <- check m n xs v
|
||||
return (xs,VPattType v)
|
||||
check m n xs (VAlts v vs) = do
|
||||
(xs,v) <- check m n xs v
|
||||
(xs,vs) <- mapAccumM (\xs (v1,v2) -> do (xs,v1) <- check m n xs v1
|
||||
(xs,v2) <- check m n xs v2
|
||||
return (xs,(v1,v2)))
|
||||
xs vs
|
||||
return (xs,VAlts v vs)
|
||||
check m n xs (VStrs vs) = do
|
||||
(xs,vs) <- mapAccumM (check m n) xs vs
|
||||
return (xs,VStrs vs)
|
||||
check m n st v = error (showValue v)
|
||||
|
||||
follow m n st tnk = do
|
||||
v <- force tnk
|
||||
(st,v) <- check m n st v
|
||||
tnk <- newEvaluatedThunk v
|
||||
return (st,tnk)
|
||||
|
||||
mapAccumM :: Monad m => (a -> b -> m (a,c)) -> a -> [b] -> m (a,[c])
|
||||
mapAccumM f s [] = return (s,[])
|
||||
mapAccumM f s (x:xs) = do
|
||||
(s,y) <- f s x
|
||||
(s,ys) <- mapAccumM f s xs
|
||||
return (s,y:ys)
|
||||
|
||||
allBinders :: [Ident] -- a,b,..z, a1, b1,... z1, a2, b2,...
|
||||
allBinders = [ identS [x] | x <- ['a'..'z'] ] ++
|
||||
@@ -699,24 +940,35 @@ getMetaVars sc_tys = foldM (\acc (scope,ty) -> go ty acc) [] sc_tys
|
||||
follow acc tnk = force tnk >>= \v -> go v acc
|
||||
|
||||
-- Get the MetaIds from a term; no duplicates in result
|
||||
go (VSort s) acc = return acc
|
||||
go (VInt _) acc = return acc
|
||||
go (VRecType as) acc = foldM (\acc (lbl,v) -> go v acc) acc as
|
||||
go (VClosure _ _) acc = return acc
|
||||
go (VProd b x v1 v2) acc = go v2 acc >>= go v1
|
||||
go (VTable v1 v2) acc = go v2 acc >>= go v1
|
||||
go (VMeta m env args) acc
|
||||
| m `elem` acc = return acc
|
||||
| otherwise = do res <- getRef m
|
||||
case res of
|
||||
Bound _ -> return acc
|
||||
_ -> foldM follow (m:acc) args
|
||||
go (VApp f args) acc = foldM follow acc args
|
||||
go v acc = unimplemented ("go "++showValue v)
|
||||
go (VGen i args) acc = foldM follow acc args
|
||||
go (VSort s) acc = return acc
|
||||
go (VInt _) acc = return acc
|
||||
go (VRecType as) acc = foldM (\acc (lbl,v) -> go v acc) acc as
|
||||
go (VClosure _ _) acc = return acc
|
||||
go (VProd b x v1 v2) acc = go v2 acc >>= go v1
|
||||
go (VTable v1 v2) acc = go v2 acc >>= go v1
|
||||
go (VMeta m args) acc
|
||||
| m `elem` acc = return acc
|
||||
| otherwise = do res <- getRef m
|
||||
case res of
|
||||
Evaluated _ v -> go v acc
|
||||
_ -> foldM follow (m:acc) args
|
||||
go (VApp f args) acc = foldM follow acc args
|
||||
go v acc = unimplemented ("go "++showValue v)
|
||||
|
||||
-- | Eliminate any substitutions in a term
|
||||
zonkTerm :: Term -> EvalM s Term
|
||||
zonkTerm (Meta i) = do
|
||||
zonkTerm :: [Ident] -> Term -> EvalM s Term
|
||||
zonkTerm xs (Abs b x t) = do
|
||||
t <- zonkTerm (x:xs) t
|
||||
return (Abs b x t)
|
||||
zonkTerm xs (Prod b x t1 t2) = do
|
||||
t1 <- zonkTerm xs t1
|
||||
t2 <- zonkTerm xs' t2
|
||||
return (Prod b x t1 t2)
|
||||
where
|
||||
xs' | x == identW = xs
|
||||
| otherwise = x:xs
|
||||
zonkTerm xs (Meta i) = do
|
||||
tnk <- EvalM $ \gr k mt d r msgs ->
|
||||
case Map.lookup i mt of
|
||||
Just v -> k v mt d r msgs
|
||||
@@ -726,7 +978,5 @@ zonkTerm (Meta i) = do
|
||||
Hole _ -> return (Meta i)
|
||||
Residuation _ _ _ -> return (Meta i)
|
||||
Narrowing _ _ -> return (Meta i)
|
||||
Bound t -> do t <- zonkTerm t
|
||||
setRef tnk (Bound t) -- "Short out" multiple hops
|
||||
return t
|
||||
zonkTerm t = composOp zonkTerm t
|
||||
Evaluated _ v -> zonkTerm xs =<< value2term xs v
|
||||
zonkTerm xs t = composOp (zonkTerm xs) t
|
||||
|
||||
Reference in New Issue
Block a user