forked from GitHub/gf-core
now in the command shell the primary type in the pipe is Expr not Tree. This makes the pt -compute and pt -typecheck more interesting
This commit is contained in:
@@ -25,7 +25,7 @@ data Value
|
|||||||
deriving (Eq,Ord,Show)
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
data Argument
|
data Argument
|
||||||
= ATree Tree
|
= AExpr Expr
|
||||||
| ANoArg
|
| ANoArg
|
||||||
| AMacro Ident
|
| AMacro Ident
|
||||||
deriving (Eq,Ord,Show)
|
deriving (Eq,Ord,Show)
|
||||||
|
|||||||
@@ -39,10 +39,10 @@ import Text.PrettyPrint
|
|||||||
|
|
||||||
import Debug.Trace
|
import Debug.Trace
|
||||||
|
|
||||||
type CommandOutput = ([Tree],String) ---- errors, etc
|
type CommandOutput = ([Expr],String) ---- errors, etc
|
||||||
|
|
||||||
data CommandInfo = CommandInfo {
|
data CommandInfo = CommandInfo {
|
||||||
exec :: [Option] -> [Tree] -> IO CommandOutput,
|
exec :: [Option] -> [Expr] -> IO CommandOutput,
|
||||||
synopsis :: String,
|
synopsis :: String,
|
||||||
syntax :: String,
|
syntax :: String,
|
||||||
explanation :: String,
|
explanation :: String,
|
||||||
@@ -117,8 +117,9 @@ allCommands cod env@(pgf, mos) = Map.fromList [
|
|||||||
"by the flag. The target format is postscript, unless overridden by the",
|
"by the flag. The target format is postscript, unless overridden by the",
|
||||||
"flag -format."
|
"flag -format."
|
||||||
],
|
],
|
||||||
exec = \opts ts -> do
|
exec = \opts es -> do
|
||||||
let grph = if null ts then [] else alignLinearize pgf (head ts)
|
let ts = toTrees es
|
||||||
|
grph = if null ts then [] else alignLinearize pgf (head ts)
|
||||||
if isFlag "view" opts || isFlag "format" opts then do
|
if isFlag "view" opts || isFlag "format" opts then do
|
||||||
let file s = "_grph." ++ s
|
let file s = "_grph." ++ s
|
||||||
let view = optViewGraph opts ++ " "
|
let view = optViewGraph opts ++ " "
|
||||||
@@ -261,7 +262,7 @@ allCommands cod env@(pgf, mos) = Map.fromList [
|
|||||||
_ | isOpt "changes" opts -> changesMsg
|
_ | isOpt "changes" opts -> changesMsg
|
||||||
_ | isOpt "coding" opts -> codingMsg
|
_ | isOpt "coding" opts -> codingMsg
|
||||||
_ | isOpt "license" opts -> licenseMsg
|
_ | isOpt "license" opts -> licenseMsg
|
||||||
[t] -> let co = getCommandOp (showTree t) in
|
[t] -> let co = getCommandOp (showExpr t) in
|
||||||
case lookCommand co (allCommands cod env) of ---- new map ??!!
|
case lookCommand co (allCommands cod env) of ---- new map ??!!
|
||||||
Just info -> commandHelp True (co,info)
|
Just info -> commandHelp True (co,info)
|
||||||
_ -> "command not found"
|
_ -> "command not found"
|
||||||
@@ -306,7 +307,7 @@ allCommands cod env@(pgf, mos) = Map.fromList [
|
|||||||
"gr -lang=LangHin -cat=Cl | l -table -to_devanagari -to_utf8 -- hindi table",
|
"gr -lang=LangHin -cat=Cl | l -table -to_devanagari -to_utf8 -- hindi table",
|
||||||
"l -unlexer=\"LangSwe=to_utf8 LangHin=to_devanagari,to_utf8\" -- different lexers"
|
"l -unlexer=\"LangSwe=to_utf8 LangHin=to_devanagari,to_utf8\" -- different lexers"
|
||||||
],
|
],
|
||||||
exec = \opts -> return . fromStrings . map (optLin opts),
|
exec = \opts -> return . fromStrings . map (optLin opts) . toTrees,
|
||||||
options = [
|
options = [
|
||||||
("all","show all forms and variants"),
|
("all","show all forms and variants"),
|
||||||
("bracket","show tree structure with brackets and paths to nodes"),
|
("bracket","show tree structure with brackets and paths to nodes"),
|
||||||
@@ -443,7 +444,7 @@ allCommands cod env@(pgf, mos) = Map.fromList [
|
|||||||
"pt -compute (plus one two) -- compute value",
|
"pt -compute (plus one two) -- compute value",
|
||||||
"p \"foo\" | pt -typecheck -- type check parse results"
|
"p \"foo\" | pt -typecheck -- type check parse results"
|
||||||
],
|
],
|
||||||
exec = \opts -> returnFromTrees . treeOps (map prOpt opts),
|
exec = \opts -> returnFromExprs . treeOps (map prOpt opts),
|
||||||
options = treeOpOptions pgf
|
options = treeOpOptions pgf
|
||||||
}),
|
}),
|
||||||
("q", emptyCommandInfo {
|
("q", emptyCommandInfo {
|
||||||
@@ -464,7 +465,7 @@ allCommands cod env@(pgf, mos) = Map.fromList [
|
|||||||
("lines","return the list of lines, instead of the singleton of all contents"),
|
("lines","return the list of lines, instead of the singleton of all contents"),
|
||||||
("tree","convert strings into trees")
|
("tree","convert strings into trees")
|
||||||
],
|
],
|
||||||
exec = \opts arg -> do
|
exec = \opts _ -> do
|
||||||
let file = valStrOpts "file" "_gftmp" opts
|
let file = valStrOpts "file" "_gftmp" opts
|
||||||
s <- readFile file
|
s <- readFile file
|
||||||
return $ case opts of
|
return $ case opts of
|
||||||
@@ -524,7 +525,7 @@ allCommands cod env@(pgf, mos) = Map.fromList [
|
|||||||
("ut", emptyCommandInfo {
|
("ut", emptyCommandInfo {
|
||||||
longname = "unicode_table",
|
longname = "unicode_table",
|
||||||
synopsis = "show a transliteration table for a unicode character set",
|
synopsis = "show a transliteration table for a unicode character set",
|
||||||
exec = \opts arg -> do
|
exec = \opts _ -> do
|
||||||
let t = concatMap prOpt (take 1 opts)
|
let t = concatMap prOpt (take 1 opts)
|
||||||
let out = maybe "no such transliteration" characterTable $ transliteration t
|
let out = maybe "no such transliteration" characterTable $ transliteration t
|
||||||
return $ fromString out,
|
return $ fromString out,
|
||||||
@@ -548,8 +549,9 @@ allCommands cod env@(pgf, mos) = Map.fromList [
|
|||||||
"by the flag. The target format is postscript, unless overridden by the",
|
"by the flag. The target format is postscript, unless overridden by the",
|
||||||
"flag -format."
|
"flag -format."
|
||||||
],
|
],
|
||||||
exec = \opts ts -> do
|
exec = \opts es -> do
|
||||||
let funs = not (isOpt "nofun" opts)
|
let ts = toTrees es
|
||||||
|
funs = not (isOpt "nofun" opts)
|
||||||
let cats = not (isOpt "nocat" opts)
|
let cats = not (isOpt "nocat" opts)
|
||||||
let grph = visualizeTrees pgf (funs,cats) ts -- True=digraph
|
let grph = visualizeTrees pgf (funs,cats) ts -- True=digraph
|
||||||
if isFlag "view" opts || isFlag "format" opts then do
|
if isFlag "view" opts || isFlag "format" opts then do
|
||||||
@@ -599,7 +601,7 @@ allCommands cod env@(pgf, mos) = Map.fromList [
|
|||||||
],
|
],
|
||||||
exec = \opts arg -> do
|
exec = \opts arg -> do
|
||||||
case arg of
|
case arg of
|
||||||
[Fun id []] -> case Map.lookup id (funs (abstract pgf)) of
|
[EVar id] -> case Map.lookup id (funs (abstract pgf)) of
|
||||||
Just (ty,_,eqs) -> return $ fromString $
|
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
|
if null eqs
|
||||||
@@ -679,16 +681,21 @@ allCommands cod env@(pgf, mos) = Map.fromList [
|
|||||||
optNum opts = valIntOpts "number" 1 opts
|
optNum opts = valIntOpts "number" 1 opts
|
||||||
optNumInf opts = valIntOpts "number" 1000000000 opts ---- 10^9
|
optNumInf opts = valIntOpts "number" 1000000000 opts ---- 10^9
|
||||||
|
|
||||||
fromTrees ts = (ts,unlines (map showTree ts))
|
fromTrees ts = (map tree2expr ts,unlines (map showTree ts))
|
||||||
fromStrings ss = (map (Lit . LStr) ss, unlines ss)
|
fromStrings ss = (map (ELit . LStr) ss, unlines ss)
|
||||||
fromString s = ([Lit (LStr s)], s)
|
fromString s = ([ELit (LStr s)], s)
|
||||||
|
toTrees = map expr2tree
|
||||||
toStrings = map showAsString
|
toStrings = map showAsString
|
||||||
toString = unwords . toStrings
|
toString = unwords . toStrings
|
||||||
|
|
||||||
returnFromTrees ts = return $ case ts of
|
returnFromTrees ts = return $ case ts of
|
||||||
[] -> (ts, "no trees found")
|
[] -> ([], "no trees found")
|
||||||
_ -> fromTrees ts
|
_ -> fromTrees ts
|
||||||
|
|
||||||
|
returnFromExprs es = return $ case es of
|
||||||
|
[] -> ([], "no trees found")
|
||||||
|
_ -> (es,unlines (map showExpr es))
|
||||||
|
|
||||||
prGrammar opts
|
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 "fullform" opts = return $ fromString $ concatMap (prFullFormLexicon . morpho) $ optLangs opts
|
||||||
@@ -715,8 +722,8 @@ allCommands cod env@(pgf, mos) = Map.fromList [
|
|||||||
app f = maybe id id (treeOp pgf f)
|
app f = maybe id id (treeOp pgf f)
|
||||||
|
|
||||||
showAsString t = case t of
|
showAsString t = case t of
|
||||||
Lit (LStr s) -> s
|
ELit (LStr s) -> s
|
||||||
_ -> "\n" ++ showTree t --- newline needed in other cases than the first
|
_ -> "\n" ++ showExpr t --- newline needed in other cases than the first
|
||||||
|
|
||||||
stringOpOptions = [
|
stringOpOptions = [
|
||||||
("bind","bind tokens separated by Prelude.BIND, i.e. &+"),
|
("bind","bind tokens separated by Prelude.BIND, i.e. &+"),
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ data CommandEnv = CommandEnv {
|
|||||||
morphos :: Map.Map Language Morpho,
|
morphos :: Map.Map Language Morpho,
|
||||||
commands :: Map.Map String CommandInfo,
|
commands :: Map.Map String CommandInfo,
|
||||||
commandmacros :: Map.Map String CommandLine,
|
commandmacros :: Map.Map String CommandLine,
|
||||||
expmacros :: Map.Map String Tree
|
expmacros :: Map.Map String Expr
|
||||||
}
|
}
|
||||||
|
|
||||||
mkCommandEnv :: Encoding -> PGF -> CommandEnv
|
mkCommandEnv :: Encoding -> PGF -> CommandEnv
|
||||||
@@ -72,18 +72,20 @@ interpretPipe enc env cs = do
|
|||||||
appLine es = map (map (appCommand es))
|
appLine es = map (map (appCommand es))
|
||||||
|
|
||||||
-- macro definition applications: replace ?i by (exps !! i)
|
-- macro definition applications: replace ?i by (exps !! i)
|
||||||
appCommand :: [Tree] -> Command -> Command
|
appCommand :: [Expr] -> Command -> Command
|
||||||
appCommand xs c@(Command i os arg) = case arg of
|
appCommand xs c@(Command i os arg) = case arg of
|
||||||
ATree e -> Command i os (ATree (app e))
|
AExpr e -> Command i os (AExpr (app e))
|
||||||
_ -> c
|
_ -> c
|
||||||
where
|
where
|
||||||
app e = case e of
|
app e = case e of
|
||||||
Meta i -> xs !! i
|
EAbs x e -> EAbs x (app e)
|
||||||
Fun f as -> Fun f (map app as)
|
EApp e1 e2 -> EApp (app e1) (app e2)
|
||||||
Abs x b -> Abs x (app b)
|
ELit l -> ELit l
|
||||||
|
EMeta i -> xs !! i
|
||||||
|
EVar x -> EVar x
|
||||||
|
|
||||||
-- return the trees to be sent in pipe, and the output possibly printed
|
-- return the trees to be sent in pipe, and the output possibly printed
|
||||||
interpret :: (String -> String) -> CommandEnv -> [Tree] -> Command -> IO CommandOutput
|
interpret :: (String -> String) -> CommandEnv -> [Expr] -> Command -> IO CommandOutput
|
||||||
interpret enc env trees0 comm = case lookCommand co comms of
|
interpret enc env trees0 comm = case lookCommand co comms of
|
||||||
Just info -> do
|
Just info -> do
|
||||||
checkOpts info
|
checkOpts info
|
||||||
@@ -108,15 +110,15 @@ interpret enc env trees0 comm = case lookCommand co comms of
|
|||||||
|
|
||||||
-- analyse command parse tree to a uniform datastructure, normalizing comm name
|
-- analyse command parse tree to a uniform datastructure, normalizing comm name
|
||||||
--- the env is needed for macro lookup
|
--- the env is needed for macro lookup
|
||||||
getCommand :: CommandEnv -> Command -> [Tree] -> (String,[Option],[Tree])
|
getCommand :: CommandEnv -> Command -> [Expr] -> (String,[Option],[Expr])
|
||||||
getCommand env co@(Command c opts arg) ts =
|
getCommand env co@(Command c opts arg) ts =
|
||||||
(getCommandOp c,opts,getCommandArg env arg ts)
|
(getCommandOp c,opts,getCommandArg env arg ts)
|
||||||
|
|
||||||
getCommandArg :: CommandEnv -> Argument -> [Tree] -> [Tree]
|
getCommandArg :: CommandEnv -> Argument -> [Expr] -> [Expr]
|
||||||
getCommandArg env a ts = case a of
|
getCommandArg env a ts = case a of
|
||||||
AMacro m -> case Map.lookup m (expmacros env) of
|
AMacro m -> case Map.lookup m (expmacros env) of
|
||||||
Just t -> [t]
|
Just t -> [t]
|
||||||
_ -> []
|
_ -> []
|
||||||
ATree t -> [t] -- ignore piped
|
AExpr t -> [t] -- ignore piped
|
||||||
ANoArg -> ts -- use piped
|
ANoArg -> ts -- use piped
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ pFilename = liftM2 (:) (RP.satisfy isFileFirst) (RP.munch (not . isSpace)) where
|
|||||||
|
|
||||||
pArgument =
|
pArgument =
|
||||||
RP.option ANoArg
|
RP.option ANoArg
|
||||||
(fmap ATree (pTree False)
|
(fmap AExpr pExpr
|
||||||
RP.<++
|
RP.<++
|
||||||
(RP.munch isSpace >> RP.char '%' >> fmap AMacro pIdent))
|
(RP.munch isSpace >> RP.char '%' >> fmap AMacro pIdent))
|
||||||
|
|
||||||
|
|||||||
@@ -6,13 +6,9 @@ module GF.Command.TreeOperations (
|
|||||||
import GF.Compile.TypeCheck
|
import GF.Compile.TypeCheck
|
||||||
import PGF
|
import PGF
|
||||||
|
|
||||||
--import GF.Compile.GrammarToGFCC (mkType,mkExp)
|
|
||||||
import qualified GF.Grammar.Grammar as G
|
|
||||||
import qualified GF.Grammar.Macros as M
|
|
||||||
|
|
||||||
import Data.List
|
import Data.List
|
||||||
|
|
||||||
type TreeOp = [Tree] -> [Tree]
|
type TreeOp = [Expr] -> [Expr]
|
||||||
|
|
||||||
treeOp :: PGF -> String -> Maybe TreeOp
|
treeOp :: PGF -> String -> Maybe TreeOp
|
||||||
treeOp pgf f = fmap snd $ lookup f $ allTreeOps pgf
|
treeOp pgf f = fmap snd $ lookup f $ allTreeOps pgf
|
||||||
@@ -20,20 +16,20 @@ treeOp pgf f = fmap snd $ lookup f $ allTreeOps pgf
|
|||||||
allTreeOps :: PGF -> [(String,(String,TreeOp))]
|
allTreeOps :: PGF -> [(String,(String,TreeOp))]
|
||||||
allTreeOps pgf = [
|
allTreeOps pgf = [
|
||||||
("compute",("compute by using semantic definitions (def)",
|
("compute",("compute by using semantic definitions (def)",
|
||||||
map (expr2tree pgf . tree2expr))),
|
map (compute pgf))),
|
||||||
("paraphrase",("paraphrase by using semantic definitions (def)",
|
("paraphrase",("paraphrase by using semantic definitions (def)",
|
||||||
nub . concatMap (paraphrase pgf))),
|
map tree2expr . nub . concatMap (paraphrase pgf . expr2tree))),
|
||||||
("smallest",("sort trees from smallest to largest, in number of nodes",
|
("smallest",("sort trees from smallest to largest, in number of nodes",
|
||||||
smallest)),
|
smallest)),
|
||||||
("typecheck",("type check and solve metavariables; reject if incorrect",
|
("typecheck",("type check and solve metavariables; reject if incorrect",
|
||||||
concatMap (typecheck pgf)))
|
concatMap (typecheck pgf)))
|
||||||
]
|
]
|
||||||
|
|
||||||
smallest :: [Tree] -> [Tree]
|
smallest :: [Expr] -> [Expr]
|
||||||
smallest = sortBy (\t u -> compare (size t) (size u)) where
|
smallest = sortBy (\t u -> compare (size t) (size u)) where
|
||||||
size t = case t of
|
size t = case t of
|
||||||
Abs _ b -> size b + 1
|
EAbs _ e -> size e + 1
|
||||||
Fun f ts -> sum (map size ts) + 1
|
EApp e1 e2 -> size e1 + size e2 + 1
|
||||||
_ -> 1
|
_ -> 1
|
||||||
|
|
||||||
{-
|
{-
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ loop opts gfenv0 = do
|
|||||||
_ -> putStrLn "command definition not parsed" >> loopNewCPU gfenv
|
_ -> putStrLn "command definition not parsed" >> loopNewCPU gfenv
|
||||||
|
|
||||||
"dt":f:ws -> do
|
"dt":f:ws -> do
|
||||||
case readTree (unwords ws) of
|
case readExpr (unwords ws) of
|
||||||
Just exp -> loopNewCPU $ gfenv {
|
Just exp -> loopNewCPU $ gfenv {
|
||||||
commandenv = env {
|
commandenv = env {
|
||||||
expmacros = Map.insert f exp (expmacros env)
|
expmacros = Map.insert f exp (expmacros env)
|
||||||
|
|||||||
11
src/PGF.hs
11
src/PGF.hs
@@ -48,7 +48,7 @@ module PGF(
|
|||||||
parse, canParse, parseAllLang, parseAll,
|
parse, canParse, parseAllLang, parseAll,
|
||||||
|
|
||||||
-- ** Evaluation
|
-- ** Evaluation
|
||||||
tree2expr, PGF.expr2tree, paraphrase, typecheck,
|
tree2expr, expr2tree, PGF.compute, paraphrase, typecheck,
|
||||||
|
|
||||||
-- ** Word Completion (Incremental Parsing)
|
-- ** Word Completion (Incremental Parsing)
|
||||||
complete,
|
complete,
|
||||||
@@ -287,9 +287,6 @@ complete pgf from typ input =
|
|||||||
| otherwise = (init ws, last ws)
|
| otherwise = (init ws, last ws)
|
||||||
where ws = words s
|
where ws = words s
|
||||||
|
|
||||||
-- | Converts an expression to tree. The expression
|
-- | Converts an expression to normal form
|
||||||
-- is first reduced to beta-eta-alfa normal form and
|
compute :: PGF -> Expr -> Expr
|
||||||
-- after that converted to tree. The function definitions
|
compute pgf = PGF.Data.normalForm (funs (abstract pgf))
|
||||||
-- are used in the computation.
|
|
||||||
expr2tree :: PGF -> Expr -> Tree
|
|
||||||
expr2tree pgf = PGF.Data.expr2tree (funs (abstract pgf))
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ module PGF.Expr(Tree(..), Literal(..),
|
|||||||
Expr(..), Patt(..), Equation(..),
|
Expr(..), Patt(..), Equation(..),
|
||||||
readExpr, showExpr, pExpr, ppExpr, ppPatt,
|
readExpr, showExpr, pExpr, ppExpr, ppPatt,
|
||||||
|
|
||||||
tree2expr, expr2tree,
|
tree2expr, expr2tree, normalForm,
|
||||||
|
|
||||||
-- needed in the typechecker
|
-- needed in the typechecker
|
||||||
Value(..), Env, eval, apply, eqValue,
|
Value(..), Env, eval, apply, eqValue,
|
||||||
@@ -42,9 +42,7 @@ data Tree =
|
|||||||
deriving (Eq, Ord)
|
deriving (Eq, Ord)
|
||||||
|
|
||||||
-- | An expression represents a potentially unevaluated expression
|
-- | An expression represents a potentially unevaluated expression
|
||||||
-- in the abstract syntax of the grammar. It can be evaluated with
|
-- in the abstract syntax of the grammar.
|
||||||
-- the 'expr2tree' function and then linearized or it can be used
|
|
||||||
-- directly in the dependent types.
|
|
||||||
data Expr =
|
data Expr =
|
||||||
EAbs CId Expr -- ^ lambda abstraction
|
EAbs CId Expr -- ^ lambda abstraction
|
||||||
| EApp Expr Expr -- ^ application
|
| EApp Expr Expr -- ^ application
|
||||||
@@ -111,7 +109,7 @@ pTrees :: RP.ReadP [Tree]
|
|||||||
pTrees = liftM2 (:) (pTree True) pTrees RP.<++ (RP.skipSpaces >> return [])
|
pTrees = liftM2 (:) (pTree True) pTrees RP.<++ (RP.skipSpaces >> return [])
|
||||||
|
|
||||||
pTree :: Bool -> RP.ReadP Tree
|
pTree :: Bool -> RP.ReadP Tree
|
||||||
pTree isNested = RP.skipSpaces >> (pParen RP.<++ pAbs RP.<++ pApp RP.<++ fmap Lit pLit RP.<++ pMeta)
|
pTree isNested = RP.skipSpaces >> (pParen RP.<++ pAbs RP.<++ pApp RP.<++ fmap Lit pLit RP.<++ fmap Meta pMeta)
|
||||||
where
|
where
|
||||||
pParen = RP.between (RP.char '(') (RP.char ')') (pTree False)
|
pParen = RP.between (RP.char '(') (RP.char ')') (pTree False)
|
||||||
pAbs = do xs <- RP.between (RP.char '\\') (RP.skipSpaces >> RP.string "->") (RP.sepBy1 (RP.skipSpaces >> pCId) (RP.skipSpaces >> RP.char ','))
|
pAbs = do xs <- RP.between (RP.char '\\') (RP.skipSpaces >> RP.string "->") (RP.sepBy1 (RP.skipSpaces >> pCId) (RP.skipSpaces >> RP.char ','))
|
||||||
@@ -120,9 +118,6 @@ pTree isNested = RP.skipSpaces >> (pParen RP.<++ pAbs RP.<++ pApp RP.<++ fmap Li
|
|||||||
pApp = do f <- pCId
|
pApp = do f <- pCId
|
||||||
ts <- (if isNested then return [] else pTrees)
|
ts <- (if isNested then return [] else pTrees)
|
||||||
return (Fun f ts)
|
return (Fun f ts)
|
||||||
pMeta = do RP.char '?'
|
|
||||||
n <- fmap read (RP.munch1 isDigit)
|
|
||||||
return (Meta n)
|
|
||||||
|
|
||||||
pExpr :: RP.ReadP Expr
|
pExpr :: RP.ReadP Expr
|
||||||
pExpr = RP.skipSpaces >> (pAbs RP.<++ pTerm)
|
pExpr = RP.skipSpaces >> (pAbs RP.<++ pTerm)
|
||||||
@@ -135,12 +130,14 @@ pExpr = RP.skipSpaces >> (pAbs RP.<++ pTerm)
|
|||||||
|
|
||||||
pFactor = fmap EVar pCId
|
pFactor = fmap EVar pCId
|
||||||
RP.<++ fmap ELit pLit
|
RP.<++ fmap ELit pLit
|
||||||
RP.<++ pMeta
|
RP.<++ fmap EMeta pMeta
|
||||||
RP.<++ RP.between (RP.char '(') (RP.char ')') pExpr
|
RP.<++ RP.between (RP.char '(') (RP.char ')') pExpr
|
||||||
where
|
|
||||||
pMeta = do RP.char '?'
|
pMeta = do RP.char '?'
|
||||||
n <- fmap read (RP.munch1 isDigit)
|
cs <- RP.look
|
||||||
return (EMeta n)
|
case cs of
|
||||||
|
(c:_) | isDigit c -> fmap read (RP.munch1 isDigit)
|
||||||
|
_ -> return 0
|
||||||
|
|
||||||
pLit :: RP.ReadP Literal
|
pLit :: RP.ReadP Literal
|
||||||
pLit = pNum RP.<++ liftM LStr pStr
|
pLit = pNum RP.<++ liftM LStr pStr
|
||||||
@@ -166,7 +163,7 @@ ppTree d (Abs xs t) = ppParens (d > 0) (PP.char '\\' PP.<>
|
|||||||
ppTree d (Fun f []) = PP.text (prCId f)
|
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 (map (ppTree 1) ts))
|
||||||
ppTree d (Lit l) = ppLit l
|
ppTree d (Lit l) = ppLit l
|
||||||
ppTree d (Meta n) = PP.char '?' PP.<> PP.int n
|
ppTree d (Meta n) = ppMeta n
|
||||||
ppTree d (Var id) = PP.text (prCId id)
|
ppTree d (Var id) = PP.text (prCId id)
|
||||||
|
|
||||||
|
|
||||||
@@ -181,7 +178,7 @@ ppExpr d (EAbs x e) = let (xs,e1) = getVars (EAbs x e)
|
|||||||
getVars e = ([],e)
|
getVars e = ([],e)
|
||||||
ppExpr d (EApp e1 e2) = ppParens (d > 1) ((ppExpr 1 e1) PP.<+> (ppExpr 2 e2))
|
ppExpr d (EApp e1 e2) = ppParens (d > 1) ((ppExpr 1 e1) PP.<+> (ppExpr 2 e2))
|
||||||
ppExpr d (ELit l) = ppLit l
|
ppExpr d (ELit l) = ppLit l
|
||||||
ppExpr d (EMeta n) = PP.char '?' PP.<+> PP.int n
|
ppExpr d (EMeta n) = ppMeta n
|
||||||
ppExpr d (EVar f) = PP.text (prCId f)
|
ppExpr d (EVar f) = PP.text (prCId f)
|
||||||
|
|
||||||
ppPatt d (PApp f ps) = ppParens (d > 1) (PP.text (prCId f) PP.<+> PP.hsep (map (ppPatt 2) ps))
|
ppPatt d (PApp f ps) = ppParens (d > 1) (PP.text (prCId f) PP.<+> PP.hsep (map (ppPatt 2) ps))
|
||||||
@@ -193,15 +190,20 @@ ppLit (LStr s) = PP.text (show s)
|
|||||||
ppLit (LInt n) = PP.integer n
|
ppLit (LInt n) = PP.integer n
|
||||||
ppLit (LFlt d) = PP.double d
|
ppLit (LFlt d) = PP.double d
|
||||||
|
|
||||||
|
ppMeta n
|
||||||
|
| n == 0 = PP.char '?'
|
||||||
|
| otherwise = PP.char '?' PP.<> PP.int n
|
||||||
|
|
||||||
ppParens True = PP.parens
|
ppParens True = PP.parens
|
||||||
ppParens False = id
|
ppParens False = id
|
||||||
|
|
||||||
|
|
||||||
-----------------------------------------------------
|
-----------------------------------------------------
|
||||||
-- Evaluation
|
-- Conversion Expr <-> Tree
|
||||||
-----------------------------------------------------
|
-----------------------------------------------------
|
||||||
|
|
||||||
-- | Converts a tree to expression.
|
-- | Converts a tree to expression. The conversion
|
||||||
|
-- is always total, every tree is a valid expression.
|
||||||
tree2expr :: Tree -> Expr
|
tree2expr :: Tree -> Expr
|
||||||
tree2expr (Fun x ts) = foldl EApp (EVar x) (map tree2expr ts)
|
tree2expr (Fun x ts) = foldl EApp (EVar x) (map tree2expr ts)
|
||||||
tree2expr (Lit l) = ELit l
|
tree2expr (Lit l) = ELit l
|
||||||
@@ -209,29 +211,40 @@ tree2expr (Meta n) = EMeta n
|
|||||||
tree2expr (Abs xs t) = foldr EAbs (tree2expr t) xs
|
tree2expr (Abs xs t) = foldr EAbs (tree2expr t) xs
|
||||||
tree2expr (Var x) = EVar x
|
tree2expr (Var x) = EVar x
|
||||||
|
|
||||||
-- | Converts an expression to tree. The expression
|
-- | Converts an expression to tree. The conversion is only partial.
|
||||||
-- is first reduced to beta-eta-alfa normal form and
|
-- Variables and meta variables of function type and beta redexes are not allowed.
|
||||||
-- after that converted to tree.
|
expr2tree :: Expr -> Tree
|
||||||
expr2tree :: Funs -> Expr -> Tree
|
expr2tree e = abs [] e
|
||||||
expr2tree funs e = value2tree [] (eval funs Map.empty e)
|
|
||||||
where
|
where
|
||||||
value2tree xs (VApp f vs) = case Map.lookup f funs of
|
abs xs (EAbs x e) = abs (x:xs) e
|
||||||
Just (DTyp hyps _ _,_,_) -> -- eta conversion
|
abs xs e = case xs of
|
||||||
let a1 = length hyps
|
[] -> app [] e
|
||||||
a2 = length vs
|
xs -> Abs (reverse xs) (app [] e)
|
||||||
a = a1 - a2
|
|
||||||
i = length xs
|
app as (EApp e1 e2) = app ((abs [] e2) : as) e1
|
||||||
xs' = [var i | i <- [i..i+a-1]]
|
app as (ELit l)
|
||||||
in ret (reverse xs'++xs)
|
| null as = Lit l
|
||||||
(Fun f (map (value2tree []) vs++map Var xs'))
|
| otherwise = error "literal of function type encountered"
|
||||||
Nothing -> error ("unknown variable "++prCId f)
|
app as (EMeta n)
|
||||||
value2tree xs (VGen i vs) | null vs = ret xs (Var (var i))
|
| null as = Meta n
|
||||||
| otherwise = error "variable of function type"
|
| otherwise = error "meta variables of function type are not allowed in trees"
|
||||||
value2tree xs (VMeta n vs) | null vs = ret xs (Meta n)
|
app as (EAbs x e) = error "beta redexes are not allowed in trees"
|
||||||
| otherwise = error "meta variable of function type"
|
app as (EVar x) = Fun x as
|
||||||
value2tree xs (VLit l) = ret xs (Lit l)
|
|
||||||
value2tree xs (VClosure env (EAbs x e)) = let i = length xs
|
|
||||||
in value2tree (var i:xs) (eval funs (Map.insert x (VGen i []) env) e)
|
-----------------------------------------------------
|
||||||
|
-- Computation
|
||||||
|
-----------------------------------------------------
|
||||||
|
|
||||||
|
-- | Compute an expression to normal form
|
||||||
|
normalForm :: Funs -> Expr -> Expr
|
||||||
|
normalForm funs e = value2expr 0 (eval funs Map.empty 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 n vs) = foldl EApp (EMeta n) (map (value2expr i) 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)
|
var i = mkCId ('v':show i)
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ fromDef pgf t@(Fun f ts) = defDown t ++ defUp t where
|
|||||||
[(ps,p) | (p,d@(Fun g ps)) <- equs, g==f,
|
[(ps,p) | (p,d@(Fun g ps)) <- equs, g==f,
|
||||||
isClosed d || (length equs == 1 && isLinear d)]
|
isClosed d || (length equs == 1 && isLinear d)]
|
||||||
|
|
||||||
equss = [(f,[(Fun f (map patt2tree ps), expr2tree (funs (abstract pgf)) d) | (Equ ps d) <- eqs]) |
|
equss = [(f,[(Fun f (map patt2tree ps), expr2tree d) | (Equ ps d) <- eqs]) |
|
||||||
(f,(_,_,eqs)) <- Map.assocs (funs (abstract pgf)), not (null eqs)]
|
(f,(_,_,eqs)) <- Map.assocs (funs (abstract pgf)), not (null eqs)]
|
||||||
|
|
||||||
trequ s f e = True ----trace (s ++ ": " ++ show f ++ " " ++ show e) True
|
trequ s f e = True ----trace (s ++ ": " ++ show f ++ " " ++ show e) True
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ import Data.List (partition,sort,groupBy)
|
|||||||
|
|
||||||
import Debug.Trace
|
import Debug.Trace
|
||||||
|
|
||||||
typecheck :: PGF -> Tree -> [Tree]
|
typecheck :: PGF -> Expr -> [Expr]
|
||||||
typecheck pgf t = case inferExpr pgf (newMetas (tree2expr t)) of
|
typecheck pgf e = case inferExpr pgf (newMetas e) of
|
||||||
Ok t -> [expr2tree (funs (abstract pgf)) t]
|
Ok e -> [e]
|
||||||
Bad s -> trace s []
|
Bad s -> trace s []
|
||||||
|
|
||||||
inferExpr :: PGF -> Expr -> Err Expr
|
inferExpr :: PGF -> Expr -> Err Expr
|
||||||
|
|||||||
Reference in New Issue
Block a user