1 (* Copyright (C) 2000, HELM Team.
3 * This file is part of HELM, an Hypertextual, Electronic
4 * Library of Mathematics, developed at the Computer Science
5 * Department, University of Bologna, Italy.
7 * HELM is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * HELM is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with HELM; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22 * For details, see the HELM World-Wide-Web page,
23 * http://cs.unibo.it/helm/.
26 (* AUTOR: Ferruccio Guidi <fguidi@cs.unibo.it>
34 (* external function specification ******************************************)
36 type arity_t = Const of int
40 type eval_spec = {eval : M.query -> M.result;
44 type text_out_spec = {out : string -> unit;
45 path : (string -> unit) -> M.path -> unit;
46 query : (string -> unit) -> string -> M.query -> unit;
47 result : (string -> unit) -> string -> M.result -> unit
50 type text_in_spec = {result_in : Lexing.lexbuf -> M.result}
52 type fun_spec = {arity_p : arity_t;
54 body : eval_spec -> text_out_spec -> text_in_spec ->
55 M.path list -> M.query list -> M.result;
56 txt_out : text_out_spec ->
57 M.path list -> M.query list -> unit
60 type gen_spec = {arity : arity_t;
61 code : eval_spec -> M.query list -> M.query
64 exception ArityError of M.path * arity_t * int
66 exception NameError of M.path
68 exception NumberError of M.result
70 type std_text_out_spec = {s_out : string -> unit;
71 s_path : M.path -> unit;
72 s_query : M.query -> unit;
73 s_result : M.result -> unit
76 let check_arity p i = function
77 | Const k when i = k -> ()
78 | Positive when i > 0 -> ()
80 | a -> raise (ArityError (p, a, i))
82 (* external functions implementation ****************************************)
85 {s_out = o.out; s_path = o.path o.out;
86 s_query = o.query o.out ""; s_result = o.result o.out "\n"
94 let my_int_of_string s =
95 let l = String.length s in
97 if i = l then End else
99 | ' ' | '\t' | '\r' | 'n' -> Space
100 | '0' .. '9' -> Figure (Char.code s.[i] - Char.code '0')
103 let rec aux i xv = match get_t i, xv with
105 | End, None -> raise (Failure "int_of_string")
107 | Space, xv -> aux (succ i) xv
108 | Figure f, None -> aux (succ i) (Some f)
109 | Figure f, Some v -> aux (succ i) (Some (10 * v + f))
115 | [s, _] -> my_int_of_string s
116 | _ -> raise (Failure "int_of_string")
117 with Failure "int_of_string" -> raise (NumberError r)
119 let out_txt2 o n x1 x2 =
120 o.s_out "(" ; o.s_query x1; o.s_out (" " ^ n ^ " "); o.s_query x2; o.s_out ")"
122 let out_txt_ o p xl =
123 if p <> [] then begin o.s_path p; o.s_out " " end;
124 o.s_out "{"; P.flat_list o.s_out o.s_query ", " xl; o.s_out "}"
126 let out_txt_full o p pl xl =
127 o.s_path p; o.s_out " {"; P.flat_list o.s_out o.s_path ", " pl; o.s_out "} {";
128 P.flat_list o.s_out o.s_query ", " xl; o.s_out "}"
131 let arity_p = Const 0 in
132 let arity_s = Const 0 in
133 let body _ _ _ _ _ = r in
134 let txt_out o _ _ = (std o).s_out n in
135 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
138 let arity_p = Const 0 in
139 let arity_s = Const 1 in
140 let body e _ _ _ = function
141 | [x] -> f (e.eval x)
144 let txt_out o _ = function
145 | [x] -> let o = std o in o.s_out (n ^ " "); o.s_query x
148 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
151 let arity_p = Const 0 in
152 let arity_s = Const 2 in
153 let body e _ _ _ = function
154 | [x1; x2] -> f (e.eval x1) (e.eval x2)
157 let txt_out o _ = function
158 | [x1; x2] -> let o = std o in out_txt2 o n x1 x2
161 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
164 let s = if b then "false" else "empty" in
167 let true_fun = arity0 "true" U.mql_true
170 let aux r = if r = U.mql_false then U.mql_true else U.mql_false in
174 let aux r = [string_of_int (List.length r), []] in
178 let aux = function [] -> [] | hd :: _ -> [hd] in
181 let diff_fun = arity2 "diff" U.mql_diff
183 let xor_fun = arity2 "xor" U.xor
185 let sub_fun = arity2 "sub" U.set_sub
187 let meet_fun = arity2 "meet" U.set_meet
189 let eq_fun = arity2 "==" U.set_eq
193 if int_of_set v1 <= int_of_set v2 then U.mql_true else U.mql_false
199 if int_of_set v1 < int_of_set v2 then U.mql_true else U.mql_false
204 let arity_p = Const 0 in
205 let arity_s = Const 1 in
206 let body e o _ _ = function
208 let t = P.start_time () in
209 let r = (e.eval x) in
210 let s = P.stop_time t in
211 o.out (Printf.sprintf "Stat: %s,%i\n" s (List.length r));
215 let txt_out o _ = function
216 | [x] -> let o = std o in o.s_out "stat "; o.s_query x
219 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
221 let log_fun xml src =
223 let t = P.start_time () in o.s_query x;
224 let s = P.stop_time t in
225 if C.set e.conn C.Stat then o.s_out (Printf.sprintf "Log source: %s\n" s);
230 let t = P.start_time () in o.s_result s;
231 let r = P.stop_time t in
232 if C.set e.conn C.Stat then o.s_out (Printf.sprintf "Log: %s\n" r); s
235 if xml then o.s_out "xml ";
236 if src then o.s_out "source "
238 let arity_p = Const 0 in
239 let arity_s = Const 1 in
240 let body e o _ _ = function
241 | [x] -> let o = std o in if src then log_src e o x else log_res e o x
244 let txt_out o _ = function
245 | [x] -> let o = std o in o.s_out "log "; txt_log o; o.s_query x
248 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
251 let arity_p = Const 0 in
252 let arity_s = Const 1 in
253 let body e o _ _ = function
256 let out s = rs := ! rs ^ s in
257 o.result out " " (e.eval x);
261 let txt_out o _ = function
262 | [x] -> let o = std o in o.s_out "render "; o.s_query x
265 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
268 let arity_p = Const 0 in
269 let arity_s = Const 1 in
270 let body e o i _ = function
273 let ich = open_in (fst av) in
274 let r = i.result_in (Lexing.from_channel ich) in
277 U.mql_iter aux (e.eval x)
280 let txt_out o _ = function
281 | [x] -> let o = std o in o.s_out "read "; o.s_query x
284 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
288 let c = String.length v in
289 if c < l then [(String.make (l - c) ' ' ^ v), g] else [v, g]
291 let arity_p = Const 0 in
292 let arity_s = Const 2 in
293 let body e _ _ _ = function
295 let l = int_of_set (e.eval y) in
296 U.mql_iter (aux l) (e.eval x)
299 let txt_out o _ = function
302 o.s_out "align "; o.s_query y; o.s_out " in "; o.s_query x
305 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
308 let arity_p = Const 0 in
309 let arity_s = Const 3 in
310 let body e _ _ _ = function
312 if (e.eval y) = U.mql_false then (e.eval x2) else (e.eval x1)
315 let txt_out o _ = function
318 o.s_out "if "; o.s_query y; o.s_out " then "; o.s_query x1;
319 o.s_out " else "; o.s_query x2
322 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
325 let rec iter f = function
328 | head :: tail -> U.mql_intersect (f head) (iter f tail)
330 let arity_p = Const 0 in
331 let arity_s = Positive in
332 let body e _ _ _ xl = iter e.eval xl in
333 let txt_out o _ = function
335 | [x1; x2] -> let o = std o in out_txt2 o "/\\" x1 x2
336 | xl -> let o = std o in out_txt_ o ["intersect"] xl
338 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
341 let arity_p = Const 0 in
343 let body e _ _ _ xl = U.mql_iter e.eval xl in
344 let txt_out o _ xl = let o = std o in out_txt_ o [] xl
346 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
349 let rec iter f = function
353 if r1 = U.mql_false then (iter f tail) else r1
355 let arity_p = Const 0 in
357 let body e _ _ _ xl = iter e.eval xl in
358 let txt_out o _ = function
359 | [x1; x2] -> let o = std o in out_txt2 o "||" x1 x2
360 | xl -> let o = std o in out_txt_ o ["or"] xl
362 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
365 let rec iter f = function
369 if f head = U.mql_false then U.mql_false else iter f tail
371 let arity_p = Const 0 in
373 let body e _ _ _ xl = iter e.eval xl in
374 let txt_out o _ = function
375 | [x1; x2] -> let o = std o in out_txt2 o "&&" x1 x2
376 | xl -> let o = std o in out_txt_ o ["and"] xl
378 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
381 let rec iter f = function
384 | head :: tail -> ignore (f head); iter f tail
386 let arity_p = Const 0 in
388 let body e _ _ _ xl = iter e.eval xl in
389 let txt_out o _ = function
391 let o = std o in o.s_query x1; o.s_out " ;; "; o.s_query x2
392 | xl -> let o = std o in out_txt_ o ["seq"] xl
394 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
397 let proj_group_aux p (q, v) = if q = p then U.mql_subj v else [] in
398 let proj_group p a = U.mql_iter (proj_group_aux p) a in
399 let proj_set p (_, g) = U.mql_iter (proj_group p) g in
400 let arity_p = Const 1 in
401 let arity_s = Const 1 in
402 let body e _ _ pl xl =
404 | [p], [x] -> U.mql_iter (proj_set p) (e.eval x)
407 let txt_out o pl xl =
411 o.s_out "proj "; o.s_path p; o.s_out " of "; o.s_query x
414 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
417 let proj (r, _) = (r, []) in
418 let keep_path l (p, v) t = if List.mem p l = b then t else (p, v) :: t in
419 let keep_grp l a = List.fold_right (keep_path l) a [] in
421 let kg = keep_grp l a in
422 if kg = [] then g else kg :: g
424 let keep_av l (s, g) = (s, List.fold_right (keep_set l) g []) in
425 let txt_allbut o = if b then o.s_out "allbut " in
426 let txt_path_list o l = P.flat_list o.s_out o.s_path ", " l in
428 let arity_s = Const 1 in
429 let body e _ _ pl xl =
431 | true, [], [x] -> e.eval x
432 | false, [], [x] -> List.map proj (e.eval x)
433 | _, l, [x] -> List.map (keep_av l) (e.eval x)
436 let txt_out o pl xl =
440 o.s_out "keep "; txt_allbut o; o.s_query x
443 o.s_out "keep "; txt_allbut o; txt_path_list o l;
444 o.s_out " in "; o.s_query x
447 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
449 (* external functions interface *********************************************)
451 let fun_get_spec = function
452 | ["empty"] -> false_fun false
453 | ["false"] -> false_fun true
454 | ["true"] -> true_fun
456 | ["count"] -> count_fun
457 | ["stat"] -> stat_fun
458 | ["log"; "text"; "result"] -> log_fun false false
459 | ["log"; "text"; "source"] -> log_fun false true
460 | ["render"] -> render_fun
461 | ["read"] -> read_fun
462 | ["peek"] -> peek_fun
463 | ["diff"] -> diff_fun
466 | ["meet"] -> meet_fun
470 | ["align"] -> align_fun
472 | ["intersect"] -> intersect_fun
473 | ["union"] -> union_fun
477 | ["proj"] -> proj_fun
478 | ["keep"; "these"] -> keep_fun false
479 | ["keep"; "allbut"] -> keep_fun true
480 | p -> raise (NameError p)
482 let fun_arity p m n =
483 check_arity p m (fun_get_spec p).arity_p;
484 check_arity p n (fun_get_spec p).arity_s
486 let fun_eval e o i p pl xl = (fun_get_spec p).body e o i pl xl
488 let fun_txt_out o p pl xl =
489 try (fun_get_spec p).txt_out o pl xl
490 with NameError q when q = p -> out_txt_full (std o) p pl xl
492 (* generator functions implementation ***************************************)
495 let mk_let v s x = M.Let (v, M.Const [(s, [])], x) in
496 let arity = Const 1 in
497 let code _ = function
498 | [x] -> mk_let "SET" "Set" x
501 {arity = arity; code = code}
503 (* generator functions interface ********************************************)
505 let gen_get_spec = function
506 | ["helm"; "vars"] -> helm_vars_gen
507 | p -> raise (NameError p)
509 let gen_arity p n = check_arity p n (gen_get_spec p).arity
511 let gen_eval e p xl = (gen_get_spec p).code e xl