/[svn]/runtime/eval.ml
ViewVC logotype

Contents of /runtime/eval.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 310 - (show annotations)
Tue Jul 10 17:24:12 2007 UTC (5 years, 11 months ago) by abate
File size: 8148 byte(s)
[r2003-05-10 14:44:29 by cvscast] Start Unicode support. Remove more generic comparisons

Original author: cvscast
Date: 2003-05-10 14:44:30+00:00
1 open Value
2 open Run_dispatch
3 open Ident
4
5 module Env = Map.Make (Ident.Id)
6 type env = t Env.t
7
8 let global_env = State.ref "Eval.global_env" Env.empty
9 let enter_global x v = global_env := Env.add x v !global_env
10
11
12 let exn_int_of = CDuceExn (Pair (
13 Atom (Atoms.mk "Invalid_argument"),
14 string_latin1 "int_of"))
15
16
17
18
19 (* Evaluation of expressions *)
20
21 exception EMatchFail
22
23 let rec eval env e0 =
24 match e0.Typed.exp_descr with
25 | Typed.Forget (e,_) -> eval env e
26 | Typed.Var s ->
27 (try Env.find s env
28 with Not_found -> Env.find s !global_env)
29 | Typed.Apply (f,arg) -> eval_apply (eval env f) (eval env arg)
30 | Typed.Abstraction a ->
31 let env =
32 IdSet.fold
33 (fun accu x ->
34 try Env.add x (Env.find x env) accu
35 with Not_found -> accu (* global *))
36 Env.empty a.Typed.fun_fv in
37 let env_ref = ref env in
38 let rec self = Abstraction (a.Typed.fun_iface,
39 eval_branches' env_ref a.Typed.fun_body) in
40 (match a.Typed.fun_name with
41 | None -> ()
42 | Some f -> env_ref := Env.add f self env;
43 );
44 self
45 (* Optimizations:
46 - for the non-recursive case, use eval_branches
47 - for the recursive case, could cheat by patching self afterwards:
48 (Obj.magic self).(1) <- ....
49 *)
50 | Typed.RecordLitt r -> Record (LabelMap.map (eval env) r)
51 | Typed.Pair (e1,e2) -> Pair (eval env e1, eval env e2)
52 | Typed.Xml (e1,e2) -> Xml (eval env e1, eval env e2)
53 | Typed.Cst c -> const c
54 | Typed.Match (arg,brs) -> eval_branches env brs (eval env arg)
55 | Typed.Map (arg,brs) -> eval_map env brs (eval env arg)
56 | Typed.Ttree (arg,brs) -> eval_ttree env brs (eval env arg)
57 | Typed.Op ("raise", [e]) -> raise (CDuceExn (eval env e))
58 | Typed.Try (arg,brs) ->
59 (try eval env arg with CDuceExn v -> eval_branches env brs v)
60 | Typed.Op ("flatten", [{Typed.exp_descr=Typed.Map (arg,brs)}]) ->
61 eval_transform env brs (eval env arg)
62 | Typed.Op ("flatten", [e]) -> eval_flatten (eval env e)
63 | Typed.Op ("@", [e1; e2]) -> eval_concat (eval env e1) (eval env e2)
64 | Typed.Op ("+", [e1; e2]) -> eval_add (eval env e1) (eval env e2)
65 | Typed.Op ("*", [e1; e2]) -> eval_mul (eval env e1) (eval env e2)
66 | Typed.Op ("-", [e1; e2]) -> eval_sub (eval env e1) (eval env e2)
67 | Typed.Op ("/", [e1; e2]) -> eval_div (eval env e1) (eval env e2)
68 | Typed.Op ("mod", [e1; e2]) -> eval_mod (eval env e1) (eval env e2)
69 | Typed.Op ("load_xml", [e]) -> eval_load_xml (eval env e)
70 | Typed.Op ("load_html", [e]) -> eval_load_html (eval env e)
71 | Typed.Op ("load_file", [e]) -> eval_load_file (eval env e)
72 | Typed.Op ("print_xml", [e]) -> eval_print_xml (eval env e)
73 | Typed.Op ("print", [e]) -> eval_print (eval env e)
74 | Typed.Op ("int_of", [e]) -> eval_int_of (eval env e)
75 | Typed.Op ("string_of", [e]) -> eval_string_of (eval env e)
76 | Typed.Op ("dump_to_file", [e1; e2]) ->
77 eval_dump_to_file (eval env e1) (eval env e2)
78 | Typed.Op ("=",[e1; e2]) -> eval_equal (eval env e1) (eval env e2)
79 | Typed.Op ("<",[e1; e2]) -> eval_lt (eval env e1) (eval env e2)
80 | Typed.Op ("<=",[e1; e2]) -> eval_lte (eval env e1) (eval env e2)
81 | Typed.Op (">",[e1; e2]) -> eval_gt (eval env e1) (eval env e2)
82 | Typed.Op (">=",[e1; e2]) -> eval_gte (eval env e1) (eval env e2)
83 | Typed.Dot (e, l) -> eval_dot l (eval env e)
84 | Typed.RemoveField (e, l) -> eval_remove_field l (eval env e)
85 | Typed.MatchFail -> raise EMatchFail
86 | Typed.Op (o,_) -> failwith ("Unknown operator " ^ o)
87
88
89 and eval_apply f arg = match f with
90 | Abstraction (_,clos) -> clos arg
91 | _ -> eval_concat f arg
92
93 and eval_branches' env_ref brs arg =
94 eval_branches !env_ref brs arg
95
96 and eval_branches env brs arg =
97 let (disp, rhs) = Typed.dispatcher brs in
98 let (code, bindings) = run_dispatcher disp arg in
99 let (bind, e) = rhs.(code) in
100 let env =
101 List.fold_left (fun env (x,i) ->
102 if (i = -1) then Env.add x arg env
103 else Env.add x bindings.(i) env) env (IdMap.get bind) in
104 eval env e
105
106 and eval_let_decl env l =
107 let v = eval env l.Typed.let_body in
108 let (disp,bind) = Typed.dispatcher_let_decl l in
109 let (_,bindings) = run_dispatcher disp v in
110 List.map (fun (x,i) -> (x, if (i = -1) then v else bindings.(i))) (IdMap.get bind)
111
112 and eval_map env brs = function
113 | Pair (x,y) ->
114 let x = eval_branches env brs x in
115 Pair (x, eval_map env brs y)
116 | String_latin1 (_,_,_,_) | String_utf8 (_,_,_,_) as v -> eval_map env brs (normalize v)
117 | q -> q
118
119 and eval_flatten = function
120 | Pair (x,y) -> eval_concat x (eval_flatten y)
121 | q -> q
122
123 and eval_transform env brs = function
124 | Pair (x,y) ->
125 let x = eval_branches env brs x in
126 eval_concat x (eval_transform env brs y)
127 | String_latin1 (_,_,_,_) | String_utf8 (_,_,_,_) as v -> eval_transform env brs (normalize v)
128 | q -> q
129
130 and eval_ttree env brs = function
131 | Pair (x,y) ->
132 let y = eval_ttree env brs y in (* Beware of evaluation order !! Reverse it ? *)
133 (try
134 let x = eval_branches env brs x in
135 (* TODO: avoid raising exceptions (for each character/element !) *)
136 eval_concat x y
137 with EMatchFail ->
138 let x = match x with
139 | Xml (tag, Pair (attr, child)) ->
140 let child = eval_ttree env brs child in
141 Xml (tag, Pair (attr, child))
142 | Xml (_,_) -> assert false
143 | x -> x in
144 Pair (x,y))
145 | String_latin1 (_,_,_,_) | String_utf8 (_,_,_,_) as v -> eval_ttree env brs (normalize v)
146 (* TODO: optimize for strings, to avoid decomposing compound String values *)
147 | q -> q
148
149 and eval_concat l1 l2 = match l1 with
150 | Pair (x,y) -> Pair (x, eval_concat y l2)
151 | String_latin1 (s,i,j,q) -> String_latin1 (s,i,j, eval_concat q l2)
152 | String_utf8 (s,i,j,q) -> String_utf8 (s,i,j, eval_concat q l2)
153 | q -> l2
154
155 and eval_dot l = function
156 | Record r -> LabelMap.assoc l r
157 | _ -> assert false
158
159 and eval_remove_field l = function
160 | Record r -> Record (LabelMap.remove l r)
161 | _ -> assert false
162
163 and eval_add x y = match (x,y) with
164 | (Integer x, Integer y) -> Integer (Intervals.vadd x y)
165 | Record r1, Record r2 -> Record (LabelMap.merge (fun x y -> y) r1 r2)
166 | _ -> assert false
167
168 and eval_mul x y = match (x,y) with
169 | (Integer x, Integer y) -> Integer (Intervals.vmult x y)
170 | _ -> assert false
171
172 and eval_sub x y = match (x,y) with
173 | (Integer x, Integer y) -> Integer (Intervals.vsub x y)
174 | _ -> assert false
175
176 and eval_div x y = match (x,y) with
177 | (Integer x, Integer y) -> Integer (Intervals.vdiv x y)
178 | _ -> assert false
179
180 and eval_mod x y = match (x,y) with
181 | (Integer x, Integer y) -> Integer (Intervals.vmod x y)
182 | _ -> assert false
183
184 and eval_load_xml e =
185 Load_xml.load_xml (get_string_latin1 e)
186
187 and eval_load_html e =
188 Load_xml.load_html (get_string_latin1 e)
189
190 and eval_load_file e =
191 Location.protect_op "load_file";
192 let ic = open_in (get_string_latin1 e) in
193 let len = in_channel_length ic in
194 let s = String.create len in
195 really_input ic s 0 len;
196 close_in ic;
197 Value.string_latin1 s
198
199 and eval_int_of e =
200 let s = get_string_latin1 e in
201 try Integer (Intervals.mk s)
202 with Failure _ -> raise exn_int_of
203
204 and eval_print_xml v =
205 string_latin1 (Print_xml.string_of_xml v)
206
207 and eval_print v =
208 Location.protect_op "print";
209 print_string (get_string_latin1 v);
210 flush stdout;
211 Value.nil
212
213 and eval_dump_to_file f v =
214 Location.protect_op "dump_to_file";
215 let oc = open_out (get_string_latin1 f) in
216 output_string oc (get_string_latin1 v);
217 close_out oc;
218 Value.nil
219
220
221 and eval_string_of v =
222 let b = Buffer.create 16 in
223 let ppf = Format.formatter_of_buffer b in
224 Value.print ppf v;
225 Format.pp_print_flush ppf ();
226 string_latin1 (Buffer.contents b)
227
228 and eval_equal v1 v2 =
229 let c = Value.compare v1 v2 in
230 Value.vbool (Value.compare v1 v2 = 0)
231
232 and eval_lt v1 v2 =
233 let c = Value.compare v1 v2 in
234 Value.vbool (Value.compare v1 v2 < 0)
235
236 and eval_lte v1 v2 =
237 let c = Value.compare v1 v2 in
238 Value.vbool (Value.compare v1 v2 <= 0)
239
240 and eval_gt v1 v2 =
241 let c = Value.compare v1 v2 in
242 Value.vbool (Value.compare v1 v2 > 0)
243
244 and eval_gte v1 v2 =
245 let c = Value.compare v1 v2 in
246 Value.vbool (Value.compare v1 v2 >= 0)

CVS Admin">CVS Admin
ViewVC Help
Powered by ViewVC 1.1.5