mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-04-22 19:22:50 -06:00
some bug fixes in type check and solve
This commit is contained in:
@@ -25,8 +25,8 @@ abstract Imper = {
|
|||||||
|
|
||||||
Decl : (A : Typ) -> (Var A -> Stm) -> Stm ;
|
Decl : (A : Typ) -> (Var A -> Stm) -> Stm ;
|
||||||
Assign : (A : Typ) -> Var A -> Exp A -> Stm -> Stm ;
|
Assign : (A : Typ) -> Var A -> Exp A -> Stm -> Stm ;
|
||||||
While : Exp TInt -> Stm -> Stm -> Stm ;
|
While : Exp (TNum TInt) -> Stm -> Stm -> Stm ;
|
||||||
IfElse : Exp TInt -> Stm -> Stm -> Stm -> Stm ;
|
IfElse : Exp (TNum TInt) -> Stm -> Stm -> Stm -> Stm ;
|
||||||
Block : Stm -> Stm -> Stm ;
|
Block : Stm -> Stm -> Stm ;
|
||||||
Printf : (A : Typ) -> Exp A -> Stm -> Stm ;
|
Printf : (A : Typ) -> Exp A -> Stm -> Stm ;
|
||||||
Return : (A : Typ) -> Exp A -> Stm ;
|
Return : (A : Typ) -> Exp A -> Stm ;
|
||||||
|
|||||||
@@ -17,10 +17,13 @@ compute :: GFCGrammar -> Exp -> Err Exp
|
|||||||
compute = computeAbsTerm
|
compute = computeAbsTerm
|
||||||
|
|
||||||
computeAbsTerm :: GFCGrammar -> Exp -> Err Exp
|
computeAbsTerm :: GFCGrammar -> Exp -> Err Exp
|
||||||
computeAbsTerm gr = computeAbsTermIn gr []
|
computeAbsTerm gr = computeAbsTermIn (lookupAbsDef gr) []
|
||||||
|
|
||||||
computeAbsTermIn :: GFCGrammar -> [Ident] -> Exp -> Err Exp
|
--- a hack to make compute work on source grammar as well
|
||||||
computeAbsTermIn gr xs e = errIn ("computing" +++ prt e) $ compt xs e where
|
type LookDef = Ident -> Ident -> Err (Maybe Term)
|
||||||
|
|
||||||
|
computeAbsTermIn :: LookDef -> [Ident] -> Exp -> Err Exp
|
||||||
|
computeAbsTermIn lookd xs e = errIn ("computing" +++ prt e) $ compt xs e where
|
||||||
compt vv t = case t of
|
compt vv t = case t of
|
||||||
Prod x a b -> liftM2 (Prod x) (compt vv a) (compt (x:vv) b)
|
Prod x a b -> liftM2 (Prod x) (compt vv a) (compt (x:vv) b)
|
||||||
Abs x b -> liftM (Abs x) (compt (x:vv) b)
|
Abs x b -> liftM (Abs x) (compt (x:vv) b)
|
||||||
@@ -46,11 +49,12 @@ computeAbsTermIn gr xs e = errIn ("computing" +++ prt e) $ compt xs e where
|
|||||||
_ -> do
|
_ -> do
|
||||||
return $ mkAbs yy $ mkApp f aa'
|
return $ mkAbs yy $ mkApp f aa'
|
||||||
|
|
||||||
look (Q m f) = case lookupAbsDef gr m f of
|
look t = case t of
|
||||||
Ok (Just EData) -> Nothing -- canonical --- should always be QC
|
(Q m f) -> case lookd m f of
|
||||||
Ok md -> md
|
Ok (Just EData) -> Nothing -- canonical --- should always be QC
|
||||||
_ -> Nothing
|
Ok md -> md
|
||||||
look _ = Nothing
|
_ -> Nothing
|
||||||
|
_ -> Nothing
|
||||||
|
|
||||||
beta :: [Ident] -> Exp -> Exp
|
beta :: [Ident] -> Exp -> Exp
|
||||||
beta vv c = case c of
|
beta vv c = case c of
|
||||||
|
|||||||
@@ -101,6 +101,18 @@ qualifAnnotPar m t = case t of
|
|||||||
Con c -> QC m c
|
Con c -> QC m c
|
||||||
_ -> composSafeOp (qualifAnnotPar m) t
|
_ -> composSafeOp (qualifAnnotPar m) t
|
||||||
|
|
||||||
|
lookupAbsDef :: SourceGrammar -> Ident -> Ident -> Err (Maybe Term)
|
||||||
|
lookupAbsDef gr m c = errIn ("looking up absdef of" +++ prt c) $ do
|
||||||
|
mi <- lookupModule gr m
|
||||||
|
case mi of
|
||||||
|
ModMod mo -> do
|
||||||
|
info <- lookupInfo mo c
|
||||||
|
case info of
|
||||||
|
AbsFun _ (Yes t) -> return $ return t
|
||||||
|
AnyInd _ n -> lookupAbsDef gr n c
|
||||||
|
_ -> return Nothing
|
||||||
|
_ -> Bad $ prt m +++ "is not an abstract module"
|
||||||
|
|
||||||
|
|
||||||
lookupLincat :: SourceGrammar -> Ident -> Ident -> Err Type
|
lookupLincat :: SourceGrammar -> Ident -> Ident -> Err Type
|
||||||
lookupLincat gr m c | elem c [zIdent "String", zIdent "Int"] =
|
lookupLincat gr m c | elem c [zIdent "String", zIdent "Int"] =
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import Abstract
|
|||||||
import AbsCompute
|
import AbsCompute
|
||||||
import Refresh
|
import Refresh
|
||||||
import LookAbs
|
import LookAbs
|
||||||
|
import qualified Lookup ---
|
||||||
|
|
||||||
import TC
|
import TC
|
||||||
|
|
||||||
@@ -24,14 +25,14 @@ annotate gr exp = annotateIn gr [] exp Nothing
|
|||||||
justTypeCheck :: GFCGrammar -> Exp -> Val -> Err Constraints
|
justTypeCheck :: GFCGrammar -> Exp -> Val -> Err Constraints
|
||||||
justTypeCheck gr e v = do
|
justTypeCheck gr e v = do
|
||||||
(_,constrs0) <- checkExp (grammar2theory gr) (initTCEnv []) e v
|
(_,constrs0) <- checkExp (grammar2theory gr) (initTCEnv []) e v
|
||||||
constrs1 <- reduceConstraints gr 0 constrs0
|
constrs1 <- reduceConstraints (lookupAbsDef gr) 0 constrs0
|
||||||
return $ fst $ splitConstraints constrs1
|
return $ fst $ splitConstraints gr constrs1
|
||||||
|
|
||||||
-- type check in empty context, return the expression itself if valid
|
-- type check in empty context, return the expression itself if valid
|
||||||
checkIfValidExp :: GFCGrammar -> Exp -> Err Exp
|
checkIfValidExp :: GFCGrammar -> Exp -> Err Exp
|
||||||
checkIfValidExp gr e = do
|
checkIfValidExp gr e = do
|
||||||
(_,_,constrs0) <- inferExp (grammar2theory gr) (initTCEnv []) e
|
(_,_,constrs0) <- inferExp (grammar2theory gr) (initTCEnv []) e
|
||||||
constrs1 <- reduceConstraints gr 0 constrs0
|
constrs1 <- reduceConstraints (lookupAbsDef gr) 0 constrs0
|
||||||
ifNull (return e) (Bad . unwords . prConstrs) constrs1
|
ifNull (return e) (Bad . unwords . prConstrs) constrs1
|
||||||
|
|
||||||
annotateIn :: GFCGrammar -> Binds -> Exp -> Maybe Val -> Err Tree
|
annotateIn :: GFCGrammar -> Binds -> Exp -> Maybe Val -> Err Tree
|
||||||
@@ -45,7 +46,7 @@ annotateIn gr gamma exp = maybe (infer exp) (check exp) where
|
|||||||
env = initTCEnv gamma
|
env = initTCEnv gamma
|
||||||
theory = grammar2theory gr
|
theory = grammar2theory gr
|
||||||
aexp2treeC (a,c) = do
|
aexp2treeC (a,c) = do
|
||||||
c' <- reduceConstraints gr (length gamma) c
|
c' <- reduceConstraints (lookupAbsDef gr) (length gamma) c
|
||||||
aexp2tree (a,c')
|
aexp2tree (a,c')
|
||||||
|
|
||||||
-- invariant way of creating TCEnv from context
|
-- invariant way of creating TCEnv from context
|
||||||
@@ -53,34 +54,48 @@ initTCEnv gamma =
|
|||||||
(length gamma,[(x,VGen i x) | ((x,_),i) <- zip gamma [0..]], gamma)
|
(length gamma,[(x,VGen i x) | ((x,_),i) <- zip gamma [0..]], gamma)
|
||||||
|
|
||||||
-- process constraints after eqVal by computing by defs
|
-- process constraints after eqVal by computing by defs
|
||||||
reduceConstraints :: GFCGrammar -> Int -> Constraints -> Err Constraints
|
reduceConstraints :: LookDef -> Int -> Constraints -> Err Constraints
|
||||||
reduceConstraints gr i = liftM concat . mapM redOne where
|
reduceConstraints look i = liftM concat . mapM redOne where
|
||||||
redOne (u,v) = do
|
redOne (u,v) = do
|
||||||
u' <- computeVal gr u
|
u' <- computeVal look u
|
||||||
v' <- computeVal gr v
|
v' <- computeVal look v
|
||||||
eqVal i u' v'
|
eqVal i u' v'
|
||||||
|
|
||||||
computeVal :: GFCGrammar -> Val -> Err Val
|
computeVal :: LookDef -> Val -> Err Val
|
||||||
computeVal gr v = case v of
|
computeVal look v = case v of
|
||||||
VClos g@(_:_) e -> do
|
VClos g@(_:_) e -> do
|
||||||
e' <- compt (map fst g) e --- bindings of g in e?
|
e' <- compt (map fst g) e --- bindings of g in e?
|
||||||
whnf $ VClos g e'
|
whnf $ VClos g e'
|
||||||
|
{- ----
|
||||||
|
_ -> do ---- how to compute a Val, really??
|
||||||
|
e <- val2exp v
|
||||||
|
e' <- compt [] e
|
||||||
|
whnf $ vClos e'
|
||||||
|
-}
|
||||||
VApp f c -> liftM2 VApp (compv f) (compv c) >>= whnf
|
VApp f c -> liftM2 VApp (compv f) (compv c) >>= whnf
|
||||||
_ -> whnf v
|
_ -> whnf v
|
||||||
where
|
where
|
||||||
compt = computeAbsTermIn gr
|
compt = computeAbsTermIn look
|
||||||
compv = computeVal gr
|
compv = computeVal look
|
||||||
|
|
||||||
-- take apart constraints that have the form (? <> t), usable as solutions
|
-- take apart constraints that have the form (? <> t), usable as solutions
|
||||||
splitConstraints :: Constraints -> (Constraints,MetaSubst)
|
splitConstraints :: GFCGrammar -> Constraints -> (Constraints,MetaSubst)
|
||||||
splitConstraints cs = csmsu where
|
splitConstraints gr = splitConstraintsGen (lookupAbsDef gr)
|
||||||
|
|
||||||
|
splitConstraintsSrc :: Grammar -> Constraints -> (Constraints,MetaSubst)
|
||||||
|
splitConstraintsSrc gr = splitConstraintsGen (Lookup.lookupAbsDef gr)
|
||||||
|
|
||||||
|
splitConstraintsGen :: LookDef -> Constraints -> (Constraints,MetaSubst)
|
||||||
|
splitConstraintsGen look cs = csmsu where
|
||||||
|
|
||||||
csmsu = (nub [(a,b) | (a,b) <- csf1,a /= b],msf1)
|
csmsu = (nub [(a,b) | (a,b) <- csf1,a /= b],msf1)
|
||||||
(csf1,msf1) = unif (csf,msf) -- alternative: filter first
|
(csf1,msf1) = unif (csf,msf) -- alternative: filter first
|
||||||
(csf,msf) = foldr mkOne ([],[]) cs
|
(csf,msf) = foldr mkOne ([],[]) cs
|
||||||
|
|
||||||
csmsf = foldr mkOne ([],msu) csu
|
csmsf = foldr mkOne ([],msu) csu
|
||||||
(csu,msu) = unif (cs,[]) -- alternative: unify first
|
(csu,msu) = unif (cs1,[]) -- alternative: unify first
|
||||||
|
|
||||||
|
cs1 = errVal cs $ reduceConstraints look 0 cs
|
||||||
|
|
||||||
mkOne (u,v) = case (u,v) of
|
mkOne (u,v) = case (u,v) of
|
||||||
(VClos g (Meta m), v) | null g -> sub m v
|
(VClos g (Meta m), v) | null g -> sub m v
|
||||||
@@ -112,6 +127,9 @@ performMetaSubstNode subst n@(N (b,a,v,(c,m),s)) = let
|
|||||||
Meta m -> errVal e $ maybe (return e) val2expSafe $ lookup m subst
|
Meta m -> errVal e $ maybe (return e) val2expSafe $ lookup m subst
|
||||||
_ -> composSafeOp metaSubstExp e
|
_ -> composSafeOp metaSubstExp e
|
||||||
|
|
||||||
|
reduceConstraintsNode gr = changeConstrs red where
|
||||||
|
red cs = errVal cs $ reduceConstraints (lookupAbsDef gr) 0 cs
|
||||||
|
|
||||||
-- weak heuristic to narrow down menus; not used for TC. 15/11/2001
|
-- weak heuristic to narrow down menus; not used for TC. 15/11/2001
|
||||||
-- the age-old method from GF 0.9
|
-- the age-old method from GF 0.9
|
||||||
possibleConstraints :: GFCGrammar -> Constraints -> Bool
|
possibleConstraints :: GFCGrammar -> Constraints -> Bool
|
||||||
@@ -191,8 +209,7 @@ cont2val = type2val . cont2exp
|
|||||||
justTypeCheckSrc :: Grammar -> Exp -> Val -> Err Constraints
|
justTypeCheckSrc :: Grammar -> Exp -> Val -> Err Constraints
|
||||||
justTypeCheckSrc gr e v = do
|
justTypeCheckSrc gr e v = do
|
||||||
(_,constrs0) <- checkExp (grammar2theorySrc gr) (initTCEnv []) e v
|
(_,constrs0) <- checkExp (grammar2theorySrc gr) (initTCEnv []) e v
|
||||||
----- constrs1 <- reduceConstraints gr 0 constrs0
|
return $ fst $ splitConstraintsSrc gr constrs0
|
||||||
return $ fst $ splitConstraints constrs0
|
|
||||||
|
|
||||||
grammar2theorySrc :: Grammar -> Theory
|
grammar2theorySrc :: Grammar -> Theory
|
||||||
grammar2theorySrc gr (m,f) = case lookupFunTypeSrc gr m f of
|
grammar2theorySrc gr (m,f) = case lookupFunTypeSrc gr m f of
|
||||||
|
|||||||
@@ -264,12 +264,10 @@ customTermCommand =
|
|||||||
in
|
in
|
||||||
[tr | t <- generateTrees gr False cat 2 Nothing (Just t),
|
[tr | t <- generateTrees gr False cat 2 Nothing (Just t),
|
||||||
Ok tr <- [annotate gr $ MM.qualifTerm (absId g) t]])
|
Ok tr <- [annotate gr $ MM.qualifTerm (absId g) t]])
|
||||||
|
,(strCI "typecheck", \g t -> err (const [t]) (return . loc2tree)
|
||||||
,(strCI "typecheck", \g t -> let gr = grammar g in
|
(reCheckState (grammar g) (tree2loc t)))
|
||||||
err (const []) (return . const t)
|
|
||||||
(checkIfValidExp gr (tree2exp t)))
|
|
||||||
,(strCI "solve", \g t -> err (const [t]) (return . loc2tree)
|
,(strCI "solve", \g t -> err (const [t]) (return . loc2tree)
|
||||||
(uniqueRefinements (grammar g) (tree2loc t)))
|
(solveAll (grammar g) (tree2loc t)))
|
||||||
,(strCI "context", \g t -> err (const [t]) (return . loc2tree)
|
,(strCI "context", \g t -> err (const [t]) (return . loc2tree)
|
||||||
(contextRefinements (grammar g) (tree2loc t)))
|
(contextRefinements (grammar g) (tree2loc t)))
|
||||||
,(strCI "reindex", \g t -> let gr = grammar g in
|
,(strCI "reindex", \g t -> let gr = grammar g in
|
||||||
|
|||||||
@@ -187,10 +187,11 @@ refineWithTreeReal :: Bool -> CGrammar -> Tree -> Meta -> Action
|
|||||||
refineWithTreeReal der gr tree m state = do
|
refineWithTreeReal der gr tree m state = do
|
||||||
state' <- replaceSubTree tree state
|
state' <- replaceSubTree tree state
|
||||||
let cs0 = allConstrs state'
|
let cs0 = allConstrs state'
|
||||||
(cs,ms) = splitConstraints cs0
|
(cs,ms) = splitConstraints gr cs0
|
||||||
v = vClos $ tree2exp (bodyTree tree)
|
v = vClos $ tree2exp (bodyTree tree)
|
||||||
msubst = (m,v) : ms
|
msubst = (m,v) : ms
|
||||||
metaSubstRefinements gr msubst $ mapLoc (performMetaSubstNode msubst) state'
|
metaSubstRefinements gr msubst $
|
||||||
|
mapLoc (reduceConstraintsNode gr . performMetaSubstNode msubst) state'
|
||||||
|
|
||||||
-- without dep. types, no constraints, no grammar needed - simply: do
|
-- without dep. types, no constraints, no grammar needed - simply: do
|
||||||
-- testErr (actIsMeta state) "move pointer to meta"
|
-- testErr (actIsMeta state) "move pointer to meta"
|
||||||
@@ -339,12 +340,13 @@ reCheckState gr st = annotate gr (tree2exp (loc2tree st)) >>= return . tree2loc
|
|||||||
|
|
||||||
-- extract metasubstitutions from constraints and solve them
|
-- extract metasubstitutions from constraints and solve them
|
||||||
solveAll :: CGrammar -> State -> Err State
|
solveAll :: CGrammar -> State -> Err State
|
||||||
solveAll gr st0 = do
|
solveAll gr st = solve st >>= solve where
|
||||||
st <- reCheckState gr st0
|
solve st0 = do ---- why need twice?
|
||||||
let cs0 = allConstrs st
|
st <- reCheckState gr st0
|
||||||
(cs,ms) = splitConstraints cs0
|
let cs0 = allConstrs st
|
||||||
metaSubstRefinements gr ms $ mapLoc (performMetaSubstNode ms) st
|
(cs,ms) = splitConstraints gr cs0
|
||||||
|
metaSubstRefinements gr ms $
|
||||||
|
mapLoc (reduceConstraintsNode gr . performMetaSubstNode ms) st
|
||||||
|
|
||||||
-- active refinements
|
-- active refinements
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user