diff options
Diffstat (limited to 'src-3.0/GF/Devel/Grammar/Lookup.hs')
| -rw-r--r-- | src-3.0/GF/Devel/Grammar/Lookup.hs | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/src-3.0/GF/Devel/Grammar/Lookup.hs b/src-3.0/GF/Devel/Grammar/Lookup.hs new file mode 100644 index 000000000..689996760 --- /dev/null +++ b/src-3.0/GF/Devel/Grammar/Lookup.hs @@ -0,0 +1,168 @@ +module GF.Devel.Grammar.Lookup where + +import GF.Devel.Grammar.Grammar +import GF.Devel.Grammar.Construct +import GF.Devel.Grammar.Macros +import GF.Devel.Grammar.PrGF +import GF.Infra.Ident + +import GF.Data.Operations + +import Control.Monad (liftM) +import Data.Map +import Data.List (sortBy) ---- + +-- look up fields for a constant in a grammar + +lookupJField :: (Judgement -> a) -> GF -> Ident -> Ident -> Err a +lookupJField field gf m c = do + j <- lookupJudgement gf m c + return $ field j + +lookupJForm :: GF -> Ident -> Ident -> Err JudgementForm +lookupJForm = lookupJField jform + +-- the following don't (need to) check that the jment form is adequate + +lookupCatContext :: GF -> Ident -> Ident -> Err Context +lookupCatContext gf m c = do + ty <- lookupJField jtype gf m c + return $ contextOfType ty + +lookupFunType :: GF -> Ident -> Ident -> Err Term +lookupFunType = lookupJField jtype + +lookupLin :: GF -> Ident -> Ident -> Err Term +lookupLin = lookupJField jdef + +lookupLincat :: GF -> Ident -> Ident -> Err Term +lookupLincat = lookupJField jtype + +lookupOperType :: GF -> Ident -> Ident -> Err Term +lookupOperType gr m c = do + ju <- lookupJudgement gr m c + case jform ju of + JParam -> return typePType + _ -> case jtype ju of + Meta _ -> fail ("no type given to " ++ prIdent m ++ "." ++ prIdent c) + ty -> return ty +---- can't be just lookupJField jtype + +lookupOperDef :: GF -> Ident -> Ident -> Err Term +lookupOperDef = lookupJField jdef + +lookupOverload :: GF -> Ident -> Ident -> Err [([Type],(Type,Term))] +lookupOverload gr m c = do + tr <- lookupJField jdef gr m c + case tr of + Overload tysts -> return + [(lmap snd args,(val,tr)) | (ty,tr) <- tysts, let (args,val) = prodForm ty] + _ -> Bad $ prt c +++ "is not an overloaded operation" + +lookupParams :: GF -> Ident -> Ident -> Err [(Ident,Context)] +lookupParams gf m c = do + EParam _ ty <- lookupJField jdef gf m c + return ty + +lookupParamConstructor :: GF -> Ident -> Ident -> Err Type +lookupParamConstructor = lookupJField jtype + +lookupParamValues :: GF -> Ident -> Ident -> Err [Term] +lookupParamValues gf m c = do + ps <- lookupParams gf m c + liftM concat $ mapM mkPar ps + where + mkPar (f,co) = do + vs <- liftM combinations $ mapM (\ (_,ty) -> allParamValues gf ty) co + return $ lmap (mkApp (QC m f)) vs + +lookupFlags :: GF -> Ident -> [(Ident,String)] +lookupFlags gf m = errVal [] $ do + mo <- lookupModule gf m + return $ toList $ mflags mo + +allParamValues :: GF -> Type -> Err [Term] +allParamValues cnc ptyp = case ptyp of + App (Q (IC "Predef") (IC "Ints")) (EInt n) -> + return [EInt i | i <- [0..n]] + QC p c -> lookupParamValues cnc p c + Q p c -> lookupParamValues cnc p c ---- + + RecType r -> do + let (ls,tys) = unzip $ sortByFst r + tss <- mapM allPV tys + return [R (zipAssign ls ts) | ts <- combinations tss] + _ -> prtBad "cannot find parameter values for" ptyp + where + allPV = allParamValues cnc + -- to normalize records and record types + sortByFst = sortBy (\ x y -> compare (fst x) (fst y)) + +abstractOfConcrete :: GF -> Ident -> Err Ident +abstractOfConcrete gf m = do + mo <- lookupModule gf m + case mtype mo of + MTConcrete a -> return a + MTInstance a -> return a + MTGrammar -> return m + _ -> prtBad "not concrete module" m + +allOrigJudgements :: GF -> Ident -> [(Ident,Judgement)] +allOrigJudgements gf m = errVal [] $ do + mo <- lookupModule gf m + return [ju | ju@(_,j) <- listJudgements mo, jform j /= JLink] + +allConcretes :: GF -> Ident -> [Ident] +allConcretes gf m = + [c | (c,mo) <- toList (gfmodules gf), mtype mo == MTConcrete m] + +-- | select just those modules that a given one depends on, including itself +partOfGrammar :: GF -> (Ident,Module) -> GF +partOfGrammar gr (i,mo) = gr { + gfmodules = fromList [m | m@(j,_) <- mos, elem j modsFor] + } + where + mos = toList $ gfmodules gr + modsFor = i : allDepsModule gr mo + +allDepsModule :: GF -> Module -> [Ident] +allDepsModule gr m = iterFix add os0 where + os0 = depPathModule m + add os = [m | o <- os, Just n <- [llookup o mods], m <- depPathModule n] + mods = toList $ gfmodules gr + +-- | initial dependency list +depPathModule :: Module -> [Ident] +depPathModule mo = fors ++ lmap fst (mextends mo) ++ lmap snd (mopens mo) where + fors = case mtype mo of + MTConcrete i -> [i] + MTInstance i -> [i] + _ -> [] + +-- infrastructure for lookup + +lookupModule :: GF -> Ident -> Err Module +lookupModule gf m = do + maybe (raiseIdent "module not found:" m) return $ mlookup m (gfmodules gf) + +-- this finds the immediate definition, which can be a link +lookupIdent :: GF -> Ident -> Ident -> Err Judgement +lookupIdent gf m c = do + mo <- lookupModule gf m + maybe (raiseIdent "constant not found:" c) return $ mlookup c (mjments mo) + +-- this follows the link +lookupJudgement :: GF -> Ident -> Ident -> Err Judgement +lookupJudgement gf m c = do + ju <- lookupIdent gf m c + case jform ju of + JLink -> lookupJudgement gf (jlink ju) c + _ -> return ju + +mlookup = Data.Map.lookup + +raiseIdent msg i = raise (msg +++ prIdent i) + +lmap = Prelude.map +llookup = Prelude.lookup + |
