-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathLambdaInterpreter.hs
146 lines (130 loc) · 5.91 KB
/
LambdaInterpreter.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import Settings
import Expression
import Command
import CommandParser
import Taggers
import PrettyPrinter
import InteractiveTagger
import qualified Data.Map as Map
import System.IO
import System.Console.CmdArgs
import Control.Concurrent
import Data.Maybe
import Data.Either.Combinators
tryFunctions :: [Expression -> TaggedExpression] -> Expression -> TaggedExpression
tryFunctions [] term = Nothing
tryFunctions (f:fs) expr =
let taggedExpr = f expr in
if isJust taggedExpr then taggedExpr else tryFunctions fs expr
evaluateExpression ::
(Expression -> IO TaggedExpression) -> Expression -> IO Expression
evaluateExpression tagfn expr =
do taggedExpr <- tagfn expr
let newexpr = applyTags $ fromTaggedExpression expr taggedExpr
prettyPrint newexpr
-- TODO: The following must be doable more elegant
-- In particular the conversion fromRight' and afterwards back
-- to Right must be solved in another manner
if isJust taggedExpr
then evaluateExpression tagfn newexpr
else return expr -- return original if not transformable
tagAndPrint :: (Expression -> TaggedExpression) -> Expression -> IO TaggedExpression
tagAndPrint tagfn expr =
let taggedExpr = tagfn expr in
if isJust taggedExpr then do prettyPrint $ fromJust taggedExpr
return taggedExpr
else return taggedExpr
stepPrint :: Expression -> Settings -> IO Expression
stepPrint expr settings = evaluateExpression (tagAndPrint tagfn) expr
where tagfn = tryFunctions
[ allAbbreviationTags settings
, normalOrderTags
]
interactivePrint :: Expression -> Settings -> IO Expression
interactivePrint expr settings =
evaluateExpression (interactiveTags settings) expr
normalizePrint :: Expression -> Settings -> IO Expression
normalizePrint expr settings = evaluateExpression (return . tagfn) expr
where tagfn = tryFunctions
[ allAbbreviationTags settings
, normalOrderTags
]
consumeExpression ::
InteractivityMode -> Expression -> Settings -> IO Expression
consumeExpression strategy = case strategy of
Full -> normalizePrint
Steps -> stepPrint
Interactive -> interactivePrint
evalCommand :: Command -> Settings -> IO ()
evalCommand cmd settings = case cmd of
EmptyCmd -> repl settings
SimpleExpression e -> do prettyPrint e
result <- computeMe e settings
--putStrLn $ show (simpleFromTaggedExpression e result)
repl settings
{environment =
Map.insert "_" result (environment settings)}
where computeMe = consumeExpression
(interactivityMode settings)
simpleFromTaggedExpression e Nothing = e
simpleFromTaggedExpression e (Just r) = r
LetStmt n e -> let curenv = environment settings in
let newenv = Map.insert n e curenv in
repl (settings {environment = newenv})
LoadCmd f -> do abbrevs <- readLambdaFile f
let newenv = Map.union abbrevs $ environment settings
repl settings {environment = newenv}
SetCmd f -> case f of
"fulleval" -> repl settings {interactivityMode = Full}
"stepeval" -> repl settings {interactivityMode = Steps}
"inteval" -> repl settings {interactivityMode = Interactive}
_ -> do
_ <- putStrLn $ "Unknown option: " ++ f
repl settings
repl :: Settings -> IO ()
repl settings = do putStr "> "
hFlush stdout
input <- getLine
if dropWhile (==' ') input == ""
then repl settings
else (case parseCommand (dropWhile (==' ') input) of
Nothing -> do putStrLn "Command not recognized"
repl settings
Just cmd -> evalCommand cmd settings)
getOnlyLetCommand :: String -> Maybe (String, Expression)
getOnlyLetCommand cmd = case parseCommand (dropWhile (==' ') cmd) of
Just (LetStmt n e) -> Just (n, e)
_ -> Nothing
addEnvBindingFromLine :: Environment -> String -> Environment
addEnvBindingFromLine env line = case getOnlyLetCommand line of
Just (n, e) -> Map.insert n e env
Nothing -> env
readLambdaFile :: String -> IO Environment
readLambdaFile f = do putStr "loading "
putStrLn f
content <- readFile f
let res = foldl addEnvBindingFromLine Map.empty $
lines content
return res
readLambdaFiles :: [String] -> IO Environment
readLambdaFiles f = foldl doit (return Map.empty) f where
doit m p = do old <- m
newabbrevs <- readLambdaFile p
return $ Map.union old newabbrevs
interruptionHandler :: MVar Bool -> IO ()
interruptionHandler itr = do i <- takeMVar itr
putStrLn "Interrupted"
putMVar itr (not i)
main :: IO ()
main = do myargs <- cmdArgs $ defaultArguments
itr <- newMVar False -- to capture Ctrl-C signal
--installHandler sigINT (Catch $ interruptionHandler itr) Nothing
putStrLn $ show myargs
abbrevs <- readLambdaFiles $ filename myargs
putStrLn $ "Abbrevs:"
putStrLn $ show abbrevs
let env = Map.union abbrevs $ environment defaultSettings
repl $ defaultSettings { clargs = myargs
, environment = env
, interruption = itr
}