1
0
forked from GitHub/gf-core

hopefully complete and correct typechecker in PGF

This commit is contained in:
krasimir
2009-09-06 20:31:52 +00:00
parent 26367d6a1e
commit 54dbfeef48
18 changed files with 914 additions and 492 deletions

View File

@@ -32,6 +32,7 @@ import GF.Command.TreeOperations ---- temporary place for typecheck and compute
import GF.Data.Operations
import GF.Text.Coding
import Data.List
import Data.Maybe
import qualified Data.Map as Map
import System.Cmd
@@ -283,7 +284,7 @@ allCommands cod env@(pgf, mos) = Map.fromList [
_ | isOpt "changes" opts -> changesMsg
_ | isOpt "coding" opts -> codingMsg
_ | isOpt "license" opts -> licenseMsg
[t] -> let co = getCommandOp (showExpr t) in
[t] -> let co = getCommandOp (showExpr [] t) in
case lookCommand co (allCommands cod env) of ---- new map ??!!
Just info -> commandHelp True (co,info)
_ -> "command not found"
@@ -615,23 +616,29 @@ allCommands cod env@(pgf, mos) = Map.fromList [
],
exec = \opts arg -> do
case arg of
[EVar id] -> case Map.lookup id (funs (abstract pgf)) of
[EFun id] -> case Map.lookup id (funs (abstract pgf)) of
Just (ty,_,eqs) -> return $ fromString $
render (text "fun" <+> text (prCId id) <+> colon <+> ppType 0 ty $$
render (text "fun" <+> text (prCId id) <+> colon <+> ppType 0 [] ty $$
if null eqs
then empty
else text "def" <+> vcat [text (prCId id) <+> hsep (map (ppPatt 9) patts) <+> char '=' <+> ppExpr 0 res | Equ patts res <- eqs])
else text "def" <+> vcat [let (scope,ds) = mapAccumL (ppPatt 9) [] patts
in text (prCId id) <+> hsep ds <+> char '=' <+> ppExpr 0 scope res | Equ patts res <- eqs])
Nothing -> case Map.lookup id (cats (abstract pgf)) of
Just hyps -> do return $ fromString $
render (text "cat" <+> text (prCId id) <+> hsep (map ppHypo hyps) $$
render (text "cat" <+> text (prCId id) <+> hsep (snd (mapAccumL ppHypo [] hyps)) $$
if null (functionsToCat pgf id)
then empty
else space $$
text "fun" <+> vcat [text (prCId fid) <+> colon <+> ppType 0 ty
text "fun" <+> vcat [text (prCId fid) <+> colon <+> ppType 0 [] ty
| (fid,ty) <- functionsToCat pgf id])
Nothing -> do putStrLn "unknown identifier"
return void
_ -> do putStrLn "a single identifier is expected from the command"
[e] -> case inferExpr pgf e of
Left tcErr -> error $ render (ppTcError tcErr)
Right (e,ty) -> do putStrLn ("Expression: "++showExpr [] e)
putStrLn ("Type: "++showType [] ty)
return void
_ -> do putStrLn "a single identifier or expression is expected from the command"
return void
})
]
@@ -689,7 +696,9 @@ allCommands cod env@(pgf, mos) = Map.fromList [
optType opts =
let str = valStrOpts "cat" (prCId $ lookStartCat pgf) opts
in case readType str of
Just ty -> ty
Just ty -> case checkType pgf ty of
Left tcErr -> error $ render (ppTcError tcErr)
Right ty -> ty
Nothing -> error ("Can't parse '"++str++"' as type")
optComm opts = valStrOpts "command" "" opts
optViewFormat opts = valStrOpts "format" "png" opts
@@ -710,10 +719,10 @@ allCommands cod env@(pgf, mos) = Map.fromList [
returnFromExprs es = return $ case es of
[] -> ([], "no trees found")
_ -> (es,unlines (map showExpr es))
_ -> (es,unlines (map (showExpr []) es))
prGrammar opts
| isOpt "cats" opts = return $ fromString $ unwords $ map showType $ categories pgf
| isOpt "cats" opts = return $ fromString $ unwords $ map (showType []) $ categories pgf
| isOpt "fullform" opts = return $ fromString $ concatMap (prFullFormLexicon . morpho) $ optLangs opts
| isOpt "missing" opts = return $ fromString $ unlines $ [unwords (prCId la:":": map prCId cs) |
la <- optLangs opts, let cs = missingLins pgf la]
@@ -739,7 +748,7 @@ allCommands cod env@(pgf, mos) = Map.fromList [
showAsString t = case t of
ELit (LStr s) -> s
_ -> "\n" ++ showExpr t --- newline needed in other cases than the first
_ -> "\n" ++ showExpr [] t --- newline needed in other cases than the first
stringOpOptions = sort $ [
("bind","bind tokens separated by Prelude.BIND, i.e. &+"),

View File

@@ -12,14 +12,13 @@ import GF.Command.Abstract
import GF.Command.Parse
import PGF
import PGF.Data
import PGF.Macros
import PGF.Morphology
import GF.System.Signal
import GF.Infra.UseIO
import GF.Infra.Option
import GF.Data.ErrM ----
import Text.PrettyPrint
import Control.Monad.Error
import qualified Data.Map as Map
data CommandEnv = CommandEnv {
@@ -43,12 +42,6 @@ interpretCommandLine enc env line =
case readCommandLine line of
Just [] -> return ()
Just pipes -> mapM_ (interpretPipe enc env) pipes
{-
Just pipes -> do res <- runInterruptibly (mapM_ (interpretPipe enc env) pipes)
case res of
Left ex -> putStrLnFlush $ enc (show ex)
Right x -> return x
-}
Nothing -> putStrLnFlush "command not parsed"
interpretPipe enc env cs = do
@@ -60,12 +53,15 @@ interpretPipe enc env cs = do
intercs (trees,_) (c:cs) = do
treess2 <- interc trees c
intercs treess2 cs
interc es comm@(Command co _ arg) = case co of
interc es comm@(Command co opts arg) = case co of
'%':f -> case Map.lookup f (commandmacros env) of
Just css -> do
mapM_ (interpretPipe enc env) (appLine (getCommandArg env arg es) css)
return ([],[]) ---- return ?
_ -> do
Just css ->
case getCommandTrees env arg es of
Right es -> do mapM_ (interpretPipe enc env) (appLine es css)
return ([],[])
Left msg -> do putStrLn ('\n':msg)
return ([],[])
Nothing -> do
putStrLn $ "command macro " ++ co ++ " not interpreted"
return ([],[])
_ -> interpret enc env es comm
@@ -82,43 +78,53 @@ appCommand xs c@(Command i os arg) = case arg of
EApp e1 e2 -> EApp (app e1) (app e2)
ELit l -> ELit l
EMeta i -> xs !! i
EVar x -> EVar x
EFun x -> EFun x
-- return the trees to be sent in pipe, and the output possibly printed
interpret :: (String -> String) -> CommandEnv -> [Expr] -> Command -> IO CommandOutput
interpret enc env trees0 comm = case lookCommand co comms of
Just info -> do
checkOpts info
tss@(_,s) <- exec info opts trees
optTrace $ enc s
return tss
_ -> do
putStrLn $ "command " ++ co ++ " not interpreted"
return ([],[])
where
optTrace = if isOpt "tr" opts then putStrLn else const (return ())
(co,opts,trees) = getCommand env comm trees0
comms = commands env
checkOpts info =
case
[o | OOpt o <- opts, notElem o ("tr" : map fst (options info))] ++
[o | OFlag o _ <- opts, notElem o (map fst (flags info))]
of
[] -> return ()
[o] -> putStrLn $ "option not interpreted: " ++ o
os -> putStrLn $ "options not interpreted: " ++ unwords os
interpret enc env trees comm =
case getCommand env trees comm of
Left msg -> do putStrLn ('\n':msg)
return ([],[])
Right (info,opts,trees) -> do tss@(_,s) <- exec info opts trees
if isOpt "tr" opts
then putStrLn (enc s)
else return ()
return tss
-- analyse command parse tree to a uniform datastructure, normalizing comm name
--- the env is needed for macro lookup
getCommand :: CommandEnv -> Command -> [Expr] -> (String,[Option],[Expr])
getCommand env co@(Command c opts arg) ts =
(getCommandOp c,opts,getCommandArg env arg ts)
getCommand :: CommandEnv -> [Expr] -> Command -> Either String (CommandInfo,[Option],[Expr])
getCommand env es co@(Command c opts arg) = do
info <- getCommandInfo env c
checkOpts info opts
es <- getCommandTrees env arg es
return (info,opts,es)
getCommandArg :: CommandEnv -> Argument -> [Expr] -> [Expr]
getCommandArg env a ts = case a of
AMacro m -> case Map.lookup m (expmacros env) of
Just t -> [t]
_ -> []
AExpr t -> [t] -- ignore piped
ANoArg -> ts -- use piped
getCommandInfo :: CommandEnv -> String -> Either String CommandInfo
getCommandInfo env cmd =
case lookCommand (getCommandOp cmd) (commands env) of
Just info -> return info
Nothing -> fail $ "command " ++ cmd ++ " not interpreted"
checkOpts :: CommandInfo -> [Option] -> Either String ()
checkOpts info opts =
case
[o | OOpt o <- opts, notElem o ("tr" : map fst (options info))] ++
[o | OFlag o _ <- opts, notElem o (map fst (flags info))]
of
[] -> return ()
[o] -> fail $ "option not interpreted: " ++ o
os -> fail $ "options not interpreted: " ++ unwords os
getCommandTrees :: CommandEnv -> Argument -> [Expr] -> Either String [Expr]
getCommandTrees env a es =
case a of
AMacro m -> case Map.lookup m (expmacros env) of
Just e -> return [e]
_ -> return []
AExpr e -> case inferExpr (multigrammar env) e of
Left tcErr -> fail $ render (ppTcError tcErr)
Right (e,ty) -> return [e] -- ignore piped
ANoArg -> return es -- use piped

View File

@@ -20,9 +20,7 @@ allTreeOps pgf = [
("paraphrase",("paraphrase by using semantic definitions (def)",
map tree2expr . nub . concatMap (paraphrase pgf . expr2tree))),
("smallest",("sort trees from smallest to largest, in number of nodes",
smallest)),
("typecheck",("type check and solve metavariables; reject if incorrect",
concatMap (typecheck pgf)))
smallest))
]
smallest :: [Expr] -> [Expr]
@@ -31,35 +29,3 @@ smallest = sortBy (\t u -> compare (size t) (size u)) where
EAbs _ e -> size e + 1
EApp e1 e2 -> size e1 + size e2 + 1
_ -> 1
{-
toTree :: G.Term -> Tree
toTree t = case M.termForm t of
Ok (xx,f,aa) -> Abs xx (Fun f (map toTree aa))
fromTree :: Tree -> G.Term
fromTree t = case t of
Abs xx b -> M.mkAbs xx (fromTree b)
Var x -> M.vr x
Fun f ts -> M.mkApp f (map fromTree ts)
-}
{-
data Tree =
Abs [CId] Tree -- ^ lambda abstraction. The list of variables is non-empty
| Var CId -- ^ variable
| Fun CId [Tree] -- ^ function application
| Lit Literal -- ^ literal
| Meta Int -- ^ meta variable
data Literal =
LStr String -- ^ string constant
| LInt Integer -- ^ integer constant
| LFlt Double -- ^ floating point constant
mkType :: A.Type -> C.Type
mkType t = case GM.typeForm t of
Ok (hyps,(_,cat),args) -> C.DTyp (mkContext hyps) (i2i cat) (map mkExp args)
mkExp :: A.Term -> C.Expr
-}

View File

@@ -68,7 +68,7 @@ plAbstract (name, Abstr aflags funs cats _catfuns) =
plCat :: (CId, [Hypo]) -> String
plCat (cat, hypos) = plFact "cat" (plTypeWithHypos typ)
where ((_,subst), hypos') = alphaConvert emptyEnv hypos
args = reverse [EVar x | (_,x) <- subst]
args = reverse [EFun x | (_,x) <- subst]
typ = DTyp hypos' cat args
plFun :: (CId, (Type, Int, [Equation])) -> String
@@ -119,7 +119,7 @@ instance PLPrint Hypo where
plp (HypV var typ) = plOper ":" (plp var) (plp typ)
instance PLPrint Expr where
plp (EVar x) = plp x
plp (EFun x) = plp x
plp (EAbs x e) = plOper "^" (plp x) (plp e)
plp (EApp e e') = plOper " * " (plp e) (plp e')
plp (ELit lit) = plp lit
@@ -279,7 +279,7 @@ instance AlphaConvert Expr where
alphaConvert env (EApp e1 e2) = (env'', EApp e1' e2')
where (env', e1') = alphaConvert env e1
(env'', e2') = alphaConvert env' e2
alphaConvert env expr@(EVar i) = (env, maybe expr EVar (lookup i (snd env)))
alphaConvert env expr@(EFun i) = (env, maybe expr EFun (lookup i (snd env)))
alphaConvert env expr = (env, expr)
-- pattern variables are not alpha converted

View File

@@ -70,17 +70,17 @@ canon2gfcc opts pars cgr@(M.MGrammar ((a,abm):cms)) =
gflags = Map.empty
aflags = Map.fromList [(mkCId f,x) | (f,x) <- optionsPGF (M.flags abm)]
mkDef (Just eqs) = [C.Equ (map mkPatt ps) (mkExp e) | (ps,e) <- eqs]
mkDef (Just eqs) = [C.Equ ps' (mkExp scope' e) | (ps,e) <- eqs, let (scope',ps') = mapAccumL mkPatt [] ps]
mkDef Nothing = []
mkArrity (Just a) = a
mkArrity Nothing = 0
-- concretes
lfuns = [(f', (mkType ty, mkArrity ma, mkDef pty)) |
lfuns = [(f', (mkType [] ty, mkArrity ma, mkDef pty)) |
(f,AbsFun (Just ty) ma pty) <- tree2list (M.jments abm), let f' = i2i f]
funs = Map.fromAscList lfuns
lcats = [(i2i c, mkContext cont) |
lcats = [(i2i c, snd (mkContext [] cont)) |
(c,AbsCat (Just cont) _) <- tree2list (M.jments abm)]
cats = Map.fromAscList lcats
catfuns = Map.fromList
@@ -118,36 +118,45 @@ canon2gfcc opts pars cgr@(M.MGrammar ((a,abm):cms)) =
i2i :: Ident -> CId
i2i = CId . ident2bs
mkType :: A.Type -> C.Type
mkType t = case GM.typeForm t of
Ok (hyps,(_,cat),args) -> C.DTyp (mkContext hyps) (i2i cat) (map mkExp args)
mkType :: [Ident] -> A.Type -> C.Type
mkType scope t =
case GM.typeForm t of
Ok (hyps,(_,cat),args) -> let (scope',hyps') = mkContext scope hyps
in C.DTyp hyps' (i2i cat) (map (mkExp scope') args)
mkExp :: A.Term -> C.Expr
mkExp t = case GM.termForm t of
Ok (xs,c,args) -> mkAbs xs (mkApp c (map mkExp args))
mkExp :: [Ident] -> A.Term -> C.Expr
mkExp scope t = case GM.termForm t of
Ok (xs,c,args) -> mkAbs xs (mkApp (reverse xs++scope) c (map (mkExp scope) args))
where
mkAbs xs t = foldr (C.EAbs . i2i) t xs
mkApp c args = case c of
Q _ c -> foldl C.EApp (C.EVar (i2i c)) args
QC _ c -> foldl C.EApp (C.EVar (i2i c)) args
Vr x -> C.EVar (i2i x)
mkApp scope c args = case c of
Q _ c -> foldl C.EApp (C.EFun (i2i c)) args
QC _ c -> foldl C.EApp (C.EFun (i2i c)) args
Vr x -> case lookup x (zip scope [0..]) of
Just i -> foldl C.EApp (C.EVar i) args
Nothing -> foldl C.EApp (C.EMeta 0) args
EInt i -> C.ELit (C.LInt i)
EFloat f -> C.ELit (C.LFlt f)
K s -> C.ELit (C.LStr s)
Meta (MetaSymb i) -> C.EMeta i
_ -> C.EMeta 0
mkPatt p = case p of
A.PP _ c ps -> C.PApp (i2i c) (map mkPatt ps)
A.PV x -> C.PVar (i2i x)
A.PW -> C.PWild
A.PInt i -> C.PLit (C.LInt i)
A.PFloat f -> C.PLit (C.LFlt f)
A.PString s -> C.PLit (C.LStr s)
mkPatt scope p =
case p of
A.PP _ c ps -> let (scope',ps') = mapAccumL mkPatt scope ps
in (scope',C.PApp (i2i c) ps')
A.PV x -> (x:scope,C.PVar (i2i x))
A.PW -> ( scope,C.PWild)
A.PInt i -> ( scope,C.PLit (C.LInt i))
A.PFloat f -> ( scope,C.PLit (C.LFlt f))
A.PString s -> ( scope,C.PLit (C.LStr s))
mkContext :: A.Context -> [C.Hypo]
mkContext hyps = [(if x == identW then C.Hyp else C.HypV (i2i x)) (mkType ty) | (x,ty) <- hyps]
mkContext :: [Ident] -> A.Context -> ([Ident],[C.Hypo])
mkContext scope hyps = mapAccumL (\scope (x,ty) -> let ty' = mkType scope ty
in if x == identW
then ( scope,C.Hyp ty')
else (x:scope,C.HypV (i2i x) ty')) scope hyps
mkTerm :: Term -> C.Term
mkTerm tr = case tr of

View File

@@ -9,7 +9,7 @@
-- load and interpret grammars compiled in Portable Grammar Format (PGF).
-- The PGF format is produced as a final output from the GF compiler.
-- The API is meant to be used for embedding GF grammars in Haskell
-- programs.
-- programs
-------------------------------------------------
module PGF(
@@ -51,7 +51,11 @@ module PGF(
parse, canParse, parseAllLang, parseAll,
-- ** Evaluation
tree2expr, expr2tree, PGF.compute, paraphrase, typecheck,
tree2expr, expr2tree, PGF.compute, paraphrase,
-- ** Type Checking
checkType, checkExpr, inferExpr,
ppTcError, TcError(..),
-- ** Word Completion (Incremental Parsing)
complete,
@@ -80,6 +84,7 @@ import GF.Data.Utilities (replace)
import Data.Char
import qualified Data.Map as Map
import qualified Data.IntMap as IntMap
import Data.Maybe
import Data.Binary
import System.Random (newStdGen)
@@ -307,4 +312,4 @@ complete pgf from typ input =
-- | Converts an expression to normal form
compute :: PGF -> Expr -> Expr
compute pgf = PGF.Data.normalForm (funs (abstract pgf))
compute pgf = PGF.Data.normalForm (funs (abstract pgf)) 0 []

View File

@@ -104,20 +104,24 @@ instance Binary Term where
instance Binary Expr where
put (EAbs x exp) = putWord8 0 >> put (x,exp)
put (EApp e1 e2) = putWord8 1 >> put (e1,e2)
put (EVar x) = putWord8 2 >> put x
put (ELit (LStr s)) = putWord8 3 >> put s
put (ELit (LFlt d)) = putWord8 4 >> put d
put (ELit (LInt i)) = putWord8 5 >> put i
put (EMeta i) = putWord8 6 >> put i
put (ELit (LStr s)) = putWord8 2 >> put s
put (ELit (LFlt d)) = putWord8 3 >> put d
put (ELit (LInt i)) = putWord8 4 >> put i
put (EMeta i) = putWord8 5 >> put i
put (EFun f) = putWord8 6 >> put f
put (EVar i) = putWord8 7 >> put i
put (ETyped e ty) = putWord8 8 >> put (e,ty)
get = do tag <- getWord8
case tag of
0 -> liftM2 EAbs get get
1 -> liftM2 EApp get get
2 -> liftM EVar get
3 -> liftM (ELit . LStr) get
4 -> liftM (ELit . LFlt) get
5 -> liftM (ELit . LInt) get
6 -> liftM EMeta get
2 -> liftM (ELit . LStr) get
3 -> liftM (ELit . LFlt) get
4 -> liftM (ELit . LInt) get
5 -> liftM EMeta get
6 -> liftM EFun get
7 -> liftM EVar get
8 -> liftM2 ETyped get get
_ -> decodingError
instance Binary Patt where

View File

@@ -7,12 +7,12 @@ module PGF.Expr(Tree(..), Literal(..),
tree2expr, expr2tree, normalForm,
-- needed in the typechecker
Value(..), Env, eval, apply, eqValue,
Value(..), Env, Funs, eval, apply,
MetaId,
-- helpers
pStr,pFactor,
pStr,pFactor,freshName,ppMeta
) where
import PGF.CId
@@ -20,16 +20,17 @@ import PGF.Type
import Data.Char
import Data.Maybe
import Data.List as List
import Data.Map as Map hiding (showTree)
import Control.Monad
import qualified Text.PrettyPrint as PP
import qualified Text.ParserCombinators.ReadP as RP
import qualified Data.Map as Map
data Literal =
LStr String -- ^ string constant
| LInt Integer -- ^ integer constant
| LFlt Double -- ^ floating point constant
deriving (Eq,Ord)
deriving (Eq,Ord,Show)
type MetaId = Int
@@ -52,9 +53,10 @@ data Expr =
| EApp Expr Expr -- ^ application
| ELit Literal -- ^ literal
| EMeta {-# UNPACK #-} !MetaId -- ^ meta variable
| EVar CId -- ^ variable or function reference
| EPi CId Expr Expr -- ^ dependent function type
deriving (Eq,Ord)
| EFun CId -- ^ function or data constructor
| EVar {-# UNPACK #-} !Int -- ^ variable with de Bruijn index
| ETyped Expr Type
deriving (Eq,Ord,Show)
-- | The pattern is used to define equations in the abstract syntax of the grammar.
data Patt =
@@ -94,12 +96,12 @@ readExpr s = case [x | (x,cs) <- RP.readP_to_S pExpr s, all isSpace cs] of
[x] -> Just x
_ -> Nothing
-- | renders expression as 'String'
showExpr :: Expr -> String
showExpr = PP.render . ppExpr 0
instance Show Expr where
showsPrec i x = showString (PP.render (ppExpr i x))
-- | renders expression as 'String'. The list
-- of identifiers is the list of all free variables
-- in the expression in order reverse to the order
-- of binding.
showExpr :: [CId] -> Expr -> String
showExpr vars = PP.render . ppExpr 0 vars
instance Read Expr where
readsPrec _ = RP.readP_to_S pExpr
@@ -124,24 +126,31 @@ pTree isNested = RP.skipSpaces >> (pParen RP.<++ pAbs RP.<++ pApp RP.<++ fmap Li
return (Fun f ts)
pExpr :: RP.ReadP Expr
pExpr = RP.skipSpaces >> (pAbs RP.<++ pTerm)
pExpr = pExpr0 >>= optTyped
where
pExpr0 = RP.skipSpaces >> (pAbs RP.<++ pTerm)
pTerm = fmap (foldl1 EApp) (RP.sepBy1 pFactor RP.skipSpaces)
pAbs = do xs <- RP.between (RP.char '\\') (RP.skipSpaces >> RP.string "->") (RP.sepBy1 (RP.skipSpaces >> pCId) (RP.skipSpaces >> RP.char ','))
e <- pExpr
e <- pExpr0
return (foldr EAbs e xs)
pFactor = fmap EVar pCId
optTyped e = do RP.skipSpaces
RP.char ':'
RP.skipSpaces
ty <- pType
return (ETyped e ty)
RP.<++
return e
pFactor = fmap EFun pCId
RP.<++ fmap ELit pLit
RP.<++ fmap EMeta pMeta
RP.<++ RP.between (RP.char '(') (RP.char ')') pExpr
pMeta = do RP.char '?'
cs <- RP.look
case cs of
(c:_) | isDigit c -> fmap read (RP.munch1 isDigit)
_ -> return 0
return 0
pLit :: RP.ReadP Literal
pLit = pNum RP.<++ liftM LStr pStr
@@ -161,35 +170,37 @@ pStr = RP.char '"' >> (RP.manyTill (pEsc RP.<++ RP.get) (RP.char '"'))
-----------------------------------------------------
ppTree d (Abs xs t) = ppParens (d > 0) (PP.char '\\' PP.<>
PP.hsep (PP.punctuate PP.comma (map (PP.text . prCId) xs)) PP.<+>
PP.hsep (PP.punctuate PP.comma (List.map (PP.text . prCId) xs)) PP.<+>
PP.text "->" PP.<+>
ppTree 0 t)
ppTree d (Fun f []) = PP.text (prCId f)
ppTree d (Fun f ts) = ppParens (d > 0) (PP.text (prCId f) PP.<+> PP.hsep (map (ppTree 1) ts))
ppTree d (Fun f ts) = ppParens (d > 0) (PP.text (prCId f) PP.<+> PP.hsep (List.map (ppTree 1) ts))
ppTree d (Lit l) = ppLit l
ppTree d (Meta n) = ppMeta n
ppTree d (Var id) = PP.text (prCId id)
ppExpr :: Int -> Expr -> PP.Doc
ppExpr d (EAbs x e) = let (xs,e1) = getVars (EAbs x e)
in ppParens (d > 0) (PP.char '\\' PP.<>
PP.hsep (PP.punctuate PP.comma (map (PP.text . prCId) xs)) PP.<+>
PP.text "->" PP.<+>
ppExpr 0 e1)
where
getVars (EAbs x e) = let (xs,e1) = getVars e in (x:xs,e1)
getVars e = ([],e)
ppExpr d (EApp e1 e2) = ppParens (d > 1) ((ppExpr 1 e1) PP.<+> (ppExpr 2 e2))
ppExpr d (ELit l) = ppLit l
ppExpr d (EMeta n) = ppMeta n
ppExpr d (EVar f) = PP.text (prCId f)
ppExpr d (EPi x e1 e2)= PP.parens (PP.text (prCId x) PP.<+> PP.colon PP.<+> ppExpr 0 e1) PP.<+> PP.text "->" PP.<+> ppExpr 0 e2
ppExpr :: Int -> [CId] -> Expr -> PP.Doc
ppExpr d scope (EAbs x e) = let (xs,e1) = getVars [x] e
in ppParens (d > 1) (PP.char '\\' PP.<>
PP.hsep (PP.punctuate PP.comma (List.map (PP.text . prCId) (reverse xs))) PP.<+>
PP.text "->" PP.<+>
ppExpr 1 (xs++scope) e1)
where
getVars xs (EAbs x e) = getVars (freshName x xs:xs) e
getVars xs e = (xs,e)
ppExpr d scope (EApp e1 e2) = ppParens (d > 3) ((ppExpr 3 scope e1) PP.<+> (ppExpr 4 scope e2))
ppExpr d scope (ELit l) = ppLit l
ppExpr d scope (EMeta n) = ppMeta n
ppExpr d scope (EFun f) = PP.text (prCId f)
ppExpr d scope (EVar i) = PP.text (prCId (scope !! i))
ppExpr d scope (ETyped e ty)= ppParens (d > 0) (ppExpr 0 scope e PP.<+> PP.colon PP.<+> ppType 0 scope ty)
ppPatt d (PApp f ps) = ppParens (d > 1) (PP.text (prCId f) PP.<+> PP.hsep (map (ppPatt 2) ps))
ppPatt d (PLit l) = ppLit l
ppPatt d (PVar f) = PP.text (prCId f)
ppPatt d PWild = PP.char '_'
ppPatt d scope (PApp f ps) = let (scope',ds) = mapAccumL (ppPatt 2) scope ps
in (scope',ppParens (not (List.null ps) && d > 1) (PP.text (prCId f) PP.<+> PP.hsep ds))
ppPatt d scope (PLit l) = (scope,ppLit l)
ppPatt d scope (PVar f) = (scope,PP.text (prCId f))
ppPatt d scope PWild = (scope,PP.char '_')
ppLit (LStr s) = PP.text (show s)
ppLit (LInt n) = PP.integer n
@@ -203,6 +214,12 @@ ppMeta n
ppParens True = PP.parens
ppParens False = id
freshName :: CId -> [CId] -> CId
freshName x xs = loop 1 x
where
loop i y
| elem y xs = loop (i+1) (mkCId (show x++"'"++show i))
| otherwise = y
-----------------------------------------------------
-- Conversion Expr <-> Tree
@@ -211,33 +228,38 @@ ppParens False = id
-- | Converts a tree to expression. The conversion
-- is always total, every tree is a valid expression.
tree2expr :: Tree -> Expr
tree2expr (Fun x ts) = foldl EApp (EVar x) (map tree2expr ts)
tree2expr (Lit l) = ELit l
tree2expr (Meta n) = EMeta n
tree2expr (Abs xs t) = foldr EAbs (tree2expr t) xs
tree2expr (Var x) = EVar x
tree2expr = tree2expr []
where
tree2expr ys (Fun x ts) = foldl EApp (EFun x) (List.map (tree2expr ys) ts)
tree2expr ys (Lit l) = ELit l
tree2expr ys (Meta n) = EMeta n
tree2expr ys (Abs xs t) = foldr EAbs (tree2expr (reverse xs++ys) t) xs
tree2expr ys (Var x) = case List.lookup x (zip ys [0..]) of
Just i -> EVar i
Nothing -> error "unknown variable"
-- | Converts an expression to tree. The conversion is only partial.
-- Variables and meta variables of function type and beta redexes are not allowed.
expr2tree :: Expr -> Tree
expr2tree e = abs [] [] e
where
abs ys xs (EAbs x e) = abs ys (x:xs) e
abs ys xs e = case xs of
[] -> app ys [] e
xs -> Abs (reverse xs) (app (xs++ys) [] e)
abs ys xs (EAbs x e) = abs ys (x:xs) e
abs ys xs (ETyped e _) = abs ys xs e
abs ys xs e = case xs of
[] -> app ys [] e
xs -> Abs (reverse xs) (app (xs++ys) [] e)
app xs as (EApp e1 e2) = app xs ((abs xs [] e2) : as) e1
app xs as (EApp e1 e2) = app xs ((abs xs [] e2) : as) e1
app xs as (ELit l)
| null as = Lit l
| otherwise = error "literal of function type encountered"
| List.null as = Lit l
| otherwise = error "literal of function type encountered"
app xs as (EMeta n)
| null as = Meta n
| otherwise = error "meta variables of function type are not allowed in trees"
app xs as (EAbs x e) = error "beta redexes are not allowed in trees"
app xs as (EVar x)
| x `elem` xs = Var x
| otherwise = Fun x as
| List.null as = Meta n
| otherwise = error "meta variables of function type are not allowed in trees"
app xs as (EAbs x e) = error "beta redexes are not allowed in trees"
app xs as (EVar i) = Var (xs !! i)
app xs as (EFun f) = Fun f as
app xs as (ETyped e _) = app xs as e
-----------------------------------------------------
@@ -245,109 +267,84 @@ expr2tree e = abs [] [] e
-----------------------------------------------------
-- | Compute an expression to normal form
normalForm :: Funs -> Expr -> Expr
normalForm funs e = value2expr 0 (eval funs Map.empty e)
normalForm :: Funs -> Int -> Env -> Expr -> Expr
normalForm funs k env e = value2expr k (eval funs env e)
where
value2expr i (VApp f vs) = foldl EApp (EVar f) (map (value2expr i) vs)
value2expr i (VGen j vs) = foldl EApp (EVar (var j)) (map (value2expr i) vs)
value2expr i (VMeta j vs) = foldl EApp (EMeta j) (map (value2expr i) vs)
value2expr i (VSusp j vs k) = value2expr i (k (VGen j vs))
value2expr i (VApp f vs) = foldl EApp (EFun f) (List.map (value2expr i) vs)
value2expr i (VGen j vs) = foldl EApp (EVar (i-j-1)) (List.map (value2expr i) vs)
value2expr i (VMeta j env vs) = foldl EApp (EMeta j) (List.map (value2expr i) vs)
value2expr i (VSusp j env vs k) = value2expr i (k (VGen j vs))
value2expr i (VLit l) = ELit l
value2expr i (VClosure env (EAbs x e)) = EAbs (var i) (value2expr (i+1) (eval funs (Map.insert x (VGen i []) env) e))
var i = mkCId ('v':show i)
ret [] t = t
ret xs t = Abs (reverse xs) t
value2expr i (VClosure env (EAbs x e)) = EAbs x (value2expr (i+1) (eval funs ((VGen i []):env) e))
data Value
= VApp CId [Value]
| VLit Literal
| VMeta {-# UNPACK #-} !MetaId [Value]
| VGen {-# UNPACK #-} !MetaId [Value]
| VSusp {-# UNPACK #-} !MetaId [Value] (Value -> Value)
| VMeta {-# UNPACK #-} !MetaId Env [Value]
| VSusp {-# UNPACK #-} !MetaId Env [Value] (Value -> Value)
| VGen {-# UNPACK #-} !Int [Value]
| VClosure Env Expr
type Funs = Map.Map CId (Type,Int,[Equation]) -- type and def of a fun
type Env = Map.Map CId Value
type Env = [Value]
eval :: Funs -> Env -> Expr -> Value
eval funs env (EVar x) = case Map.lookup x env of
Just v -> v
Nothing -> case Map.lookup x funs of
Just (_,a,eqs) -> if a == 0
then case eqs of
Equ [] e : _ -> eval funs Map.empty e
_ -> VApp x []
else VApp x []
Nothing -> error ("unknown variable "++prCId x)
eval funs env (EVar i) = env !! i
eval funs env (EFun f) = case Map.lookup f funs of
Just (_,a,eqs) -> if a == 0
then case eqs of
Equ [] e : _ -> eval funs [] e
_ -> VApp f []
else VApp f []
Nothing -> error ("unknown function "++prCId f)
eval funs env (EApp e1 e2) = apply funs env e1 [eval funs env e2]
eval funs env (EAbs x e) = VClosure env (EAbs x e)
eval funs env (EMeta k) = VMeta k []
eval funs env (EMeta i) = VMeta i env []
eval funs env (ELit l) = VLit l
eval funs env (EPi x e1 e2)= VClosure env (EPi x e1 e2)
eval funs env (ETyped e _) = eval funs env e
apply :: Funs -> Env -> Expr -> [Value] -> Value
apply funs env e [] = eval funs env e
apply funs env (EVar x) vs = case Map.lookup x env of
Just v -> applyValue funs env v vs
Nothing -> case Map.lookup x funs of
Just (_,a,eqs) -> if a <= length vs
then let (as,vs') = splitAt a vs
in match funs x eqs as vs'
else VApp x vs
Nothing -> error ("unknown variable "++prCId x)
apply funs env (EVar i) vs = applyValue funs (env !! i) vs
apply funs env (EFun f) vs = case Map.lookup f funs of
Just (_,a,eqs) -> if a <= length vs
then let (as,vs') = splitAt a vs
in match funs f eqs as vs'
else VApp f vs
Nothing -> error ("unknown function "++prCId f)
apply funs env (EApp e1 e2) vs = apply funs env e1 (eval funs env e2 : vs)
apply funs env (EAbs x e) (v:vs) = apply funs (Map.insert x v env) e vs
apply funs env (EMeta k) vs = VMeta k vs
apply funs env (EAbs x e) (v:vs) = apply funs (v:env) e vs
apply funs env (EMeta i) vs = VMeta i env vs
apply funs env (ELit l) vs = error "literal of function type"
apply funs env (ETyped e _) vs = apply funs env e vs
applyValue funs env (VApp f vs0) vs = apply funs env (EVar f) (vs0++vs)
applyValue funs env (VLit _) vs = error "literal of function type"
applyValue funs env (VMeta i vs0) vs = VMeta i (vs0++vs)
applyValue funs env (VGen i vs0) vs = VGen i (vs0++vs)
applyValue funs env (VSusp i vs0 k) vs = VSusp i vs0 (\v -> applyValue funs env (k v) vs)
applyValue funs _ (VClosure env (EAbs x e)) (v:vs) = apply funs (Map.insert x v env) e vs
applyValue funs v [] = v
applyValue funs (VApp f vs0) vs = apply funs [] (EFun f) (vs0++vs)
applyValue funs (VLit _) vs = error "literal of function type"
applyValue funs (VMeta i env vs0) vs = VMeta i env (vs0++vs)
applyValue funs (VGen i vs0) vs = VGen i (vs0++vs)
applyValue funs (VSusp i env vs0 k) vs = VSusp i env vs0 (\v -> applyValue funs (k v) vs)
applyValue funs (VClosure env (EAbs x e)) (v:vs) = apply funs (v:env) e vs
-----------------------------------------------------
-- Pattern matching
-----------------------------------------------------
match :: Funs -> CId -> [Equation] -> [Value] -> [Value] -> Value
match funs f eqs as0 vs0 =
match sig f eqs as0 vs0 =
case eqs of
[] -> VApp f (as0++vs0)
(Equ ps res):eqs -> tryMatches eqs ps as0 res Map.empty
(Equ ps res):eqs -> tryMatches eqs ps as0 res []
where
tryMatches eqs [] [] res env = apply funs env res vs0
tryMatches eqs [] [] res env = apply sig env res vs0
tryMatches eqs (p:ps) (a:as) res env = tryMatch p a env
where
tryMatch (PVar x ) (v ) env = tryMatches eqs ps as res (Map.insert x v env)
tryMatch (PWild ) (_ ) env = tryMatches eqs ps as res env
tryMatch (p ) (VMeta i vs ) env = VSusp i vs (\v -> tryMatch p v env)
tryMatch (p ) (VGen i vs ) env = VApp f (as0++vs0)
tryMatch (p ) (VSusp i vs k) env = VSusp i vs (\v -> tryMatch p (k v) env)
tryMatch (PApp f1 ps1) (VApp f2 vs2 ) env | f1 == f2 = tryMatches eqs (ps1++ps) (vs2++as) res env
tryMatch (PLit l1 ) (VLit l2 ) env | l1 == l2 = tryMatches eqs ps as res env
tryMatch _ _ env = match funs f eqs as0 vs0
-----------------------------------------------------
-- Equality checking
-----------------------------------------------------
eqValue :: Funs -> Int -> Value -> Value -> [(Value,Value)]
eqValue funs k v1 v2 =
case (whnf v1,whnf v2) of
(VApp f1 vs1, VApp f2 vs2) | f1 == f2 -> concat (zipWith (eqValue funs k) vs1 vs2)
(VLit l1, VLit l2 ) | l1 == l2 -> []
(VMeta i vs1, VMeta j vs2) | i == j -> concat (zipWith (eqValue funs k) vs1 vs2)
(VGen i vs1, VGen j vs2) | i == j -> concat (zipWith (eqValue funs k) vs1 vs2)
(VClosure env1 (EAbs x1 e1), VClosure env2 (EAbs x2 e2)) ->
let v = VGen k []
in eqValue funs (k+1) (VClosure (Map.insert x1 v env1) e1) (VClosure (Map.insert x2 v env2) e2)
_ -> [(v1,v2)]
where
whnf (VClosure env e) = eval funs env e -- should be removed when the typechecker is improved
whnf v = v
tryMatch (PVar x ) (v ) env = tryMatches eqs ps as res (v:env)
tryMatch (PWild ) (_ ) env = tryMatches eqs ps as res env
tryMatch (p ) (VMeta i envi vs ) env = VSusp i envi vs (\v -> tryMatch p v env)
tryMatch (p ) (VGen i vs ) env = VApp f (as0++vs0)
tryMatch (p ) (VSusp i envi vs k) env = VSusp i envi vs (\v -> tryMatch p (k v) env)
tryMatch (PApp f1 ps1) (VApp f2 vs2 ) env | f1 == f2 = tryMatches eqs (ps1++ps) (vs2++as) res env
tryMatch (PLit l1 ) (VLit l2 ) env | l1 == l2 = tryMatches eqs ps as res env
tryMatch _ _ env = match sig f eqs as0 vs0

View File

@@ -1,13 +1,17 @@
module PGF.Expr where
import PGF.CId
import qualified Text.PrettyPrint as PP
import qualified Text.ParserCombinators.ReadP as RP
data Expr
instance Eq Expr
instance Ord Expr
instance Eq Expr
instance Ord Expr
instance Show Expr
pFactor :: RP.ReadP Expr
ppExpr :: Int -> Expr -> PP.Doc
ppExpr :: Int -> [CId] -> Expr -> PP.Doc
freshName :: CId -> [CId] -> CId

View File

@@ -5,22 +5,22 @@ module PGF.Type ( Type(..), Hypo(..),
import PGF.CId
import {-# SOURCE #-} PGF.Expr
import Data.Char
import Data.List
import qualified Text.PrettyPrint as PP
import qualified Text.ParserCombinators.ReadP as RP
import Control.Monad
import Debug.Trace
-- | To read a type from a 'String', use 'read' or 'readType'.
data Type =
DTyp [Hypo] CId [Expr]
deriving (Eq,Ord)
deriving (Eq,Ord,Show)
-- | 'Hypo' represents a hypothesis in a type i.e. in the type A -> B, A is the hypothesis
data Hypo =
Hyp Type -- ^ hypothesis without bound variable like in A -> B
| HypV CId Type -- ^ hypothesis with bound variable like in (x : A) -> B x
| HypI CId Type -- ^ hypothesis with bound implicit variable like in {x : A} -> B x
deriving (Eq,Ord)
deriving (Eq,Ord,Show)
-- | Reads a 'Type' from a 'String'.
readType :: String -> Maybe Type
@@ -28,15 +28,12 @@ readType s = case [x | (x,cs) <- RP.readP_to_S pType s, all isSpace cs] of
[x] -> Just x
_ -> Nothing
instance Show Type where
showsPrec i x = showString (PP.render (ppType i x))
instance Read Type where
readsPrec _ = RP.readP_to_S pType
-- | renders type as 'String'
showType :: Type -> String
showType = PP.render . ppType 0
-- | renders type as 'String'. The list
-- of identifiers is the list of all free variables
-- in the expression in order reverse to the order
-- of binding.
showType :: [CId] -> Type -> String
showType vars = PP.render . ppType 0 vars
pType :: RP.ReadP Type
pType = do
@@ -72,17 +69,19 @@ pType = do
args <- RP.sepBy pFactor RP.skipSpaces
return (cat, args)
ppType :: Int -> Type -> PP.Doc
ppType d (DTyp ctxt cat args)
| null ctxt = ppRes cat args
| otherwise = ppParens (d > 0) (foldr ppCtxt (ppRes cat args) ctxt)
ppType :: Int -> [CId] -> Type -> PP.Doc
ppType d scope (DTyp hyps cat args)
| null hyps = ppRes scope cat args
| otherwise = let (scope',hdocs) = mapAccumL ppHypo scope hyps
in ppParens (d > 0) (foldr (\hdoc doc -> hdoc PP.<+> PP.text "->" PP.<+> doc) (ppRes scope' cat args) hdocs)
where
ppCtxt hyp doc = ppHypo hyp PP.<+> PP.text "->" PP.<+> doc
ppRes cat es = PP.text (prCId cat) PP.<+> PP.hsep (map (ppExpr 2) es)
ppRes scope cat es = PP.text (prCId cat) PP.<+> PP.hsep (map (ppExpr 4 scope) es)
ppHypo (Hyp typ) = ppType 1 typ
ppHypo (HypV x typ) = PP.parens (PP.text (prCId x) PP.<+> PP.char ':' PP.<+> ppType 0 typ)
ppHypo (HypI x typ) = PP.braces (PP.text (prCId x) PP.<+> PP.char ':' PP.<+> ppType 0 typ)
ppHypo scope (Hyp typ) = ( scope,ppType 1 scope typ)
ppHypo scope (HypV x typ) = let y = freshName x scope
in (y:scope,PP.parens (PP.text (prCId y) PP.<+> PP.char ':' PP.<+> ppType 0 scope typ))
ppHypo scope (HypI x typ) = let y = freshName x scope
in (y:scope,PP.braces (PP.text (prCId y) PP.<+> PP.char ':' PP.<+> ppType 0 scope typ))
ppParens :: Bool -> PP.Doc -> PP.Doc
ppParens True = PP.parens

View File

@@ -1,201 +1,463 @@
----------------------------------------------------------------------
-- |
-- Module : TypeCheck
-- Maintainer : AR
-- Module : PGF.TypeCheck
-- Maintainer : Krasimir Angelov
-- Stability : (stable)
-- Portability : (portable)
--
-- type checking in abstract syntax with dependent types.
-- Type checking in abstract syntax with dependent types.
-- The type checker also performs renaming and checking for unknown
-- functions. The variable references are replaced by de Bruijn indices.
--
-- modified from src GF TC
-----------------------------------------------------------------------------
module PGF.TypeCheck (
typecheck
) where
module PGF.TypeCheck (checkType, checkExpr, inferExpr,
ppTcError, TcError(..)
) where
import PGF.Data
import PGF.Macros (lookDef,isData)
import PGF.Expr
import PGF.Macros (typeOfHypo)
import PGF.CId
import GF.Data.ErrM
import qualified Data.Map as Map
import Control.Monad (liftM2,foldM)
import Data.List (partition,sort,groupBy)
import Data.Map as Map
import Data.IntMap as IntMap
import Data.Maybe as Maybe
import Data.List as List
import Control.Monad
import Text.PrettyPrint
import Debug.Trace
-----------------------------------------------------
-- The Scope
-----------------------------------------------------
typecheck :: PGF -> Expr -> [Expr]
typecheck pgf e = case inferExpr pgf (newMetas e) of
Ok e -> [e]
Bad s -> trace s []
data TType = TTyp Env Type
newtype Scope = Scope [(CId,TType)]
inferExpr :: PGF -> Expr -> Err Expr
inferExpr pgf e = case infer pgf emptyTCEnv e of
Ok (e,_,cs) -> let (ms,cs2) = splitConstraints pgf cs in case cs2 of
[] -> trace (prConstraints cs ++"\n"++ show ms) $ Ok (metaSubst ms e)
_ -> Bad ("Error in tree " ++ showExpr e ++ " :\n " ++ prConstraints cs2)
Bad s -> Bad s
emptyScope = Scope []
infer :: PGF -> TCEnv -> Expr -> Err (Expr, Value, [(Value,Value)])
infer pgf tenv@(k,rho,gamma) e = case e of
EVar x -> do
ty <- lookupEVar pgf tenv x
return (e,ty,[])
addScopedVar :: CId -> TType -> Scope -> Scope
addScopedVar x tty (Scope gamma) = Scope ((x,tty):gamma)
-- EInt i -> return (AInt i, valAbsInt, [])
-- EFloat i -> return (AFloat i, valAbsFloat, [])
-- K i -> return (AStr i, valAbsString, [])
-- | returns the type and the De Bruijn index of a local variable
lookupVar :: CId -> Scope -> Maybe (Int,TType)
lookupVar x (Scope gamma) = listToMaybe [(i,tty) | ((y,tty),i) <- zip gamma [0..], x == y]
EApp f t -> do
(f',typ,csf) <- infer pgf tenv f
case typ of
VClosure env (EPi x a b) -> do
(a',csa) <- checkExp pgf tenv t (VClosure env a)
let b' = eval (getFunEnv (abstract pgf)) (eins x (VClosure rho t) env) b
return $ (EApp f' a', b', csf ++ csa)
_ -> Bad ("function type expected for function " ++ show f)
_ -> Bad ("cannot infer type of expression" ++ show e)
-- | returns the type and the name of a local variable
getVar :: Int -> Scope -> (CId,TType)
getVar i (Scope gamma) = gamma !! i
scopeEnv :: Scope -> Env
scopeEnv (Scope gamma) = let n = length gamma
in [VGen (n-i-1) [] | i <- [0..n-1]]
checkExp :: PGF -> TCEnv -> Expr -> Value -> Err (Expr, [(Value,Value)])
checkExp pgf tenv@(k,rho,gamma) e typ = do
let v = VGen k []
case e of
EMeta m -> return $ (e,[])
EAbs x t -> case typ of
VClosure env (EPi y a b) -> do
let a' = eval (getFunEnv (abstract pgf)) env a
(t',cs) <- checkExp pgf (k+1,eins x v rho, eins x a' gamma) t
(VClosure (eins y v env) b)
return (EAbs x t', cs)
_ -> Bad ("function type expected for " ++ show e)
_ -> checkInferExp pgf tenv e typ
scopeVars :: Scope -> [CId]
scopeVars (Scope gamma) = List.map fst gamma
getFunEnv abs = Map.union (funs abs) (Map.map (\hypos -> (DTyp hypos cidType [],0,[])) (cats abs))
scopeSize :: Scope -> Int
scopeSize (Scope gamma) = length gamma
-----------------------------------------------------
-- The Monad
-----------------------------------------------------
type MetaStore = IntMap MetaValue
data MetaValue
= MUnbound Scope [Expr -> TcM ()]
| MBound Expr
| MGuarded Expr [Expr -> TcM ()] {-# UNPACK #-} !Int -- the Int is the number of constraints that have to be solved
-- to unlock this meta variable
newtype TcM a = TcM {unTcM :: Abstr -> MetaId -> MetaStore -> TcResult a}
data TcResult a
= Ok {-# UNPACK #-} !MetaId MetaStore a
| Fail TcError
instance Monad TcM where
return x = TcM (\abstr metaid ms -> Ok metaid ms x)
f >>= g = TcM (\abstr metaid ms -> case unTcM f abstr metaid ms of
Ok metaid ms x -> unTcM (g x) abstr metaid ms
Fail e -> Fail e)
instance Functor TcM where
fmap f x = TcM (\abstr metaid ms -> case unTcM x abstr metaid ms of
Ok metaid ms x -> Ok metaid ms (f x)
Fail e -> Fail e)
lookupCatHyps :: CId -> TcM [Hypo]
lookupCatHyps cat = TcM (\abstr metaid ms -> case Map.lookup cat (cats abstr) of
Just hyps -> Ok metaid ms hyps
Nothing -> Fail (UnknownCat cat))
lookupFunType :: CId -> TcM TType
lookupFunType fun = TcM (\abstr metaid ms -> case Map.lookup fun (funs abstr) of
Just (ty,_,_) -> Ok metaid ms (TTyp [] ty)
Nothing -> Fail (UnknownFun fun))
newMeta :: Scope -> TcM MetaId
newMeta scope = TcM (\abstr metaid ms -> Ok (metaid+1) (IntMap.insert metaid (MUnbound scope []) ms) metaid)
newGuardedMeta :: Scope -> Expr -> TcM MetaId
newGuardedMeta scope e = getFuns >>= \funs -> TcM (\abstr metaid ms -> Ok (metaid+1) (IntMap.insert metaid (MGuarded e [] 0) ms) metaid)
getMeta :: MetaId -> TcM MetaValue
getMeta i = TcM (\abstr metaid ms -> Ok metaid ms $! case IntMap.lookup i ms of
Just mv -> mv)
setMeta :: MetaId -> MetaValue -> TcM ()
setMeta i mv = TcM (\abstr metaid ms -> Ok metaid (IntMap.insert i mv ms) ())
tcError :: TcError -> TcM a
tcError e = TcM (\abstr metaid ms -> Fail e)
getFuns :: TcM Funs
getFuns = TcM (\abstr metaid ms -> Ok metaid ms (funs abstr))
addConstraint :: MetaId -> MetaId -> Env -> [Value] -> (Value -> TcM ()) -> TcM ()
addConstraint i j env vs c = do
funs <- getFuns
mv <- getMeta j
case mv of
MUnbound scope cs -> addRef >> setMeta j (MUnbound scope ((\e -> release >> c (apply funs env e vs)) : cs))
MBound e -> c (apply funs env e vs)
MGuarded e cs x | x == 0 -> c (apply funs env e vs)
| otherwise -> addRef >> setMeta j (MGuarded e ((\e -> release >> c (apply funs env e vs)) : cs) x)
where
cidType = mkCId "Type"
addRef = TcM (\abstr metaid ms -> case IntMap.lookup i ms of
Just (MGuarded e cs x) -> Ok metaid (IntMap.insert i (MGuarded e cs (x+1)) ms) ())
checkInferExp :: PGF -> TCEnv -> Expr -> Value -> Err (Expr, [(Value,Value)])
checkInferExp pgf tenv@(k,_,_) e typ = do
(e',w,cs1) <- infer pgf tenv e
let cs2 = eqValue (getFunEnv (abstract pgf)) k w typ
return (e',cs1 ++ cs2)
lookupEVar :: PGF -> TCEnv -> CId -> Err Value
lookupEVar pgf (_,g,_) x = case Map.lookup x g of
Just v -> return v
_ -> maybe (Bad "var not found") (return . VClosure eempty . type2expr . (\(a,b,c) -> a)) $
Map.lookup x (funs (abstract pgf))
release = TcM (\abstr metaid ms -> case IntMap.lookup i ms of
Just (MGuarded e cs x) -> if x == 1
then unTcM (sequence_ [c e | c <- cs]) abstr metaid (IntMap.insert i (MGuarded e [] 0) ms)
else Ok metaid (IntMap.insert i (MGuarded e cs (x-1)) ms) ())
type2expr :: Type -> Expr
type2expr (DTyp hyps cat es) =
foldr (uncurry EPi) (foldl EApp (EVar cat) es) [toPair h | h <- hyps]
-----------------------------------------------------
-- Type errors
-----------------------------------------------------
data TcError
= UnknownCat CId
| UnknownFun CId
| WrongCatArgs Scope Type CId Int Int
| TypeMismatch Scope Expr Type Type
| NotFunType Scope Expr Type
| CannotInferType Scope Expr
| UnresolvedMetaVars Scope Expr [MetaId]
ppTcError :: TcError -> Doc
ppTcError (UnknownCat cat) = text "Category" <+> text (prCId cat) <+> text "is not in scope"
ppTcError (UnknownFun fun) = text "Function" <+> text (prCId fun) <+> text "is not in scope"
ppTcError (WrongCatArgs scope ty cat m n) =
text "Category" <+> text (prCId cat) <+> text "should have" <+> int m <+> text "argument(s), but has been given" <+> int n $$
text "In the type:" <+> ppType 0 (scopeVars scope) ty
ppTcError (TypeMismatch scope e ty1 ty2) = text "Couldn't match expected type" <+> ppType 0 (scopeVars scope) ty1 $$
text " against inferred type" <+> ppType 0 (scopeVars scope) ty2 $$
text "In the expression:" <+> ppExpr 0 (scopeVars scope) e
ppTcError (NotFunType scope e ty) = text "A function type is expected for the expression" <+> ppExpr 0 (scopeVars scope) e <+> text "instead of type" <+> ppType 0 (scopeVars scope) ty
ppTcError (CannotInferType scope e) = text "Cannot infer the type of expression" <+> ppExpr 0 (scopeVars scope) e
ppTcError (UnresolvedMetaVars scope e xs) = text "Meta variable(s)" <+> fsep (List.map ppMeta xs) <+> text "should be resolved" $$
text "in the expression:" <+> ppExpr 0 (scopeVars scope) e
-----------------------------------------------------
-- checkType
-----------------------------------------------------
checkType :: PGF -> Type -> Either TcError Type
checkType pgf ty =
case unTcM (tcType emptyScope ty >>= refineType) (abstract pgf) 0 IntMap.empty of
Ok _ ms ty -> Right ty
Fail err -> Left err
tcType :: Scope -> Type -> TcM Type
tcType scope ty@(DTyp hyps cat es) = do
(scope,hyps) <- tcHypos scope hyps
c_hyps <- lookupCatHyps cat
let m = length es
n = length c_hyps
if m == n
then do (delta,es) <- tcHypoExprs scope [] (zip es c_hyps)
return (DTyp hyps cat es)
else tcError (WrongCatArgs scope ty cat n m)
tcHypos :: Scope -> [Hypo] -> TcM (Scope,[Hypo])
tcHypos scope [] = return (scope,[])
tcHypos scope (h:hs) = do
(scope,h ) <- tcHypo scope h
(scope,hs) <- tcHypos scope hs
return (scope,h:hs)
tcHypo :: Scope -> Hypo -> TcM (Scope,Hypo)
tcHypo scope (Hyp ty) = do
ty <- tcType scope ty
return (scope,Hyp ty)
tcHypo scope (HypV x ty) = do
ty <- tcType scope ty
return (addScopedVar x (TTyp (scopeEnv scope) ty) scope,HypV x ty)
tcHypoExprs :: Scope -> Env -> [(Expr,Hypo)] -> TcM (Env,[Expr])
tcHypoExprs scope delta [] = return (delta,[])
tcHypoExprs scope delta ((e,h):xs) = do
(delta,e ) <- tcHypoExpr scope delta e h
(delta,es) <- tcHypoExprs scope delta xs
return (delta,e:es)
tcHypoExpr :: Scope -> Env -> Expr -> Hypo -> TcM (Env,Expr)
tcHypoExpr scope delta e (Hyp ty) = do
e <- tcExpr scope e (TTyp delta ty)
return (delta,e)
tcHypoExpr scope delta e (HypV x ty) = do
e <- tcExpr scope e (TTyp delta ty)
funs <- getFuns
return (eval funs (scopeEnv scope) e:delta,e)
-----------------------------------------------------
-- checkExpr
-----------------------------------------------------
checkExpr :: PGF -> Expr -> Type -> Either TcError Expr
checkExpr pgf e ty =
case unTcM (do e <- tcExpr emptyScope e (TTyp [] ty)
e <- refineExpr e
checkResolvedMetaStore emptyScope e
return e) (abstract pgf) 0 IntMap.empty of
Ok _ ms e -> Right e
Fail err -> Left err
tcExpr :: Scope -> Expr -> TType -> TcM Expr
tcExpr scope e0@(EAbs x e) tty =
case tty of
TTyp delta (DTyp (h:hs) c es) -> do e <- case h of
Hyp ty -> tcExpr (addScopedVar x (TTyp delta ty) scope)
e (TTyp delta (DTyp hs c es))
HypV y ty -> tcExpr (addScopedVar x (TTyp delta ty) scope)
e (TTyp ((VGen (scopeSize scope) []):delta) (DTyp hs c es))
return (EAbs x e)
_ -> do ty <- evalType (scopeSize scope) tty
tcError (NotFunType scope e0 ty)
tcExpr scope (EMeta _) tty = do
i <- newMeta scope
return (EMeta i)
tcExpr scope e0 tty = do
(e0,tty0) <- infExpr scope e0
i <- newGuardedMeta scope e0
eqType scope (scopeSize scope) i tty tty0
return (EMeta i)
-----------------------------------------------------
-- inferExpr
-----------------------------------------------------
inferExpr :: PGF -> Expr -> Either TcError (Expr,Type)
inferExpr pgf e =
case unTcM (do (e,tty) <- infExpr emptyScope e
e <- refineExpr e
checkResolvedMetaStore emptyScope e
ty <- evalType 0 tty
return (e,ty)) (abstract pgf) 1 IntMap.empty of
Ok _ ms (e,ty) -> Right (e,ty)
Fail err -> Left err
infExpr :: Scope -> Expr -> TcM (Expr,TType)
infExpr scope e0@(EApp e1 e2) = do
(e1,tty1) <- infExpr scope e1
case tty1 of
(TTyp delta1 (DTyp (h:hs) c es)) -> do (delta1,e2) <- tcHypoExpr scope delta1 e2 h
return (EApp e1 e2,TTyp delta1 (DTyp hs c es))
_ -> do ty1 <- evalType (scopeSize scope) tty1
tcError (NotFunType scope e1 ty1)
infExpr scope e0@(EFun x) = do
case lookupVar x scope of
Just (i,tty) -> return (EVar i,tty)
Nothing -> do tty <- lookupFunType x
return (e0,tty)
infExpr scope e0@(EVar i) = do
return (e0,snd (getVar i scope))
infExpr scope e0@(ELit l) = do
let cat = case l of
LStr _ -> mkCId "String"
LInt _ -> mkCId "Int"
LFlt _ -> mkCId "Float"
return (e0,TTyp [] (DTyp [] cat []))
infExpr scope (ETyped e ty) = do
ty <- tcType scope ty
e <- tcExpr scope e (TTyp (scopeEnv scope) ty)
return (ETyped e ty,TTyp (scopeEnv scope) ty)
infExpr scope e = tcError (CannotInferType scope e)
-----------------------------------------------------
-- eqType
-----------------------------------------------------
eqType :: Scope -> Int -> MetaId -> TType -> TType -> TcM ()
eqType scope k i0 tty1@(TTyp delta1 ty1@(DTyp hyps1 cat1 es1)) tty2@(TTyp delta2 ty2@(DTyp hyps2 cat2 es2))
| cat1 == cat2 = do (k,delta1,delta2) <- eqHyps k delta1 hyps1 delta2 hyps2
sequence_ [eqExpr k delta1 e1 delta2 e2 | (e1,e2) <- zip es1 es2]
| otherwise = raiseTypeMatchError
where
toPair (Hyp t) = (wildCId, type2expr t)
toPair (HypV x t) = (x, type2expr t)
raiseTypeMatchError = do ty1 <- evalType k tty1
ty2 <- evalType k tty2
e <- refineExpr (EMeta i0)
tcError (TypeMismatch scope e ty1 ty2)
type TCEnv = (Int,Env,Env)
eqHyps :: Int -> Env -> [Hypo] -> Env -> [Hypo] -> TcM (Int,Env,Env)
eqHyps k delta1 [] delta2 [] =
return (k,delta1,delta2)
eqHyps k delta1 (Hyp ty1 : h1s) delta2 (Hyp ty2 : h2s) = do
eqType scope k i0 (TTyp delta1 ty1) (TTyp delta2 ty2)
(k,delta1,delta2) <- eqHyps k delta1 h1s delta2 h2s
return (k,delta1,delta2)
eqHyps k delta1 (HypV x ty1 : h1s) delta2 (HypV y ty2 : h2s) = do
eqType scope k i0 (TTyp delta1 ty1) (TTyp delta2 ty2)
(k,delta1,delta2) <- eqHyps (k+1) ((VGen k []):delta1) h1s ((VGen k []):delta2) h2s
return (k,delta1,delta2)
eqHyps k delta1 h1s delta2 h2s = raiseTypeMatchError
eempty = Map.empty
eins = Map.insert
eqExpr :: Int -> Env -> Expr -> Env -> Expr -> TcM ()
eqExpr k env1 e1 env2 e2 = do
funs <- getFuns
eqValue k (eval funs env1 e1) (eval funs env2 e2)
emptyTCEnv :: TCEnv
emptyTCEnv = (0,eempty,eempty)
eqValue :: Int -> Value -> Value -> TcM ()
eqValue k v1 v2 = do
v1 <- deRef v1
v2 <- deRef v2
eqValue' k v1 v2
deRef v@(VMeta i env vs) = do
mv <- getMeta i
funs <- getFuns
case mv of
MBound e -> deRef (apply funs env e vs)
MGuarded e _ x | x == 0 -> deRef (apply funs env e vs)
| otherwise -> return v
MUnbound _ _ -> return v
deRef v = return v
eqValue' k (VSusp i env vs1 c) v2 = addConstraint i0 i env vs1 (\v1 -> eqValue k (c v1) v2)
eqValue' k v1 (VSusp i env vs2 c) = addConstraint i0 i env vs2 (\v2 -> eqValue k v1 (c v2))
eqValue' k (VMeta i env1 vs1) (VMeta j env2 vs2) | i == j = zipWithM_ (eqValue k) vs1 vs2
eqValue' k (VMeta i env1 vs1) v2 = do (MUnbound scopei cs) <- getMeta i
e2 <- mkLam i scopei env1 vs1 v2
sequence_ [c e2 | c <- cs]
setMeta i (MBound e2)
eqValue' k v1 (VMeta i env2 vs2) = do (MUnbound scopei cs) <- getMeta i
e1 <- mkLam i scopei env2 vs2 v1
sequence_ [c e1 | c <- cs]
setMeta i (MBound e1)
eqValue' k (VApp f1 vs1) (VApp f2 vs2) | f1 == f2 = zipWithM_ (eqValue k) vs1 vs2
eqValue' k (VLit l1) (VLit l2 ) | l1 == l2 = return ()
eqValue' k (VGen i vs1) (VGen j vs2) | i == j = zipWithM_ (eqValue k) vs1 vs2
eqValue' k (VClosure env1 (EAbs x1 e1)) (VClosure env2 (EAbs x2 e2)) = let v = VGen k []
in eqExpr (k+1) (v:env1) e1 (v:env2) e2
eqValue' k v1 v2 = raiseTypeMatchError
mkLam i scope env vs0 v = do
let k = scopeSize scope
vs = reverse (take k env) ++ vs0
xs = nub [i | VGen i [] <- vs]
if length vs == length xs
then return ()
else raiseTypeMatchError
v <- occurCheck i k xs v
funs <- getFuns
return (addLam vs0 (value2expr funs (length xs) v))
where
addLam [] e = e
addLam (v:vs) e = EAbs var (addLam vs e)
var = mkCId "v"
occurCheck i0 k xs (VApp f vs) = do vs <- mapM (occurCheck i0 k xs) vs
return (VApp f vs)
occurCheck i0 k xs (VLit l) = return (VLit l)
occurCheck i0 k xs (VMeta i env vs) = do if i == i0
then raiseTypeMatchError
else return ()
mv <- getMeta i
funs <- getFuns
case mv of
MBound e -> occurCheck i0 k xs (apply funs env e vs)
MGuarded e _ _ -> occurCheck i0 k xs (apply funs env e vs)
MUnbound scopei _ | scopeSize scopei > k -> raiseTypeMatchError
| otherwise -> do vs <- mapM (occurCheck i0 k xs) vs
return (VMeta i env vs)
occurCheck i0 k xs (VSusp i env vs cnt) = do addConstraint i0 i env vs (\v -> occurCheck i0 k xs (cnt v) >> return ())
return (VSusp i env vs cnt)
occurCheck i0 k xs (VGen i vs) = case List.findIndex (==i) xs of
Just i -> do vs <- mapM (occurCheck i0 k xs) vs
return (VGen i vs)
Nothing -> raiseTypeMatchError
occurCheck i0 k xs (VClosure env e) = do env <- mapM (occurCheck i0 k xs) env
return (VClosure env e)
-- this is not given in Expr
prValue = showExpr . value2expr
-----------------------------------------------------------
-- check for meta variables that still have to be resolved
-----------------------------------------------------------
value2expr v = case v of
VApp f vs -> foldl EApp (EVar f) (map value2expr vs)
VMeta i vs -> foldl EApp (EMeta i) (map value2expr vs)
VClosure g e -> e ----
VLit l -> ELit l
checkResolvedMetaStore :: Scope -> Expr -> TcM ()
checkResolvedMetaStore scope e = TcM (\abstr metaid ms ->
let xs = [i | (i,mv) <- IntMap.toList ms, not (isResolved mv)]
in if List.null xs
then Ok metaid ms ()
else Fail (UnresolvedMetaVars scope e xs))
where
isResolved (MUnbound _ []) = True
isResolved (MGuarded _ _ _) = True
isResolved (MBound _) = True
isResolved _ = False
prConstraints :: [(Value,Value)] -> String
prConstraints cs = unwords
["(" ++ prValue v ++ " <> " ++ prValue w ++ ")" | (v,w) <- cs]
-----------------------------------------------------
-- evalType
-----------------------------------------------------
-- work more on this: unification, compute,...
{-
splitConstraints :: PGF -> [(Value,Value)] -> ([(Int,Expr)],[(Value,Value)])
splitConstraints pgf = mkSplit . partition isSubst . regroup . map reorder . map reduce where
reorder (v,w) = case w of
VMeta _ _ -> (w,v)
_ -> (v,w)
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
regroup = groupBy (\x y -> fst x == fst y) . sort
isSubst cs@((v,u):_) = case v of
VMeta _ _ -> all ((==u) . snd) cs
_ -> False
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 null (eqValue (funs (abstract pgf)) 0 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
evalType :: Int -> TType -> TcM Type
evalType k (TTyp delta ty) = do funs <- getFuns
refineType (evalTy funs k delta ty)
where
evalTy sig k delta (DTyp hyps cat es) =
let ((k1,delta1),hyps1) = mapAccumL (evalHypo sig) (k,delta) hyps
in DTyp hyps1 cat (List.map (normalForm sig k1 delta1) es)
evalHypo sig (k,delta) (Hyp ty) = ((k, delta),Hyp (evalTy sig k delta ty))
evalHypo sig (k,delta) (HypV x ty) = ((k+1,(VGen k []):delta),HypV x (evalTy sig k delta ty))
evalHypo sig (k,delta) (HypI x ty) = ((k+1,(VGen k []):delta),HypI x (evalTy sig k delta ty))
metaSubst :: [(Int,Expr)] -> Expr -> Expr
metaSubst vs exp = case exp of
EApp u v -> EApp (subst u) (subst v)
EMeta i -> maybe exp id $ lookup i vs
EPi x a b -> EPi x (subst a) (subst b)
EAbs x b -> EAbs x (subst b)
_ -> exp
where
subst = metaSubst vs
-----------------------------------------------------
-- refinement
-----------------------------------------------------
--- use composOp and state monad...
newMetas :: Expr -> Expr
newMetas = fst . metas 0 where
metas i exp = case exp of
EAbs x e -> let (f,j) = metas i e in (EAbs x f, j)
EApp f a -> let (g,j) = metas i f ; (b,k) = metas j a in (EApp g b,k)
EMeta _ -> (EMeta i, i+1)
_ -> (exp,i)
refineExpr :: Expr -> TcM Expr
refineExpr e = TcM (\abstr metaid ms -> Ok metaid ms (refineExpr_ ms e))
refineExpr_ ms e = refine e
where
refine (EAbs x e) = EAbs x (refine e)
refine (EApp e1 e2) = EApp (refine e1) (refine e2)
refine (ELit l) = ELit l
refine (EMeta i) = case IntMap.lookup i ms of
Just (MBound e ) -> refine e
Just (MGuarded e _ _) -> refine e
_ -> EMeta i
refine (EFun f) = EFun f
refine (EVar i) = EVar i
refine (ETyped e ty) = ETyped (refine e) (refineType_ ms ty)
refineType :: Type -> TcM Type
refineType ty = TcM (\abstr metaid ms -> Ok metaid ms (refineType_ ms ty))
refineType_ ms (DTyp hyps cat es) = DTyp (List.map (refineHypo_ ms) hyps) cat (List.map (refineExpr_ ms) es)
refineHypo_ ms (Hyp ty) = Hyp (refineType_ ms ty)
refineHypo_ ms (HypV x ty) = HypV x (refineType_ ms ty)
refineHypo_ ms (HypI x ty) = HypI x (refineType_ ms ty)
value2expr sig i (VApp f vs) = foldl EApp (EFun f) (List.map (value2expr sig i) vs)
value2expr sig i (VGen j vs) = foldl EApp (EVar (i-j-1)) (List.map (value2expr sig i) vs)
value2expr sig i (VMeta j env vs) = foldl EApp (EMeta j) (List.map (value2expr sig i) vs)
value2expr sig i (VSusp j env vs k) = value2expr sig i (k (VGen j vs))
value2expr sig i (VLit l) = ELit l
value2expr sig i (VClosure env (EAbs x e)) = EAbs x (value2expr sig (i+1) (eval sig ((VGen i []):env) e))

View File

@@ -14,7 +14,7 @@ def g0 = g2 ;
fun g3 : Int -> (Int -> Int) ;
def g3 3 = g ;
fun const : Int -> Int -> Int ;
fun const : Float -> String -> Float ;
def const x _ = x ;
cat Nat ;

View File

@@ -1,34 +1,30 @@
i testsuite/runtime/eval/Test.gf
pt -compute \x -> x 1
pt -compute ? 1
pt -compute (\x -> x 1) ?
pt -compute unknown_var
pt -compute unknown_var 1
pt -compute 1 2
pt -compute \x -> x 1 : (Int->Int)->Int
pt -compute (? : Int -> Int) 1
pt -compute (\x -> x 1 : (Int->Int)->Int) ?
pt -compute f 1 2
pt -compute \x -> x
pt -compute ?666
pt -compute \x -> x : Nat -> Nat
pt -compute ? : String
pt -compute f
pt -compute (\x -> x 2) (f 1)
pt -compute (\x -> x 2) 1
pt -compute (\x -> x 2 : (Int->Int)->Int) (f 1)
pt -compute g 1
pt -compute g 0
pt -compute \x -> g x
pt -compute \x -> g x : Int -> Int
pt -compute g ?
pt -compute (\x -> x 5) (g2 1)
pt -compute (\x -> x 3) (\x -> x)
pt -compute (\x -> x 5 : (Int->Int)->Int) (g2 1)
pt -compute (\x -> x 3 : (Int->Int)->Int) (\x -> x)
pt -compute g0
pt -compute (\x -> x 3.2) (\x -> f x)
pt -compute g0 2.3
pt -compute g0 ((\x -> f x) 0) 1
pt -compute (\x -> x 32 : (Int -> Int -> Int) -> Int -> Int) (\x -> f x : Int -> Int -> Int)
pt -compute g0 23
pt -compute const 3.14 "pi"
pt -compute dec (succ (succ zero))
pt -compute dec (succ ?)
pt -compute \x -> dec x
pt -compute \x -> dec x : Nat -> Nat
pt -compute dec ?
pt -compute (\f -> f 0) (g3 ?)
pt -compute (\f -> f 0 : (Int -> Int) -> Int) (g3 ?)
pt -compute g (g2 ? 0)
pt -compute plus (succ zero) (succ zero)
pt -compute dec2 0 (succ zero)
pt -compute dec2 0 err
pt -compute plus err (succ zero)

View File

@@ -1,30 +1,26 @@
\v0 -> v0 1
\x -> x 1
? 1
?1 1
? 1
?3 1
f 1 2
\x -> x
?1
?666
f
@@ -32,29 +28,29 @@ g ?
f 1 2
f 1 2
literal of function type
2
g 0
g 0
\x -> g x
\v0 -> g v0
g ?1
g ?
5
3

View File

@@ -1,10 +1,10 @@
\v0 -> v0
\x -> x
1
1
\x -> x

View File

@@ -0,0 +1,37 @@
abstract Test = {
cat Nat ;
data zero : Nat ;
succ : Nat -> Nat ;
fun plus : Nat -> Nat -> Nat ;
def plus zero n = n ;
plus (succ m) n = plus m (succ n) ;
cat Vector Nat ;
fun vector : (n : Nat) -> Vector n ;
fun append : (m,n : Nat) -> Vector m -> Vector n -> Vector (plus m n) ;
fun diff : (m,n : Nat) -> Vector (plus m n) -> Vector m -> Vector n ;
cat Morph (Nat -> Nat) ;
fun mkMorph : (f : Nat -> Nat) -> Morph f ;
fun mkMorph2 : (f : Nat -> Nat) -> Vector (f zero) -> Morph f ;
fun idMorph : Morph (\x -> x) -> Nat ;
fun f0 : (n : Nat) -> ((m : Nat) -> Vector n) -> Int ;
fun f1 : (n : Nat -> Nat) -> ((m : Nat) -> Vector (n m)) -> Int ;
fun cmpVector : (n : Nat) -> Vector n -> Vector n -> Int ;
fun g : ((n : Nat) -> Vector n) -> Int ;
cat U (n,m : Nat) ;
fun u0 : (n : Nat) -> U n n ;
fun u1 : (n : Nat) -> U n (succ n) ;
fun h : (n : Nat) -> U n n -> Int ;
-- fun u2 : (n : Nat) -> U (plus n zero) zero ;
-- fun h2 : (f : Nat -> Nat) -> ((n : Nat) -> U (f n) (f zero)) -> Int ;
}

View File

@@ -0,0 +1,30 @@
i testsuite/runtime/typecheck/Test.gf
ai succ "0"
ai succ : Int 0
ai 1 2
ai (\x -> x 2 : (Int->Int)->Int) 1
ai unknown_fun
ai 0 : unknown_cat
ai \x -> x
ai \x -> x : Int
ai append (succ (succ zero)) (succ zero) (vector (succ (succ zero))) (vector (succ zero))
ai \m,n -> vector (plus m n) : (m,n : Nat) -> Vector (plus m n)
ai mkMorph (\x -> succ zero)
ai idMorph (mkMorph (\x -> x))
ai idMorph (mkMorph (\x -> succ zero))
ai append zero (succ zero) : Vector zero -> Vector (succ zero) -> Vector (succ zero)
ai \n,v1,n,v2 -> append ? ? v1 v2 : (n : Nat) -> Vector n -> (m : Nat) -> Vector m -> Vector (plus n m)
ai \n -> (\v1,v2 -> eqVector n v1 v2 : Vector ? -> Vector ? -> EQ) (vector ?) : (n : Nat) -> Vector n -> EQ
ai (\v1,v2 -> cmpVector ? v1 v2 : Vector ? -> Vector ? -> Int) (vector ?)
ai f0 ? vector
ai f1 ? vector
ai f1 ? (\x -> vector (succ x))
ai mkMorph (\x -> cmpVector ? (vector x) (vector (succ x)))
ai g (\n -> vector (succ n))
ai h ? (u0 ?)
ai h ? (u1 ?)
ai cmpVector (succ (succ zero)) (vector (succ (succ zero))) (append ? (succ zero) (vector ?) (vector (succ zero)))
ai diff ? (succ (succ zero)) (vector (succ (succ (succ (succ (succ zero)))))) (vector (succ (succ (succ zero))))
ai diff ? (succ (succ zero)) (vector (succ (succ (succ (succ zero))))) (vector (succ (succ (succ zero))))
ai idMorph (mkMorph2 (\x -> ?) (vector zero))

View File

@@ -0,0 +1,102 @@
Couldn't match expected type Nat
against inferred type String
In the expression: "0"
Category Int should have 0 argument(s), but has been given 1
In the type: Int 0
A function type is expected for the expression 1 instead of type Int
Couldn't match expected type Int -> Int
against inferred type Int
In the expression: 1
Function unknown_fun is not in scope
Category unknown_cat is not in scope
Cannot infer the type of expression \x -> x
A function type is expected for the expression \x -> x instead of type Int
Expression: append (succ (succ zero)) (succ zero) (vector (succ (succ zero))) (vector (succ zero))
Type: Vector (plus (succ (succ zero)) (succ zero))
Expression: \m, n -> vector (plus m n) : (m : Nat) -> (n : Nat) -> Vector (plus m n)
Type: (m : Nat) -> (n : Nat) -> Vector (plus m n)
Expression: mkMorph (\x -> succ zero)
Type: Morph (\x -> succ zero)
Expression: idMorph (mkMorph (\x -> x))
Type: Nat
Couldn't match expected type Morph (\x -> x)
against inferred type Morph (\x -> succ zero)
In the expression: mkMorph (\x -> succ zero)
Expression: append zero (succ zero) : Vector zero -> Vector (succ zero) -> Vector (succ zero)
Type: Vector zero -> Vector (succ zero) -> Vector (succ zero)
Expression: \n, v1, n'1, v2 -> append n n'1 v1 v2 : (n : Nat) -> Vector n -> (m : Nat) -> Vector m -> Vector (plus n m)
Type: (n : Nat) -> Vector n -> (m : Nat) -> Vector m -> Vector (plus n m)