1
0
forked from GitHub/gf-core

test unification in TypeCheck

This commit is contained in:
aarne
2009-06-22 06:39:25 +00:00
parent c8027c8a4c
commit dc63402761

View File

@@ -21,7 +21,7 @@ import PGF.CId
import GF.Data.ErrM import GF.Data.ErrM
import qualified Data.Map as Map import qualified Data.Map as Map
import Control.Monad (liftM2) import Control.Monad (liftM2,foldM)
import Data.List (partition,sort,groupBy) import Data.List (partition,sort,groupBy)
import Debug.Trace import Debug.Trace
@@ -34,7 +34,7 @@ typecheck pgf e = case inferExpr pgf (newMetas e) of
inferExpr :: PGF -> Expr -> Err Expr inferExpr :: PGF -> Expr -> Err Expr
inferExpr pgf e = case infer pgf emptyTCEnv e of inferExpr pgf e = case infer pgf emptyTCEnv e of
Ok (e,_,cs) -> let (ms,cs2) = splitConstraints pgf cs in case cs2 of Ok (e,_,cs) -> let (ms,cs2) = splitConstraints pgf cs in case cs2 of
[] -> Ok (metaSubst ms e) [] -> trace (prConstraints cs ++"\n"++ show ms) $ Ok (metaSubst ms e)
_ -> Bad ("Error in tree " ++ showExpr e ++ " :\n " ++ prConstraints cs2) _ -> Bad ("Error in tree " ++ showExpr e ++ " :\n " ++ prConstraints cs2)
Bad s -> Bad s Bad s -> Bad s
@@ -117,6 +117,7 @@ prConstraints cs = unwords
-- work more on this: unification, compute,... -- work more on this: unification, compute,...
{-
splitConstraints :: PGF -> [(Value,Value)] -> ([(Int,Expr)],[(Value,Value)]) splitConstraints :: PGF -> [(Value,Value)] -> ([(Int,Expr)],[(Value,Value)])
splitConstraints pgf = mkSplit . partition isSubst . regroup . map reorder . map reduce where splitConstraints pgf = mkSplit . partition isSubst . regroup . map reorder . map reduce where
reorder (v,w) = case w of reorder (v,w) = case w of
@@ -134,6 +135,48 @@ splitConstraints pgf = mkSplit . partition isSubst . regroup . map reorder . map
VMeta _ _ -> all ((==u) . snd) cs VMeta _ _ -> all ((==u) . snd) cs
_ -> False _ -> False
mkSplit (ms,cs) = ([(i,value2expr v) | (VMeta i _,v):_ <- ms], concat cs) mkSplit (ms,cs) = ([(i,value2expr v) | (VMeta i _,v):_ <- ms], concat cs)
-}
splitConstraints :: PGF -> [(Value,Value)] -> ([(Int,Expr)],[(Value,Value)])
splitConstraints pgf = mkSplit . unifyAll [] . map reduce where
reduce (v,w) = (whnf v,whnf w)
whnf (VClosure env e) = eval (getFunEnv (abstract pgf)) env e -- should be removed when the typechecker is improved
whnf v = v
mkSplit (ms,cs) = ([(i,value2expr v) | (i,v) <- ms], cs)
unifyAll g [] = (g, [])
unifyAll g ((a@(s, t)) : l) =
let (g1, c) = unifyAll g l
in case unify s t g1 of
Just g2 -> (g2, c)
_ -> (g1, a : c)
unify e1 e2 g = case (e1, e2) of
(VMeta s _, t) -> do
let tg = substMetas g t
let sg = maybe e1 id (lookup s g)
if (sg == e1) then extend s tg g else unify sg tg g
(t, VMeta _ _) -> unify e2 e1 g
(VApp c as, VApp d bs) | c == d ->
foldM (\ h (a,b) -> unify a b h) g (zip as bs)
_ -> Nothing
extend s t g = case t of
VMeta u _ | u == s -> return g
_ | occCheck s t -> Nothing
_ -> return ((s, t) : g)
substMetas subst trm = case trm of
VMeta s _ -> maybe trm id (lookup s subst)
VApp c vs -> VApp c (map (substMetas subst) vs)
_ -> trm
occCheck s u = case u of
VMeta t _ -> s == t
VApp c as -> any (occCheck s) as
_ -> False
metaSubst :: [(Int,Expr)] -> Expr -> Expr metaSubst :: [(Int,Expr)] -> Expr -> Expr
metaSubst vs exp = case exp of metaSubst vs exp = case exp of