letrec inference
This commit is contained in:
@@ -146,6 +146,8 @@ CaseAlt :: { Alter PsName (RlpExpr PsName) }
|
|||||||
LetE :: { RlpExpr PsName }
|
LetE :: { RlpExpr PsName }
|
||||||
: let layout1(Binding) in Expr
|
: let layout1(Binding) in Expr
|
||||||
{ Finr $ LetEF Core.NonRec $2 $4 }
|
{ Finr $ LetEF Core.NonRec $2 $4 }
|
||||||
|
| letrec layout1(Binding) in Expr
|
||||||
|
{ Finr $ LetEF Core.Rec $2 $4 }
|
||||||
|
|
||||||
Binding :: { Binding PsName (RlpExpr PsName) }
|
Binding :: { Binding PsName (RlpExpr PsName) }
|
||||||
: Pat '=' Expr { VarB $1 $3 }
|
: Pat '=' Expr { VarB $1 $3 }
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import Data.Monoid
|
|||||||
import Data.Text qualified as T
|
import Data.Text qualified as T
|
||||||
import Data.Foldable (fold)
|
import Data.Foldable (fold)
|
||||||
import Data.Function
|
import Data.Function
|
||||||
|
import Data.Foldable
|
||||||
import Data.Pretty hiding (annotate)
|
import Data.Pretty hiding (annotate)
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Data.Hashable
|
import Data.Hashable
|
||||||
@@ -108,30 +109,48 @@ gather' = \case
|
|||||||
let jxcs = jxs ^. each . constraints
|
let jxcs = jxs ^. each . constraints
|
||||||
& each . constraintTypes %~ substMap m
|
& each . constraintTypes %~ substMap m
|
||||||
as = foldr H.delete (je ^. assumptions) ks
|
as = foldr H.delete (je ^. assumptions) ks
|
||||||
j = mempty & constraints .~ (je ^. constraints <> jxcs <> cs)
|
j = mempty & constraints .~ je ^. constraints <> jxcs <> cs
|
||||||
& assumptions .~ as
|
& assumptions .~ foldOf (each . assumptions) jxs <> as
|
||||||
pure (te, fold jxs <> j)
|
pure (te, j)
|
||||||
|
|
||||||
-- Finr (LetEF NonRec [VarB (VarP k) x] e) -> do
|
Finr (LetEF Rec bs e) -> do
|
||||||
-- ((tx,jx),freeTvs) <- listenFreshTvNames $ gather x
|
let ks = bs ^.. each . singular _VarB . _1 . singular _VarP
|
||||||
-- let tx' = generalise freeTvs tx
|
(txs,txs',jxs) <- unzip3 <$> gatherBinds bs
|
||||||
|
let jxsa = foldOf (each . assumptions) jxs
|
||||||
|
jxcs <- fmap concat . for (ks `zip` txs) $ \ (k,t) ->
|
||||||
|
elimAssumptions' jxsa k t
|
||||||
|
(te,je) <- gather e
|
||||||
|
-- ... why don't we need the map?
|
||||||
|
(cs,_) <- fmap fold . for (ks `zip` txs') $ \ (k,t) ->
|
||||||
|
elimAssumptionsMap (je ^. assumptions) k t
|
||||||
|
let as = deleteKeys ks (je ^. assumptions <> jxsa)
|
||||||
|
j = mempty & constraints .~ je ^. constraints <> jxcs <> cs
|
||||||
|
& assumptions .~ as
|
||||||
|
pure (te,j)
|
||||||
|
|
||||||
|
-- Finr (LetEF Rec [VarB (VarP k) x] e) -> do
|
||||||
|
-- ((tx,jx),frees) <- listenFreshTvNames $ gather x
|
||||||
|
-- jxcs <- elimAssumptions' (jx ^. assumptions) k tx
|
||||||
|
-- let tx' = generalise frees tx
|
||||||
-- (te,je) <- gather e
|
-- (te,je) <- gather e
|
||||||
-- (cs,m) <- elimAssumptionsMap (je ^. assumptions) k tx'
|
-- (cs,m) <- elimAssumptionsMap (je ^. assumptions) k tx'
|
||||||
-- let jxcs = jx ^. constraints
|
-- let as = H.delete k (je ^. assumptions)
|
||||||
-- & each . constraintTypes %~ substMap m
|
-- <> H.delete k (jx ^. assumptions)
|
||||||
-- as = H.delete k (je ^. assumptions)
|
-- j = mempty & constraints .~ je ^. constraints <> jxcs <> cs
|
||||||
-- j = mempty & constraints .~ (je ^. constraints <> jxcs <> cs)
|
|
||||||
-- & assumptions .~ as
|
-- & assumptions .~ as
|
||||||
-- pure (te, jx <> j)
|
-- pure (te,j)
|
||||||
|
|
||||||
-- Finl (LamF [b] e) -> do
|
deleteKeys :: (Eq k, Hashable k) => [k] -> HashMap k v -> HashMap k v
|
||||||
-- tb <- freshTv
|
deleteKeys ks h = foldr H.delete h ks
|
||||||
-- (te,je) <- gather e
|
|
||||||
-- let cs = maybe [] (fmap $ Equality tb) (je ^. assumptions . at b)
|
gatherBinds :: [Binding PsName (RlpExpr PsName)]
|
||||||
-- as = je ^. assumptions & at b .~ Nothing
|
-> HM [( Type PsName
|
||||||
-- j = mempty & constraints .~ cs & assumptions .~ as
|
, Type PsName
|
||||||
-- t = tb :-> te
|
, PartialJudgement )]
|
||||||
-- pure (t,j)
|
gatherBinds bs = for bs $ \ (VarB (VarP k) x) -> do
|
||||||
|
((tx,jx),frees) <- listenFreshTvNames $ gather x
|
||||||
|
let tx' = generalise frees tx
|
||||||
|
pure (tx,tx',jx)
|
||||||
|
|
||||||
generaliseGatherBinds :: [Binding PsName (RlpExpr PsName)]
|
generaliseGatherBinds :: [Binding PsName (RlpExpr PsName)]
|
||||||
-> HM [(Type PsName, PartialJudgement)]
|
-> HM [(Type PsName, PartialJudgement)]
|
||||||
@@ -240,6 +259,7 @@ infer g0 e = do
|
|||||||
pure (csa <> cs)
|
pure (csa <> cs)
|
||||||
g <- unify cs'
|
g <- unify cs'
|
||||||
let sub t = ifoldrOf (reversed . assocs) subst t g
|
let sub t = ifoldrOf (reversed . assocs) subst t g
|
||||||
|
checkUndefinedVariables e'
|
||||||
pure $ e' & fmap (sub . view _1)
|
pure $ e' & fmap (sub . view _1)
|
||||||
& _extract %~ generaliseG g0
|
& _extract %~ generaliseG g0
|
||||||
where
|
where
|
||||||
@@ -247,6 +267,15 @@ infer g0 e = do
|
|||||||
-- the user-specified type: prioritise her.
|
-- the user-specified type: prioritise her.
|
||||||
unifyTypes _ s t = unify [Equality s t] $> s
|
unifyTypes _ s t = unify [Equality s t] $> s
|
||||||
|
|
||||||
|
checkUndefinedVariables
|
||||||
|
:: Cofree (RlpExprF PsName) (Type PsName, PartialJudgement)
|
||||||
|
-> HM ()
|
||||||
|
checkUndefinedVariables ((_,j) :< es)
|
||||||
|
= case j ^. assumptions of
|
||||||
|
[] -> checkUndefinedVariables `traverse_` es
|
||||||
|
as -> doErrs *> checkUndefinedVariables `traverse_` es
|
||||||
|
where doErrs = ifor as \n _ -> addWound $ TyErrUntypedVariable n
|
||||||
|
|
||||||
infer1 :: Context -> RlpExpr PsName -> HM (Type PsName)
|
infer1 :: Context -> RlpExpr PsName -> HM (Type PsName)
|
||||||
infer1 g = fmap extract . infer g
|
infer1 g = fmap extract . infer g
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user