shithub: MicroHs

Download patch

ref: b99cb952cda68ef05c83441bfab306be32c3f7ff
parent: 4bbd2e1708cb216e94efd7251ce18cff2bb04243
author: Lennart Augustsson <lennart.augustsson@epicgames.com>
date: Sun Nov 26 13:56:10 EST 2023

Handle constraint variables better.

--- a/lib/Data/Constraint.hs
+++ b/lib/Data/Constraint.hs
@@ -4,3 +4,6 @@
 -- A very, very minimal version of the constraints package
 
 data Dict (c :: Constraint) = c => Dict
+
+withDict :: forall (c :: Constraint) r . Dict c -> (c => r) -> r
+withDict Dict r = r
--- a/src/MicroHs/TypeCheck.hs
+++ b/src/MicroHs/TypeCheck.hs
@@ -551,12 +551,13 @@
 withDict :: forall a . HasCallStack => Ident -> EConstraint -> T a -> T a
 withDict i c ta = do
   c' <- expandSyn c >>= derefUVar
-  when (not (null (metaTvs [c']))) $ impossible
+  when (not (null (metaTvs [c']))) $
+    error (show c)
   case c' of
     (EApp (EApp (EVar eq) t1) t2) | eq == mkIdent nameTypeEq -> withEqDict i t1 t2 ta
     _ -> withInstDict i c' ta
 
-withInstDict :: forall a . Ident -> EConstraint -> T a -> T a
+withInstDict :: forall a . HasCallStack => Ident -> EConstraint -> T a -> T a
 withInstDict i c ta = do
   is <- gets instTable
   ics <- expandDict (EVar i) c
@@ -830,6 +831,9 @@
   put (seq n' $ TC mn n' fx tenv senv venv ast sub m cs is es ds)
   return n
 
+uniqIdentSep :: String
+uniqIdentSep = "$"
+
 newIdent :: SLoc -> String -> T Ident
 newIdent loc s = do
   u <- newUniq
@@ -1367,15 +1371,12 @@
 
 tCheckExpr :: HasCallStack =>
               EType -> Expr -> T Expr
-tCheckExpr t _e | Just (_ctx, _t') <- getImplies t = do
-  undefined
-{-
-  _ <- undefined -- XXX
-  u <- newUniq
-  let d = mkIdentSLoc (getSLoc e) ("adict$" ++ show u)
+tCheckExpr t e | Just (ctx, t') <- getImplies t = do
+--  error $ "tCheckExpr: " ++ show (e, ctx, t')
+  d <- newDictIdent (getSLoc e)
   e' <- withDict d ctx $ tCheckExpr t' e
   return $ eLam [EVar d] e'
--}
+
 tCheckExpr t e = tCheck tcExpr t e
 
 tGetRefType :: HasCallStack =>
@@ -1447,9 +1448,9 @@
 
     EApp f a -> do
       (f', ft) <- tInferExpr f
---      traceM $ "EApp f=" ++ showExpr f ++ "; e'=" ++ showExpr f' ++ " :: " ++ showEType ft
+--      traceM $ "EApp f=" ++ show f ++ "; f'=" ++ show f' ++ " :: " ++ show ft
       (at, rt) <- unArrow loc ft
---      traceM ("tcExpr EApp: " ++ showExpr f ++ " :: " ++ showEType ft)
+--      traceM ("tcExpr EApp: f=" ++ show f ++ " :: " ++ show ft ++ ", a=" ++ show a ++ " :: " ++ show at ++ " rt=" ++ show rt)
       a' <- checkSigma a at
       instSigma loc (EApp f' a') rt mt
 
@@ -1658,8 +1659,11 @@
 getFixity :: FixTable -> Ident -> Fixity
 getFixity fixs i = fromMaybe (AssocLeft, 9) $ M.lookup i fixs
 
+dictPrefix :: String
+dictPrefix = "adict"
+
 newDictIdent :: SLoc -> T Ident
-newDictIdent loc = newIdent loc "adict"
+newDictIdent loc = newIdent loc dictPrefix
 
 tcExprLam :: Expected -> [Eqn] -> T Expr
 tcExprLam mt qs = do
@@ -2176,7 +2180,7 @@
 -- Given a dictionary of a (constraint type), split it up
 --  * name components of a tupled constraint
 --  * name superclasses of a constraint
-expandDict :: Expr -> EConstraint -> T [InstDictC]
+expandDict :: HasCallStack => Expr -> EConstraint -> T [InstDictC]
 expandDict edict acn = do
   cn <- expandSyn acn
   let
@@ -2185,12 +2189,19 @@
     Just _ -> concat <$> mapM (\ (i, a) -> expandDict (mkTupleSel i (length args) `EApp` edict) a) (zip [0..] args)
     Nothing -> do
       ct <- gets classTable
-      let (iks, sups, _, _, fds) = fromMaybe impossible $ M.lookup iCls ct
-          vs = map idKindIdent iks
-          sub = zip vs args
-          sups' = map (subst sub) sups
-      insts <- concat <$> mapM (\ (i, sup) -> expandDict (EVar (mkSuperSel iCls i) `EApp` edict) sup) (zip [1 ..] sups')
-      return $ (edict, [], [], cn, fds) : insts
+      case M.lookup iCls ct of
+        Nothing -> do
+          -- if iCls a variable it's not in the class table, otherwise it's an error
+          when (isConIdent iCls) $
+            impossible
+          return [(edict, [], [], cn, [])]
+        Just (iks, sups, _, _, fds) -> do
+          let 
+            vs = map idKindIdent iks
+            sub = zip vs args
+            sups' = map (subst sub) sups
+          insts <- concat <$> mapM (\ (i, sup) -> expandDict (EVar (mkSuperSel iCls i) `EApp` edict) sup) (zip [1 ..] sups')
+          return $ (edict, [], [], cn, fds) : insts
 
 mkSuperSel :: HasCallStack =>
               Ident -> Int -> Ident
@@ -2399,7 +2410,7 @@
 getBestMatches :: [(Int, (Expr, [EConstraint]))] -> [(Expr, [EConstraint])]
 getBestMatches [] = []
 getBestMatches ams =
-  let (args, insts) = partition (\ (_, (EVar i, _)) -> "adict$" `isPrefixOf` unIdent i) ams
+  let (args, insts) = partition (\ (_, (EVar i, _)) -> (dictPrefix ++ uniqIdentSep) `isPrefixOf` unIdent i) ams
       pick ms =
         let b = minimum (map fst ms)         -- minimum substitution size
         in  [ ec | (s, ec) <- ms, s == b ]   -- pick out the smallest
--- a/tests/Dict.hs
+++ b/tests/Dict.hs
@@ -12,4 +12,6 @@
 dictInt = Dict
 
 main :: IO ()
-main = print $ facD dictInt 10
+main = do
+  print $ facD dictInt 10
+  print $ withDict dictInt (fac (11::Int))
--