ref: a6ae2c8e86ad0a1d3e89b470ac3bd846ccc937a2
parent: 0e97b2fe95f3096fbda442b3f72ad3e8b1c3921f
author: Lennart Augustsson <lennart.augustsson@epicgames.com>
date: Fri Oct 20 06:50:39 EDT 2023
Use an IdentMap for instances.
--- a/src/MicroHs/IdentMap.hs
+++ b/src/MicroHs/IdentMap.hs
@@ -6,7 +6,13 @@
--
module MicroHs.IdentMap(
Map,
- insert, fromListWith, fromList, lookup, empty, elems, size, toList, delete,
+ empty,
+ insertWith, insert,
+ fromListWith, fromList,
+ delete,
+ lookup,
+ size,
+ toList, elems,
) where
import Prelude --Xhiding(lookup)
import MicroHs.Ident
--- a/src/MicroHs/TypeCheck.hs
+++ b/src/MicroHs/TypeCheck.hs
@@ -61,7 +61,7 @@
type FixTable = M.Map Fixity -- precedence and associativity of operators
type AssocTable = M.Map [Ident] -- maps a type identifier to its associated construcors/selectors/methods
type ClassTable = M.Map ([IdKind], [EConstraint], [Ident]) -- super classes, instance names
-type Instances = [InstDict]
+type InstTable = M.Map [InstDict] -- indexed by class name
type Constraints= [(Ident, EConstraint)]
type InstDict = (Expr, [IdKind], [EConstraint], EConstraint)
@@ -262,6 +262,15 @@
ECon c -> conIdent c
_ -> impossible
+-- Approximate equality for dictionaries.
+-- The important thing is to avoid exact duplicates in the instance table.
+eqInstDict :: InstDict -> InstDict -> Bool
+eqInstDict (EVar i, _, _, _) (EVar i', _, _, _) | i == i' = True
+eqInstDict _ _ = False
+
+getInstCon :: InstDict -> Ident
+getInstCon (_, _, _, t) = getAppCon t
+
--------------------------
type Typed a = (a, EType)
@@ -277,7 +286,7 @@
(IM.IntMap EType) -- mapping from unique id to type
TCMode -- pattern, value, or type
ClassTable -- class info, indexed by QIdent
- Instances -- instances
+ InstTable -- instances
Constraints -- constraints that have to be solved
--Xderiving (Show)
@@ -311,7 +320,7 @@
tcMode :: TCState -> TCMode
tcMode (TC _ _ _ _ _ _ _ _ m _ _ _) = m
-instances :: TCState -> Instances
+instances :: TCState -> InstTable
instances (TC _ _ _ _ _ _ _ _ _ _ is _) = is
constraints :: TCState -> Constraints
@@ -342,8 +351,8 @@
TC mn n fx tenv senv venv ast sub _ cs is es <- get
put (TC mn n fx tenv senv venv ast sub m cs is es)
-putInstances :: Instances -> T ()
-putInstances is = T.do
+putInstTable :: InstTable -> T ()
+putInstTable is = T.do
TC mn n fx tenv senv venv ast sub m cs _ es <- get
put (TC mn n fx tenv senv venv ast sub m cs is es)
@@ -380,10 +389,10 @@
TC mn n fx tt st vt ast sub m cs is es <- get
put $ TC mn n fx tt st vt ast sub m (M.insert i x cs) is es
-addInstances :: [InstDict] -> T ()
-addInstances ics = T.do
+addInstTable :: [InstDict] -> T ()
+addInstTable ics = T.do
is <- gets instances
- putInstances (ics ++ is)
+ putInstTable $ foldr (\ ic -> M.insertWith (unionBy eqInstDict) (getInstCon ic) [ic]) is ics
addConstraint :: String -> (Ident, EConstraint) -> T ()
addConstraint _msg e@(_d, _ctx) = T.do
@@ -395,9 +404,9 @@
withDict i c ta = T.do
is <- gets instances
ics <- expandDict (EVar i) c
- addInstances ics
+ addInstTable ics
a <- ta
- putInstances is
+ putInstTable is
T.return a
-- XXX handle imports
@@ -407,7 +416,7 @@
let
xts = foldr (uncurry M.insert) ts primTypes
xvs = foldr (uncurry M.insert) vs primValues
- in TC mn 1 fs xts ss xvs as IM.empty TCExpr M.empty [] []
+ in TC mn 1 fs xts ss xvs as IM.empty TCExpr M.empty M.empty []
kTypeS :: EType
kTypeS = kType
@@ -989,12 +998,20 @@
usup []
-}
+addConstraints :: [EConstraint] -> EType -> EType
+addConstraints [] t = t
+addConstraints [c] t = c `tImplies` t
+addConstraints cs t = tupleConstraints cs `tImplies` t
+
+tupleConstraints :: [EConstraint] -> EConstraint
+tupleConstraints cs = tApps (tupleConstr noSLoc (length cs)) cs
+
expandInst :: EDef -> T [EDef]
expandInst dinst@(Instance vks ctx cc bs) = T.do
let loc = getSLocExpr cc
iCls = getAppCon cc
iInst <- newIdent loc "inst"
- let sign = Sign iInst (eForall vks cc)
+ let sign = Sign iInst (eForall vks $ addConstraints ctx cc)
(e, _) <- tLookupV iCls
ct <- gets classTable
let qiCls = getAppCon e
@@ -1016,7 +1033,7 @@
args = sups ++ meths
let bind = Fcn iInst [Eqn [] $ EAlts [([], foldl EApp (EVar $ mkClassConstructor iCls) args)] bs']
mn <- gets moduleName
- addInstances [(EVar $ qualIdent mn iInst, vks, ctx, cc)]
+ addInstTable [(EVar $ qualIdent mn iInst, vks, ctx, cc)]
T.return [dinst, sign, bind]
expandInst d = T.return [d]
@@ -1458,6 +1475,7 @@
T.return (ELam ps er)
tcEqns :: EType -> [Eqn] -> T [Eqn]
+--tcEqns t eqns | trace ("tcEqns: " ++ showEBind (BFcn dummyIdent eqns) ++ " :: " ++ showEType t) False = undefinedtcEqns t eqns | Just (ctx, t') <- getImplies t = T.do
let loc = getSLocEqns eqns
d <- newIdent loc "adict"
@@ -1850,11 +1868,12 @@
if null cs then
T.return []
else T.do
--- traceM "solveConstraints"
+ traceM "solveConstraints"
cs' <- T.mapM (\ (i,t) -> T.do { t' <- derefUVar t; T.return (i,t') }) cs--- traceM ("constraints:\n" ++ unlines (map (\ (i, t) -> showIdent i ++ " :: " ++ showExpr t) cs'))- is <- gets instances
--- traceM ("instances:\n" ++ unlines (map (\ (i, _, _, t) -> showExpr i ++ " :: " ++ showExpr t) is))+ traceM ("constraints:\n" ++ unlines (map (\ (i, t) -> showIdent i ++ " :: " ++ showExpr t) cs'))+ it <- gets instances
+ let instsOf c = fromMaybe [] $ M.lookup c it
+ traceM ("instances:\n" ++ unlines (map (\ (i, _, _, t) -> showExpr i ++ " :: " ++ showExpr t) (concat $ M.elems it)))let solve :: [(Ident, EType)] -> [(Ident, EType)] -> [(Ident, Expr)] -> T ([(Ident, EType)], [(Ident, Expr)])
solve [] uns sol = T.return (uns, sol)
solve (cns@(di, ct) : cnss) uns sol = T.do
@@ -1865,14 +1884,14 @@
goals <- T.mapM (\ c -> T.do { d <- newIdent loc "dict"; T.return (d, c) }) ctssolve (goals ++ cnss) uns ((di, ETuple (map (EVar . fst) goals)) : sol)
Nothing ->
- case [ de | (de, [], [], t) <- is, eqEType ct t ] of
+ case [ de | (de, [], [], t) <- instsOf iCls, eqEType ct t ] of
[] -> solve cnss (cns : uns) sol
[de] -> solve cnss uns ((di, de) : sol)
_ -> tcError loc $ "Multiple constraint solutions for: " ++ showEType ct
(unsolved, solved) <- solve cs' [] []
putConstraints unsolved
--- traceM ("solved:\n" ++ unlines [ showIdent i ++ " = " ++ showExpr e | (i, e) <- solved ])--- traceM ("unsolved:\n" ++ unlines [ showIdent i ++ " :: " ++ showEType t | (i, t) <- unsolved ])+ traceM ("solved:\n" ++ unlines [ showIdent i ++ " = " ++ showExpr e | (i, e) <- solved ])+ traceM ("unsolved:\n" ++ unlines [ showIdent i ++ " :: " ++ showEType t | (i, t) <- unsolved ])T.return solved
-- Check that there are no unsolved constraints.
--
⑨