@@ -51,13 +51,17 @@ isType ctxt env tm = isType' (normalise ctxt env tm)
51 | otherwise = fail (showEnv env tm ++ " is not a Type")
51 | otherwise = fail (showEnv env tm ++ " is not a Type")
53recheck :: Context -> Env -> Raw -> Term -> TC (Term, Type, UCs)
53recheck :: Context -> Env -> Raw -> Term -> TC (Term, Type, UCs)
54+recheck = recheck_borrowing []
56+recheck_borrowing :: [Name] -> Context -> Env -> Raw -> Term ->
54−recheck ctxt env tm orig
58+recheck_borrowing bs ctxt env tm orig
55 = let v = next_tvar ctxt in
59 = let v = next_tvar ctxt in
56 case runStateT (check' False ctxt env tm) (v, []) of -- holes banned
60 case runStateT (check' False ctxt env tm) (v, []) of -- holes banned
57 Error (IncompleteTerm _) -> Error $ IncompleteTerm orig
61 Error (IncompleteTerm _) -> Error $ IncompleteTerm orig
58 Error e -> Error e
62 Error e -> Error e
59 OK ((tm, ty), constraints) ->
63 OK ((tm, ty), constraints) ->
60− do checkUnique ctxt env tm
64+ do checkUnique bs ctxt env tm
61 return (tm, ty, constraints)
65 return (tm, ty, constraints)
63check :: Context -> Env -> Raw -> TC (Term, Type)
67check :: Context -> Env -> Raw -> TC (Term, Type)
@@ -127,12 +131,14 @@ check' holes ctxt env top = chk env top where
127 when (not holes) $ put (v+1, ULE su (UVar v):ULE tu (UVar v):cs)
131 when (not holes) $ put (v+1, ULE su (UVar v):ULE tu (UVar v):cs)
128 return (Bind n (Pi (uniqueBinders (map fst env) sv))
132 return (Bind n (Pi (uniqueBinders (map fst env) sv))
129 (pToV n tv), TType (UVar v))
133 (pToV n tv), TType (UVar v))
130− (UType u, _) ->
134+ (u, u') ->
131− return (Bind n (Pi (uniqueBinders (map fst env) sv))
132− (pToV n tv), UType u)
134 return (Bind n (Pi (uniqueBinders (map fst env) sv))
135 return (Bind n (Pi (uniqueBinders (map fst env) sv))
135− (pToV n tv), UType u)
136+ (pToV n tv), smaller u u')
138+ where smaller (UType NullType) _ = UType NullType
139+ smaller _ (UType NullType) = UType NullType
140+ smaller (UType u) _ = UType u
141+ smaller _ (UType u) = UType u
136 chk env (RBind n b sc)
142 chk env (RBind n b sc)
137 = do b' <- checkBinder b
143 = do b' <- checkBinder b
138 (scv, sct) <- chk ((n, b'):env) sc
144 (scv, sct) <- chk ((n, b'):env) sc
@@ -217,29 +223,57 @@ check' holes ctxt env top = chk env top where
217 discharge n (PVTy t) scv sct
223 discharge n (PVTy t) scv sct
218 = return (Bind n (PVTy t) scv, sct)
224 = return (Bind n (PVTy t) scv, sct)
226+-- Number of times a name can be used
227+data UniqueUse = Never -- no more times
228+ | Once -- at most once more
229+ | LendOnly -- only under 'lend'
220-- If any binders are of kind 'UniqueType' or 'AllTypes' and the name appears
233-- If any binders are of kind 'UniqueType' or 'AllTypes' and the name appears
221-- in the scope more than once, this is an error.
234-- in the scope more than once, this is an error.
222−checkUnique :: Context -> Env -> Term -> TC ()
235+checkUnique :: [Name] -> Context -> Env -> Term -> TC ()
236+checkUnique borrowed ctxt env tm
223−checkUnique ctxt env tm = evalStateT (chkBinders env (explicitNames tm)) []
237+ = evalStateT (chkBinders env (explicitNames tm)) []
239+ isVar (P _ _ _) = True
225− chkBinders :: Env -> Term -> StateT [(Name, Bool)] TC ()
243+ chkBinders :: Env -> Term -> StateT [(Name, (UniqueUse, Universe))] TC ()
226 chkBinders env (V i) | length env > i = chkName (fst (env!!i))
244 chkBinders env (V i) | length env > i = chkName (fst (env!!i))
227 chkBinders env (P _ n _) = chkName n
245 chkBinders env (P _ n _) = chkName n
246+ -- 'lending' a unique or nulltype variable doesn't count as a use,
247+ -- but we still can't lend something that's already been used.
248+ chkBinders env (App (App (P _ (NS (UN lend) [owner]) _) t) a)
249+ | isVar a && owner == txt "Ownership" &&
250+ (lend == txt "lend" || lend == txt "Read")
251+ = do chkBinders env t -- Check the type normally
253+ -- Remove the 'LendOnly' names from the unusable set
254+ put (filter (\(n, (ok, _)) -> ok /= LendOnly) st)
256+ put st -- Reset the old state after checking the argument
228 chkBinders env (App f a) = do chkBinders env f; chkBinders env a
257 chkBinders env (App f a) = do chkBinders env f; chkBinders env a
229 chkBinders env (Bind n b t)
258 chkBinders env (Bind n b t)
230 = do chkBinderName env n b
259 = do chkBinderName env n b
231 chkBinders ((n, b) : env) t
260 chkBinders ((n, b) : env) t
232 chkBinders env t = return ()
261 chkBinders env t = return ()
234− chkBinderName :: Env -> Name -> Binder Term -> StateT [(Name, Bool)] TC ()
263+ chkBinderName :: Env -> Name -> Binder Term ->
264+ StateT [(Name, (UniqueUse, Universe))] TC ()
235 chkBinderName env n b
265 chkBinderName env n b
236 = do let rawty = forgetEnv (map fst env) (binderTy b)
266 = do let rawty = forgetEnv (map fst env) (binderTy b)
237 (_, kind) <- lift $ check ctxt env rawty -- FIXME: Cache in binder?
267 (_, kind) <- lift $ check ctxt env rawty -- FIXME: Cache in binder?
238 case kind of
268 case kind of
239 UType UniqueType -> do ns <- get
269 UType UniqueType -> do ns <- get
240− put ((n, False) : ns)
270+ if n `elem` borrowed
271+ then put ((n, (LendOnly, NullType)) : ns)
272+ else put ((n, (Once, UniqueType)) : ns)
273+ UType NullType -> do ns <- get
274+ put ((n, (LendOnly, NullType)) : ns)
241 UType AllTypes -> do ns <- get
275 UType AllTypes -> do ns <- get
242− put ((n, False) : ns)
276+ put ((n, (Once, AllTypes)) : ns)
243 _ -> return ()
277 _ -> return ()
244 chkBinders env (binderTy b)
278 chkBinders env (binderTy b)
245 case b of
279 case b of
@@ -250,6 +284,9 @@ checkUnique ctxt env tm = evalStateT (chkBinders env (explicitNames tm)) []
250 = do ns <- get
284 = do ns <- get
251 case lookup n ns of
285 case lookup n ns of
252 Nothing -> return ()
286 Nothing -> return ()
287+ Just (Many, k) -> return ()
253− Just True -> lift $ tfail (UniqueError n)
288+ Just (Never, k) -> lift $ tfail (UniqueError k n)
289+ Just (LendOnly, k) -> lift $ tfail (UniqueError k n)
290+ Just (Once, k) -> put ((n, (Never, k)) :
254− Just False -> put ((n, True) : filter (\x -> fst x /= n) ns)
291+ filter (\x -> fst x /= n) ns)