initCallableEnv :: (PP f, IsLocated f, Unif r)
                => AnnTc r -> TCEnv r -> f
                -> IOverloadSig r
                -> [Id (AnnTc r)]
                -> [Statement (AnnTc r)]
                -> TCM r (TCEnv r)
--------------------------------------------------------------------------------
initCallableEnv l γ f fty xs s = do
    locs      <- either fatal return (symEnv s)
    let nms1   = locs `mappend` nms0  -- favors first
    let nms    = envAddReturn f siRet nms1

    return     $ tcEnvAdds arg
               $ tcEnvAdds varBs
               $ tcEnvAdds tyBs
               $ TCE nms bnds ctx pth cha mut tThis (fId l)
  where

    (i, sig)   = fty
    (bs,xts,t) = sig

    nms0       = toFgn (envNames γ)
    siRet      = SI rSym Local ReturnVar t

    rSym       = returnSymbol
    tyBs       = [lsia α | α <- αs]
    varBs      = [(x, siw x t) | (x, t) <- safeZip "initCallableEnv" xs ts]
    arg        = [(getArgId (srcPos l), mkArgumentsSI l ts)]
    bnds       = envAdds [(s,t) | BTV s _ (Just t) <- bs] $ envBounds γ
    ctx        = pushContext i (envCtx γ)
    pth        = envPath γ
    cha        = envCHA γ
    mut        = envMut γ
    tThis      = envThis γ
    ts         = map b_type xts
    αs         = map btvToTV bs

    lsia x     = (Loc (srcPos l) x, sia x (tVar x))
    sia  x t   = SI (F.symbol x) Local Ambient    t
    siw  x t   = SI (F.symbol x) Local WriteLocal t


-- | `initClassCtorEnv` makes `this` a Unique binding
--------------------------------------------------------------------------------
initClassCt
initCallableEnv :: (PP f, IsLocated f, Unif r)
                => AnnTc r -> TCEnv r -> f
                -> IOverloadSig r
                -> [Id (AnnTc r)]
                -> [Statement (AnnTc r)]
                -> TCM r (TCEnv r)
initCallableEnv l γ f fty xs s = do
    locs      <- either fatal return (symEnv s)
    let nms1   = locs `mappend` nms0  -- favors first
    let nms    = envAddReturn f siRet nms1

    return     $ tcEnvAdds arg
               $ tcEnvAdds varBs
               $ tcEnvAdds tyBs
               $ TCE nms bnds ctx pth cha mut tThis (fId l)
  where

    (i, sig)   = fty
    (bs,xts,t) = sig

    nms0       = toFgn (envNames γ)
    siRet      = SI rSym Local ReturnVar t

    rSym       = returnSymbol
    tyBs       = [lsia α | α <- αs]
    varBs      = [(x, siw x t) | (x, t) <- safeZip "initCallableEnv" xs ts]
    arg        = [(getArgId (srcPos l), mkArgumentsSI l ts)]
    bnds       = envAdds [(s,t) | BTV s _ (Just t) <- bs] $ envBounds γ
    ctx        = pushContext i (envCtx γ)
    pth        = envPath γ
    cha        = envCHA γ
    mut        = envMut γ
    tThis      = envThis γ
    ts         = map b_type xts
    αs         = map btvToTV bs

    lsia x     = (Loc (srcPos l) x, sia x (tVar x))
    sia  x t   = SI (F.symbol x) Local Ambient    t
    siw  x t   = SI (F.symbol x) Local WriteLocal t


-- | `initClassCtorEnv` makes `this` a Unique binding
--------------------------------------------------------------------------------
initCallableEnv l γ f fty xs s = do
    locs      <- either fatal return (symEnv s)
    let nms1   = locs `mappend` nms0  -- favors first
    let nms    = envAddReturn f siRet nms1

    return     $ tcEnvAdds arg
               $ tcEnvAdds varBs
               $ tcEnvAdds tyBs
               $ TCE nms bnds ctx pth cha mut tThis (fId l)
  where

    (i, sig)   = fty
    (bs,xts,t) = sig

    nms0       = toFgn (envNames γ)
    siRet      = SI rSym Local ReturnVar t

    rSym       = returnSymbol
    tyBs       = [lsia α | α <- αs]
    varBs      = [(x, siw x t) | (x, t) <- safeZip "initCallableEnv" xs ts]
    arg        = [(getArgId (srcPos l), mkArgumentsSI l ts)]
    bnds       = envAdds [(s,t) | BTV s _ (Just t) <- bs] $ envBounds γ
    ctx        = pushContext i (envCtx γ)
    pth        = envPath γ
    cha        = envCHA γ
    mut        = envMut γ
    tThis      = envThis γ
    ts         = map b_type xts
    αs         = map btvToTV bs

    lsia x     = (Loc (srcPos l) x, sia x (tVar x))
    sia  x t   = SI (F.symbol x) Local Ambient    t
    siw  x t   = SI (F.symbol x) Local WriteLocal t


-- | `initClassCtorEnv` makes `this` a Unique binding
--------------------------------------------------------------------------------