git @ Cat's Eye Technologies Robin / 7421691
Dedicated Env datatype. Checkpoint. Chris Pressey 5 years ago
7 changed file(s) with 64 addition(s) and 56 deletion(s). Raw diff Collapse all Expand all
1212 -- Robin language. (See Intrinsics.lhs for those.)
1313 --
1414
15 {-
1516 --
1617 -- Helper functions
1718 --
166167 0 -> raise i (errMsg "division-by-zero" (Number xv))
167168 _ -> cc (Number (abs (xv `mod` yv)))))))
168169 robinRemainder i env other cc = raise i (errMsg "illegal-arguments" other)
170 -}
169171
170172 --
171173 -- Mapping of names to our functions, providing an evaluation environment.
172174 --
173175
174 robinBuiltins :: Expr
176 robinBuiltins :: Env.Env Expr
175177 robinBuiltins = Env.fromList $ map (\(name,bif) -> (name, Intrinsic name bif))
176178 [
179 {-
177180 ("literal", literal),
178181 ("list", robinList),
179182 ("bind", bind),
188191 ("multiply", robinMultiply),
189192 ("divide", robinDivide),
190193 ("remainder", robinRemainder)
194 -}
191195 ]
00 module Language.Robin.Env where
1
2 import Language.Robin.Expr
31
42 --
53 -- An environment is an alist which associates symbols with
64 -- values (arbitrary S-expressions).
75 --
86
9 empty :: Expr
10 empty = List []
7 data Env a = Env [(String, a)] deriving (Show, Ord, Eq)
118
12 insert :: Expr -> Expr -> Expr -> Expr
13 insert s@(Symbol _) value env =
14 append (List [List [s, value]]) env
9 empty :: Env a
10 empty = Env []
1511
16 find :: Expr -> Expr -> Maybe Expr
17 find s@(Symbol _) (List []) = Nothing
18 find s@(Symbol _) (List (List [first, value]:rest))
19 | s == first = Just value
20 | otherwise = find s (List rest)
12 insert :: String -> a -> Env a -> Env a
13 insert s value (Env bindings) = Env ((s, value):bindings)
2114
22 fromList :: [(String,Expr)] -> Expr
23 fromList [] =
24 List []
25 fromList ((id, val):xs) =
26 append (List [List [(Symbol id), val]]) (fromList xs)
15 find :: String -> Env a -> Maybe a
16 find _ (Env []) = Nothing
17 find s (Env ((t, value):rest))
18 | s == t = Just value
19 | otherwise = find s (Env rest)
2720
28 mergeEnvs :: Expr -> Expr -> Expr
29 mergeEnvs (List a) (List b) = List (a ++ b)
21 fromList :: [(String,a)] -> Env a
22 fromList [] = empty
23 fromList ((s, val):rest) = insert s val $ fromList rest
24
25 mergeEnvs :: Env a -> Env a -> Env a
26 mergeEnvs (Env a) (Env b) = Env (a ++ b)
88 -- Every evaluation function takes a continuation, and is implemented
99 -- as a function with this signature:
1010 --
11 -- Expr -> Expr -> Expr -> (Expr -> Expr) -> Expr
11 -- IEnv Expr -> Env Expr -> Expr -> (Expr -> Expr) -> Expr
1212 --
1313 -- (This is actually the `Evaluable` type from `Robin.Expr`.)
1414 --
2424
2525 eval :: Evaluable
2626
27 eval i (List []) s@(Symbol _) cc =
28 raise i (errMsg "unbound-identifier" s)
29 eval i (List (b@(List [id@(Symbol _), value]):env)) s@(Symbol _) cc
30 | id == s = cc value
31 | otherwise = eval i (List env) s cc
32 eval i (List ((List (other:_)):env)) s@(Symbol _) cc =
33 raise i (errMsg "expected-symbol" other)
34 eval i (List (head:tail)) s@(Symbol _) cc =
35 raise i (errMsg "expected-env-entry" head)
36 eval i env s@(Symbol _) cc =
37 raise i (errMsg "expected-env-alist" env)
27 eval i env sym@(Symbol s) cc =
28 case Env.find s env of
29 Just value ->
30 cc value
31 Nothing ->
32 raise i (errMsg "unbound-identifier" sym)
3833
3934 --
4035 -- Evaluating a list means we must make several evaluations. We
6863 errMsg msg term =
6964 List [(Symbol msg), term]
7065
66 makeMacroEnv :: Env.Env Expr -> Expr -> Expr -> Env.Env Expr
7167 makeMacroEnv env actuals m@(Macro closedEnv argList _) =
7268 let
73 (List [argSelf@(Symbol _), argFormal@(Symbol _),
74 envFormal@(Symbol _)]) = argList
69 (List [(Symbol argSelf), (Symbol argFormal),
70 (Symbol envFormal)]) = argList
7571 newEnv = Env.insert argSelf m closedEnv
7672 newEnv' = Env.insert argFormal actuals newEnv
77 newEnv'' = Env.insert envFormal env newEnv'
73 newEnv'' = Env.insert envFormal (Environment env) newEnv'
7874 in
7975 newEnv''
8076
11
22 import Data.Char
33 import Data.Int
4
5 import qualified Language.Robin.Env as Env
46
57 --
68 -- An _evaluable_ is a Haskell object which behaves like a Robin macro.
810 -- (perhaps unsurprisingly?) to be the type of the evaluator function.
911 --
1012
11 type Evaluable = IEnv Expr -> Expr -> Expr -> (Expr -> Expr) -> Expr
12 -- internal-env env args continuation result
13 type Evaluable = IEnv Expr -> Env.Env Expr -> Expr -> (Expr -> Expr) -> Expr
14 -- internal-env env args continuation result
1315
1416 data Expr = Symbol String
1517 | Boolean Bool
1618 | Number Int32
17 | Macro Expr Expr Expr
19 | Macro (Env.Env Expr) Expr Expr
1820 | Intrinsic String Evaluable
1921 | List [Expr]
22 | Environment (Env.Env Expr)
2023
2124 instance Eq Expr where
2225 (Symbol x) == (Symbol y) = x == y
2528 (Macro _ _ _) == (Macro _ _ _) = False
2629 (Intrinsic x _) == (Intrinsic y _) = x == y
2730 (List x) == (List y) = x == y
31 (Environment x) == (Environment y) = x == y
2832 _ == _ = False
2933
3034 instance Show Expr where
3943 showl [] = ""
4044 showl [expr] = show expr
4145 showl (expr:exprs) = (show expr) ++ " " ++ (showl exprs)
46 show (Environment env) = ":" ++ show env
4247
4348 --
4449 -- Helpers
4651
4752 append (List x) (List y) =
4853 List (x ++ y)
54
55 exprToEnv :: Expr -> Env.Env Expr
56 exprToEnv (List []) = Env.empty
57 exprToEnv (List ((List [(Symbol s), value]):rest)) =
58 Env.insert s value (exprToEnv (List rest))
4959
5060 --
5161 -- Predicates
7373
7474 robinEval :: Evaluable
7575 robinEval i env (List [envlist, form]) cc =
76 eval i env envlist (\newEnv ->
76 eval i env envlist (\newEnvVal ->
7777 eval i env form (\body ->
78 eval i newEnv body cc))
78 eval i (exprToEnv newEnvVal) body cc))
7979 robinEval i env other cc = raise i (errMsg "illegal-arguments" other)
8080
8181 robinMacro :: Evaluable
8989 robinRaise i env other cc = raise i (errMsg "illegal-arguments" other)
9090
9191 robinCatch :: Evaluable
92 robinCatch i env (List [id@(Symbol _), handler, body]) cc =
92 robinCatch i env (List [(Symbol s), handler, body]) cc =
9393 let
9494 handlerContinuation = (\errvalue ->
95 eval i (Env.insert id errvalue env) handler cc)
95 eval i (Env.insert s errvalue env) handler cc)
9696 i' = setExceptionHandler handlerContinuation i
9797 in
9898 eval i' env body cc
9999 robinCatch i env other cc = raise i (errMsg "illegal-arguments" other)
100100
101 robinIntrinsics :: Expr
101 robinIntrinsics :: Env.Env Expr
102102 robinIntrinsics = Env.fromList $ map (\(name,bif) -> (name, Intrinsic name bif))
103103 [
104104 ("head", robinHead),
44 import System.IO
55 import System.Random
66
7 import qualified Language.Robin.Env as Env
78 import Language.Robin.Expr
89 import Language.Robin.Eval
910
1011 data Reactor = Reactor {
1112 rid :: Int32,
12 env :: Expr,
13 env :: Env.Env Expr,
1314 state :: Expr,
1415 body :: Expr -- body takes three arguments: event state
1516 } deriving (Show, Eq)
00 module Language.Robin.TopLevel (collect) where
11
2 import qualified Language.Robin.Env as Env
23 import Language.Robin.Expr
3 import qualified Language.Robin.Env as Env
44 import Language.Robin.Eval
55 import Language.Robin.Reactor
66
77
8 collect :: [Expr] -> Expr -> [Reactor] -> [Either Expr Expr] -> (Expr, [Reactor], [Either Expr Expr])
8 collect :: [Expr] -> Env.Env Expr -> [Reactor] -> [Either Expr Expr] -> (Env.Env Expr, [Reactor], [Either Expr Expr])
99
1010 collect [] env reactors results = (env, reactors, results)
1111
2727 _ ->
2828 collect rest env reactors results
2929
30 collect ((List [Symbol "require", expr]):rest) env reactors results =
31 case Env.find expr env of
30 collect ((List [Symbol "require", sym@(Symbol s)]):rest) env reactors results =
31 case Env.find s env of
3232 Nothing ->
33 error ("assertion failed: (bound? " ++ show expr ++ ")")
33 error ("assertion failed: (bound? " ++ show sym ++ ")")
3434 _ ->
3535 collect rest env reactors results
3636
37 collect ((List [Symbol "define", name@(Symbol _), expr]):rest) env reactors results =
38 case Env.find name env of
37 collect ((List [Symbol "define", sym@(Symbol s), expr]):rest) env reactors results =
38 case Env.find s env of
3939 Just _ ->
40 error ("symbol already defined: " ++ show name)
40 error ("symbol already defined: " ++ show sym)
4141 Nothing ->
4242 let
4343 result = eval (IEnv stop) env expr id
4444 in
45 collect rest (Env.insert name result env) reactors results
45 collect rest (Env.insert s result env) reactors results
4646
47 collect ((List [Symbol "define-if-absent", name@(Symbol _), expr]):rest) env reactors results =
48 case Env.find name env of
47 collect ((List [Symbol "define-if-absent", sym@(Symbol s), expr]):rest) env reactors results =
48 case Env.find s env of
4949 Just _ ->
5050 collect rest env reactors results
5151 Nothing ->
5252 let
5353 result = eval (IEnv stop) env expr id
5454 in
55 collect rest (Env.insert name result env) reactors results
55 collect rest (Env.insert s result env) reactors results
5656
5757 collect ((List [Symbol "reactor", facExpr, stateExpr, bodyExpr]):rest) env reactors results =
5858 let