git @ Cat's Eye Technologies Robin / df7d5b3
Replace exception handler with error objects. Untested. Chris Pressey 5 years ago
5 changed file(s) with 43 addition(s) and 71 deletion(s). Raw diff Collapse all Expand all
3232 evalArgs formals actuals origActuals env (\nenv ->
3333 cc $ insert formal value nenv))
3434 evalArgs _ _ origActuals env cc =
35 raise env $ errMsg "illegal-arguments" $ List origActuals
35 errMsg "illegal-arguments" $ List origActuals
3636
3737
3838 evalTwoNumbers :: (Int32 -> Int32 -> (Expr -> Expr) -> Expr) -> Evaluable
4242 eval env yexpr (\y ->
4343 assertNumber env y (\(Number yv) ->
4444 (fn xv yv cc)))))
45 evalTwoNumbers fn env other cc = raise env $ errMsg "illegal-arguments" other
45 evalTwoNumbers fn env other cc = errMsg "illegal-arguments" other
4646
4747 --
4848 -- `Small`
5555 literal :: Evaluable
5656 literal env (List (expr:_)) cc =
5757 cc expr
58 literal env other cc = raise env $ errMsg "illegal-arguments" other
58 literal env other cc = errMsg "illegal-arguments" other
5959
6060 robinList :: Evaluable
6161 robinList env (List exprs) cc =
7575 eval env branch cc
7676 Boolean False ->
7777 choose env (List rest) cc)
78 choose env other cc = raise env $ errMsg "illegal-arguments" other
78 choose env other cc = errMsg "illegal-arguments" other
7979
8080 bind :: Evaluable
8181 bind env (List [(Symbol name), expr, body]) cc =
8282 eval env expr (\value ->
8383 eval (insert name value env) body cc)
84 bind env other cc = raise env $ errMsg "illegal-arguments" other
84 bind env other cc = errMsg "illegal-arguments" other
8585
8686 robinLet :: Evaluable
8787 robinLet env (List ((List bindings):body:_)) cc =
9494 eval env sexpr (\value ->
9595 bindAll rest (insert name value env) cc)
9696 bindAll (other:rest) env cc =
97 raise env $ errMsg "illegal-binding" other
98 robinLet env other cc = raise env $ errMsg "illegal-arguments" other
97 errMsg "illegal-binding" other
98 robinLet env other cc = errMsg "illegal-arguments" other
9999
100100 robinBindArgs :: Evaluable
101101 robinBindArgs env (List [(List formals), givenArgs, givenEnvExpr, body]) cc =
103103 eval env givenEnvExpr (\outerEnvExpr ->
104104 evalArgs formals actuals actuals outerEnvExpr (\argEnv ->
105105 eval (mergeEnvs argEnv env) body cc)))
106 robinBindArgs env other cc = raise env $ errMsg "illegal-arguments" other
106 robinBindArgs env other cc = errMsg "illegal-arguments" other
107107
108108 robinFun :: Evaluable
109109 robinFun closedEnv (List [(List formals), body]) cc =
112112 fun env (List actuals) cc =
113113 evalArgs formals actuals actuals env (\argEnv ->
114114 eval (mergeEnvs argEnv closedEnv) body cc)
115 robinFun env other cc = raise env $ errMsg "illegal-arguments" other
115 robinFun env other cc = errMsg "illegal-arguments" other
116116
117117 --
118118 -- `Arith`
137137 robinAbs :: Evaluable
138138 robinAbs env (List [expr]) cc =
139139 eval env expr (\x -> assertNumber env x (\(Number xv) -> cc (Number $ abs xv)))
140 robinAbs env other cc = raise env (errMsg "illegal-arguments" other)
140 robinAbs env other cc = errMsg "illegal-arguments" other
141141
142142 robinAdd :: Evaluable
143143 robinAdd = evalTwoNumbers (\x y cc -> cc $ Number (x + y))
152152 eval env yexpr (\y ->
153153 assertNumber env y (\(Number yv) ->
154154 case yv of
155 0 -> raise env $ errMsg "division-by-zero" $ Number xv
155 0 -> errMsg "division-by-zero" $ Number xv
156156 _ -> cc $ Number (xv `div` yv)))))
157 robinDivide env other cc = raise env $ errMsg "illegal-arguments" other
157 robinDivide env other cc = errMsg "illegal-arguments" other
158158
159159 robinRemainder :: Evaluable
160160 robinRemainder env (List [xexpr, yexpr]) cc =
163163 eval env yexpr (\y ->
164164 assertNumber env y (\(Number yv) ->
165165 case yv of
166 0 -> raise env $ errMsg "division-by-zero" $ Number xv
166 0 -> errMsg "division-by-zero" $ Number xv
167167 _ -> cc $ Number (abs (xv `mod` yv))))))
168 robinRemainder env other cc = raise env $ errMsg "illegal-arguments" other
168 robinRemainder env other cc = errMsg "illegal-arguments" other
169169
170170 --
171171 -- Mapping of names to our functions, providing an evaluation environment.
2828 Just value ->
2929 cc value
3030 Nothing ->
31 raise env (errMsg "unbound-identifier" sym)
31 errMsg "unbound-identifier" sym
3232
3333 --
3434 -- Evaluating a list means we must make several evaluations. We
4545 b@(Intrinsic _ fun) ->
4646 fun env (List actuals) cc
4747 other ->
48 raise env (errMsg "inapplicable-object" other))
48 errMsg "inapplicable-object" other)
4949
5050 --
5151 -- Everything else just evaluates to itself. Continue the current
6060 --
6161
6262 errMsg msg term =
63 List [(Symbol msg), term]
63 Error (List [(Symbol msg), term])
6464
6565 makeMacroEnv :: Env -> Expr -> Expr -> Env
6666 makeMacroEnv env actuals m@(Macro closedEnv argList _) =
7474 newEnv''
7575
7676 --
77 -- Exception Handler
78 --
79
80 raise :: Env -> Expr -> Expr
81 raise env expr =
82 case getExceptionHandler env of
83 Just (Intrinsic _ evaluable) ->
84 evaluable (empty) expr (\e -> e)
85 Nothing ->
86 error ("uncaught exception: " ++ show expr)
87
88 --
8977 -- Assertions
9078 --
9179
9280 assert env pred msg expr cc =
9381 case pred expr of
9482 True -> cc expr
95 False -> raise env (errMsg msg expr)
83 False -> errMsg msg expr
9684
9785 assertSymbol env = assert env (isSymbol) "expected-symbol"
9886 assertBoolean env = assert env (isBoolean) "expected-boolean"
2222 | Macro Env Expr Expr
2323 | Intrinsic String Evaluable
2424 | List [Expr]
25 | Error Expr
2526
2627 instance Eq Expr where
2728 (Symbol x) == (Symbol y) = x == y
3031 (Macro _ _ _) == (Macro _ _ _) = False
3132 (Intrinsic x _) == (Intrinsic y _) = x == y
3233 (List x) == (List y) = x == y
34 (Error x) == (Error y) = x == y
3335 _ == _ = False
3436
3537 instance Show Expr where
4042 show (Macro env args body) = ("(macro " ++ (show args) ++
4143 " " ++ (show body) ++ ")")
4244 show (Intrinsic name _) = name
45 show (Error e) = "***ERR:" ++ (show e) ++ "***"
4346 show (List exprs) = "(" ++ (showl exprs) ++ ")" where
4447 showl [] = ""
4548 showl [expr] = show expr
104107 isMacro (Intrinsic _ _) = True
105108 isMacro _ = False
106109
107 --
108 -- Exceptions
109 --
110
111 getExceptionHandler env = find "(exception-handler)" env
112 setExceptionHandler handler env = insert "(exception-handler)" handler env
110 isError (Error _) = True
111 isError _ = False
99 assertList env x (\val ->
1010 case val of
1111 List (a:_) -> cc a
12 other -> raise env $ errMsg "expected-list" other))
13 robinHead env other cc = raise env $ errMsg "illegal-arguments" other
12 other -> errMsg "expected-list" other))
13 robinHead env other cc = errMsg "illegal-arguments" other
1414
1515 robinTail :: Evaluable
1616 robinTail env (List [expr]) cc =
1818 assertList env x (\val ->
1919 case val of
2020 List (_:b) -> cc (List b)
21 other -> raise env $ errMsg "expected-list" other))
22 robinTail env other cc = raise env $ errMsg "illegal-arguments" other
21 other -> errMsg "expected-list" other))
22 robinTail env other cc = errMsg "illegal-arguments" other
2323
2424 robinPrepend :: Evaluable
2525 robinPrepend env (List [e1, e2]) cc =
2626 eval env e1 (\x1 -> eval env e2 (\val ->
2727 case val of
2828 List x2 -> cc $ List (x1:x2)
29 other -> raise env (errMsg "expected-list" other)))
30 robinPrepend env other cc = raise env $ errMsg "illegal-arguments" other
29 other -> errMsg "expected-list" other))
30 robinPrepend env other cc = errMsg "illegal-arguments" other
3131
3232 equalP :: Evaluable
3333 equalP env (List [e1, e2]) cc =
3434 eval env e1 (\x1 -> eval env e2 (\x2 -> cc $ Boolean (x1 == x2)))
35 equalP env other cc = raise env $ errMsg "illegal-arguments" other
35 equalP env other cc = errMsg "illegal-arguments" other
3636
3737 predP pred env (List [expr]) cc =
3838 eval env expr (\x -> cc $ Boolean $ pred x)
39 predP pred env other cc = raise env $ errMsg "illegal-arguments" other
39 predP pred env other cc = errMsg "illegal-arguments" other
4040
4141 symbolP = predP isSymbol
4242 listP = predP isList
5050 eval env yexpr (\y ->
5151 assertNumber env y (\(Number yv) ->
5252 cc (Number (xv - yv))))))
53 robinSubtract env other cc = raise env $ errMsg "illegal-arguments" other
53 robinSubtract env other cc = errMsg "illegal-arguments" other
5454
5555 robinSign :: Evaluable
5656 robinSign env (List [expr]) cc =
5959 cc $ Number $ sign xv))
6060 where
6161 sign x = if x == 0 then 0 else if x < 0 then -1 else 1
62 robinSign env other cc = raise env $ errMsg "illegal-arguments" other
62 robinSign env other cc = errMsg "illegal-arguments" other
6363
6464 robinIf :: Evaluable
6565 robinIf env (List [test, texpr, fexpr]) cc =
6868 case b of
6969 True -> eval env texpr cc
7070 False -> eval env fexpr cc))
71 robinIf env other cc = raise env $ errMsg "illegal-arguments" other
71 robinIf env other cc = errMsg "illegal-arguments" other
7272
7373 robinEval :: Evaluable
7474 robinEval env (List [envlist, form]) cc =
7575 eval env envlist (\newEnvVal ->
7676 eval env form (\body ->
7777 eval newEnvVal body cc))
78 robinEval env other cc = raise env $ errMsg "illegal-arguments" other
78 robinEval env other cc = errMsg "illegal-arguments" other
7979
8080 robinMacro :: Evaluable
8181 robinMacro env (List [args@(List [(Symbol selfS), (Symbol argsS), (Symbol envS)]), body]) k =
8282 k $ Macro env args body
83 robinMacro env other cc = raise env $ errMsg "illegal-arguments" other
83 robinMacro env other cc = errMsg "illegal-arguments" other
8484
8585 robinRaise :: Evaluable
8686 robinRaise env (List [expr]) cc =
87 eval env expr (\v -> raise env v)
88 robinRaise env other cc = raise env $ errMsg "illegal-arguments" other
89
90 robinCatch :: Evaluable
91 robinCatch env (List [(Symbol s), handler, body]) cc =
92 let
93 exceptionHandler _ errvalue k =
94 eval (insert s errvalue env) handler cc
95 env' = setExceptionHandler (Intrinsic "(exception-handler)" exceptionHandler) env
96 in
97 eval env' body cc
98 robinCatch env other cc = raise env $ errMsg "illegal-arguments" other
87 eval env expr (\v -> cc $ Error v)
88 robinRaise env other cc = errMsg "illegal-arguments" other
9989
10090 robinIntrinsics :: Env
10191 robinIntrinsics = fromList $ map (\(name,bif) -> (name, Intrinsic name bif))
113103 ("macro", robinMacro),
114104 ("eval", robinEval),
115105 ("if", robinIf),
116 ("raise", robinRaise),
117 ("catch", robinCatch)
106 ("raise", robinRaise)
118107 ]
1010
1111 collect ((List [Symbol "display", expr]):rest) env reactors results =
1212 let
13 catchException env expr k = List [(Symbol "uncaught-exception"), expr]
14 env' = setExceptionHandler (Intrinsic "(exception-handler)" catchException) env
15 result = case eval env' expr id of
13 result = case eval env expr id of
1614 (List [(Symbol "uncaught-exception"), expr]) -> Left expr
1715 other -> Right other
1816 in
5452
5553 collect ((List [Symbol "reactor", facExpr, stateExpr, bodyExpr]):rest) env reactors results =
5654 let
57 catchException env expr k = List [(Symbol "uncaught-exception"), expr]
58 env' = setExceptionHandler (Intrinsic "(exception-handler)" catchException) env
59 state = eval env' stateExpr id
60 body = eval env' bodyExpr id
61 newReactor = Reactor{ rid=(fromIntegral $ length reactors), env=env', state=state, body=body }
55 state = eval env stateExpr id
56 body = eval env bodyExpr id
57 newReactor = Reactor{ rid=(fromIntegral $ length reactors), env=env, state=state, body=body }
6258 in
6359 collect rest env (newReactor:reactors) results
6460