ACLs
[hcoop/domtool2.git] / src / eval.sml
CommitLineData
a3698041
AC
1(* HCoop Domtool (http://hcoop.sourceforge.net/)
2 * Copyright (c) 2006, Adam Chlipala
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
dac62e84 17 *)
a3698041
AC
18
19(* Execution of Domtool programs reduced to primitive actions *)
20
21structure Eval :> EVAL = struct
22
23open Ast
24
25structure SM = StringMap
26
27fun lookup (evs, ev) =
28 case SM.find (evs, ev) of
29 NONE => raise Fail ("Couldn't find an environment variable "
30 ^ ev ^ " that type-checking has guaranteed")
31 | SOME v => v
32
33val conjoin : Env.env_vars * Env.env_vars -> Env.env_vars =
34 SM.unionWith #2
35
36fun findPrimitive e =
37 let
38 fun findPrim (e, _) =
39 case e of
40 EVar name => (name, [])
41 | EApp (e1, e2) =>
42 let
43 val (name, args) = findPrim e1
44 in
45 (name, e2 :: args)
46 end
47 | _ => raise Fail "Non-primitive action left after reduction"
48
49 val (name, args) = findPrim e
50 in
51 (name, rev args)
52 end
53
54fun exec evs e =
55 let
56 fun exec' evs (eAll as (e, _)) =
57 case e of
58 ESkip => SM.empty
59 | ESet (ev, e) => SM.insert (SM.empty, ev, e)
60 | EGet (x, ev, e) => exec' evs (Reduce.subst x (lookup (evs, ev)) e)
61 | ESeq es =>
62 let
63 val (new, _) =
64 foldl (fn (e, (new, keep)) =>
65 let
66 val new' = exec' keep e
67 in
68 (conjoin (new, new'),
69 conjoin (keep, new'))
70 end) (SM.empty, evs) es
71 in
72 new
73 end
74 | ELocal (e1, e2) =>
75 let
76 val evs' = exec' evs e1
77 val evs'' = exec' (conjoin (evs, evs')) e2
78 in
79 conjoin (evs, evs'')
80 end
81 | EWith (e1, e2) =>
82 let
83 val (prim, args) = findPrimitive e1
84 in
85 case Env.container prim of
86 NONE => raise Fail "Unbound primitive container"
87 | SOME (action, cleanup) =>
88 let
89 val evs' = action (evs, args)
90 val evs'' = exec' evs e2
91 in
92 cleanup ();
93 conjoin (conjoin (evs, evs'), evs'')
94 end
95 end
96
97 | _ =>
98 let
99 val (prim, args) = findPrimitive eAll
100 in
101 case Env.action prim of
102 NONE => raise Fail "Unbound primitive action"
103 | SOME action => action (evs, args)
104 end
105
e0b0abd2 106 val _ = Env.pre ()
a3698041
AC
107 val evs' = exec' evs e
108 in
e0b0abd2 109 Env.post ()
a3698041
AC
110 end
111
112end