mailman: temporarily disable suexec, allow access to public archives
[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
254d5faa 27fun lookup ((root, evs), ev) =
a3698041 28 case SM.find (evs, ev) of
254d5faa
CE
29 NONE => (case SM.find (root, ev) of
30 NONE => raise Fail ("Couldn't find an environment variable "
31 ^ ev ^ " that type-checking has guaranteed")
32 | SOME v => v)
a3698041
AC
33 | SOME v => v
34
8a7c40fa
AC
35fun printEvs (name, evs) =
36 (print ("Environment " ^ name ^ "\n");
37 SM.appi (fn (name, i) => Print.preface (name, Print.p_exp i)) evs;
38 print "\n")
39
a3698041
AC
40val conjoin : Env.env_vars * Env.env_vars -> Env.env_vars =
41 SM.unionWith #2
42
43fun findPrimitive e =
44 let
45 fun findPrim (e, _) =
46 case e of
47 EVar name => (name, [])
48 | EApp (e1, e2) =>
49 let
50 val (name, args) = findPrim e1
51 in
52 (name, e2 :: args)
53 end
54 | _ => raise Fail "Non-primitive action left after reduction"
55
56 val (name, args) = findPrim e
57 in
58 (name, rev args)
59 end
60
254d5faa 61fun exec' (evsAll as (root, evs)) (eAll as (e, _)) =
1824f573
AC
62 case e of
63 ESkip => SM.empty
64 | ESet (ev, e) => SM.insert (SM.empty, ev, e)
a356587a
AC
65 | EGet (x, _, ev, e) =>
66 let
254d5faa 67 val e' = Reduce.subst x (lookup (evsAll, ev)) e
a356587a 68 in
254d5faa 69 exec' evsAll (Reduce.reduceExp Env.empty e')
a356587a 70 end
1824f573
AC
71 | ESeq es =>
72 let
73 val (new, _) =
74 foldl (fn (e, (new, keep)) =>
75 let
254d5faa 76 val new' = exec' (root, keep) e
1824f573
AC
77 in
78 (conjoin (new, new'),
79 conjoin (keep, new'))
80 end) (SM.empty, evs) es
81 in
82 new
83 end
84 | ELocal (e1, e2) =>
85 let
254d5faa 86 val evs' = exec' evsAll e1
1824f573 87 in
254d5faa 88 exec' (root, (conjoin (evs, evs'))) e2
1824f573
AC
89 end
90 | EWith (e1, e2) =>
91 let
92 val (prim, args) = findPrimitive e1
93 in
94 case Env.container prim of
95 NONE => raise Fail "Unbound primitive container"
96 | SOME (action, cleanup) =>
a3698041 97 let
254d5faa
CE
98 val evs' = action (conjoin (root, evs), args)
99 val evs'' = exec' evsAll e2
a3698041 100 in
1824f573
AC
101 cleanup ();
102 evs'
a3698041 103 end
1824f573 104 end
a3698041 105
1824f573
AC
106 | _ =>
107 let
108 val (prim, args) = findPrimitive eAll
109 in
110 case Env.action prim of
111 NONE => raise Fail "Unbound primitive action"
254d5faa 112 | SOME action => action (conjoin (root, evs), List.map (Reduce.reduceExp Env.empty) args)
1824f573 113 end
a3698041 114
1824f573
AC
115fun exec evs e =
116 let
e0b0abd2 117 val _ = Env.pre ()
a3698041
AC
118 val evs' = exec' evs e
119 in
e0b0abd2 120 Env.post ()
a3698041
AC
121 end
122
254d5faa 123val exec' = fn evs as (root, evs') => fn e => conjoin (evs', exec' evs e)
24248d62 124
a3698041 125end