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 exception ArityError of M.path * arity_t * int
62 exception NameError of M.path
64 exception NumberError of M.result
66 type std_text_out_spec = {s_out : string -> unit;
67 s_path : M.path -> unit;
68 s_query : M.query -> unit;
69 s_result : M.result -> unit
72 (* external functions implementation ****************************************)
75 {s_out = o.out; s_path = o.path o.out;
76 s_query = o.query o.out ""; s_result = o.result o.out "\n"
84 let my_int_of_string s =
85 let l = String.length s in
87 if i = l then End else
89 | ' ' | '\t' | '\r' | 'n' -> Space
90 | '0' .. '9' -> Figure (Char.code s.[i] - Char.code '0')
93 let rec aux i xv = match get_t i, xv with
95 | End, None -> raise (Failure "int_of_string")
97 | Space, xv -> aux (succ i) xv
98 | Figure f, None -> aux (succ i) (Some f)
99 | Figure f, Some v -> aux (succ i) (Some (10 * v + f))
105 | [s, _] -> my_int_of_string s
106 | _ -> raise (Failure "int_of_string")
107 with Failure "int_of_string" -> raise (NumberError r)
109 let out_txt2 o n x1 x2 =
110 o.s_out "(" ; o.s_query x1; o.s_out (" " ^ n ^ " "); o.s_query x2; o.s_out ")"
112 let out_txt_ o p xl =
113 if p <> [] then begin o.s_path p; o.s_out " " end;
114 o.s_out "{"; P.flat_list o.s_out o.s_query ", " xl; o.s_out "}"
116 let out_txt_full o p pl xl =
117 o.s_path p; o.s_out " {"; P.flat_list o.s_out o.s_path ", " pl; o.s_out "} {";
118 P.flat_list o.s_out o.s_query ", " xl; o.s_out "}"
121 let arity_p = Const 0 in
122 let arity_s = Const 0 in
123 let body _ _ _ _ _ = r in
124 let txt_out o _ _ = (std o).s_out n in
125 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
128 let arity_p = Const 0 in
129 let arity_s = Const 1 in
130 let body e _ _ _ = function
131 | [x] -> f (e.eval x)
134 let txt_out o _ = function
135 | [x] -> let o = std o in o.s_out (n ^ " "); o.s_query x
138 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
141 let arity_p = Const 0 in
142 let arity_s = Const 2 in
143 let body e _ _ _ = function
144 | [x1; x2] -> f (e.eval x1) (e.eval x2)
147 let txt_out o _ = function
148 | [x1; x2] -> let o = std o in out_txt2 o n x1 x2
151 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
154 let s = if b then "false" else "empty" in
157 let true_fun = arity0 "true" U.mql_true
160 let aux r = if r = U.mql_false then U.mql_true else U.mql_false in
164 let aux r = [string_of_int (List.length r), []] in
168 let aux = function [] -> [] | hd :: _ -> [hd] in
171 let diff_fun = arity2 "diff" U.mql_diff
173 let xor_fun = arity2 "xor" U.xor
175 let sub_fun = arity2 "sub" U.set_sub
177 let meet_fun = arity2 "meet" U.set_meet
179 let eq_fun = arity2 "==" U.set_eq
183 if int_of_set v1 <= int_of_set v2 then U.mql_true else U.mql_false
189 if int_of_set v1 < int_of_set v2 then U.mql_true else U.mql_false
194 let arity_p = Const 0 in
195 let arity_s = Const 1 in
196 let body e o _ _ = function
198 let t = P.start_time () in
199 let r = (e.eval x) in
200 let s = P.stop_time t in
201 o.out (Printf.sprintf "Stat: %s,%i\n" s (List.length r));
205 let txt_out o _ = function
206 | [x] -> let o = std o in o.s_out "stat "; o.s_query x
209 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
211 let log_fun xml src =
213 let t = P.start_time () in o.s_query x;
214 let s = P.stop_time t in
215 if C.set e.conn C.Stat then o.s_out (Printf.sprintf "Log source: %s\n" s);
220 let t = P.start_time () in o.s_result s;
221 let r = P.stop_time t in
222 if C.set e.conn C.Stat then o.s_out (Printf.sprintf "Log: %s\n" r); s
225 if xml then o.s_out "xml ";
226 if src then o.s_out "source "
228 let arity_p = Const 0 in
229 let arity_s = Const 1 in
230 let body e o _ _ = function
231 | [x] -> let o = std o in if src then log_src e o x else log_res e o x
234 let txt_out o _ = function
235 | [x] -> let o = std o in o.s_out "log "; txt_log o; o.s_query x
238 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
241 let arity_p = Const 0 in
242 let arity_s = Const 1 in
243 let body e o _ _ = function
246 let out s = rs := ! rs ^ s in
247 o.result out " " (e.eval x);
251 let txt_out o _ = function
252 | [x] -> let o = std o in o.s_out "render "; o.s_query x
255 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
258 let arity_p = Const 0 in
259 let arity_s = Const 1 in
260 let body e o i _ = function
263 let ich = open_in (fst av) in
264 let r = i.result_in (Lexing.from_channel ich) in
267 U.mql_iter aux (e.eval x)
270 let txt_out o _ = function
271 | [x] -> let o = std o in o.s_out "read "; o.s_query x
274 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
278 let c = String.length v in
279 if c < l then [(String.make (l - c) ' ' ^ v), g] else [v, g]
281 let arity_p = Const 0 in
282 let arity_s = Const 2 in
283 let body e _ _ _ = function
285 let l = int_of_set (e.eval y) in
286 U.mql_iter (aux l) (e.eval x)
289 let txt_out o _ = function
292 o.s_out "align "; o.s_query y; o.s_out " in "; o.s_query x
295 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
298 let arity_p = Const 0 in
299 let arity_s = Const 3 in
300 let body e _ _ _ = function
302 if (e.eval y) = U.mql_false then (e.eval x2) else (e.eval x1)
305 let txt_out o _ = function
308 o.s_out "if "; o.s_query y; o.s_out " then "; o.s_query x1;
309 o.s_out " else "; o.s_query x2
312 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
315 let rec iter f = function
318 | head :: tail -> U.mql_intersect (f head) (iter f tail)
320 let arity_p = Const 0 in
321 let arity_s = Positive in
322 let body e _ _ _ xl = iter e.eval xl in
323 let txt_out o _ = function
325 | [x1; x2] -> let o = std o in out_txt2 o "/\\" x1 x2
326 | xl -> let o = std o in out_txt_ o ["intersect"] xl
328 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
331 let arity_p = Const 0 in
333 let body e _ _ _ xl = U.mql_iter e.eval xl in
334 let txt_out o _ xl = let o = std o in out_txt_ o [] xl
336 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
339 let rec iter f = function
343 if r1 = U.mql_false then (iter f tail) else r1
345 let arity_p = Const 0 in
347 let body e _ _ _ xl = iter e.eval xl in
348 let txt_out o _ = function
349 | [x1; x2] -> let o = std o in out_txt2 o "||" x1 x2
350 | xl -> let o = std o in out_txt_ o ["or"] xl
352 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
355 let rec iter f = function
359 if f head = U.mql_false then U.mql_false else iter f tail
361 let arity_p = Const 0 in
363 let body e _ _ _ xl = iter e.eval xl in
364 let txt_out o _ = function
365 | [x1; x2] -> let o = std o in out_txt2 o "&&" x1 x2
366 | xl -> let o = std o in out_txt_ o ["and"] xl
368 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
371 let rec iter f = function
374 | head :: tail -> ignore (f head); iter f tail
376 let arity_p = Const 0 in
378 let body e _ _ _ xl = iter e.eval xl in
379 let txt_out o _ = function
381 let o = std o in o.s_query x1; o.s_out " ;; "; o.s_query x2
382 | xl -> let o = std o in out_txt_ o ["seq"] xl
384 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
387 let proj_group_aux p (q, v) = if q = p then U.mql_subj v else [] in
388 let proj_group p a = U.mql_iter (proj_group_aux p) a in
389 let proj_set p (_, g) = U.mql_iter (proj_group p) g in
390 let arity_p = Const 1 in
391 let arity_s = Const 1 in
392 let body e _ _ pl xl =
394 | [p], [x] -> U.mql_iter (proj_set p) (e.eval x)
397 let txt_out o pl xl =
401 o.s_out "proj "; o.s_path p; o.s_out " of "; o.s_query x
404 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
407 let proj (r, _) = (r, []) in
408 let keep_path l (p, v) t = if List.mem p l = b then t else (p, v) :: t in
409 let keep_grp l a = List.fold_right (keep_path l) a [] in
411 let kg = keep_grp l a in
412 if kg = [] then g else kg :: g
414 let keep_av l (s, g) = (s, List.fold_right (keep_set l) g []) in
415 let txt_allbut o = if b then o.s_out "allbut " in
416 let txt_path_list o l = P.flat_list o.s_out o.s_path ", " l in
418 let arity_s = Const 1 in
419 let body e _ _ pl xl =
421 | true, [], [x] -> e.eval x
422 | false, [], [x] -> List.map proj (e.eval x)
423 | _, l, [x] -> List.map (keep_av l) (e.eval x)
426 let txt_out o pl xl =
430 o.s_out "keep "; txt_allbut o; o.s_query x
433 o.s_out "keep "; txt_allbut o; txt_path_list o l;
434 o.s_out " in "; o.s_query x
437 {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
439 (* external functions interface *********************************************)
441 let get_spec = function
442 | ["empty"] -> false_fun false
443 | ["false"] -> false_fun true
444 | ["true"] -> true_fun
446 | ["count"] -> count_fun
447 | ["stat"] -> stat_fun
448 | ["log"; "text"; "result"] -> log_fun false false
449 | ["log"; "text"; "source"] -> log_fun false true
450 | ["render"] -> render_fun
451 | ["read"] -> read_fun
452 | ["peek"] -> peek_fun
453 | ["diff"] -> diff_fun
456 | ["meet"] -> meet_fun
460 | ["align"] -> align_fun
462 | ["intersect"] -> intersect_fun
463 | ["union"] -> union_fun
467 | ["proj"] -> proj_fun
468 | ["keep"; "these"] -> keep_fun false
469 | ["keep"; "allbut"] -> keep_fun true
470 | p -> raise (NameError p)
472 let check_arity p m n =
474 | Const k when i = k -> ()
475 | Positive when i > 0 -> ()
477 | a -> raise (ArityError (p, a, i))
479 aux m (get_spec p).arity_p; aux n (get_spec p).arity_s
481 let eval e o i p pl xl = (get_spec p).body e o i pl xl
483 let txt_out o p pl xl =
484 try (get_spec p).txt_out o pl xl
485 with NameError q when q = p -> out_txt_full (std o) p pl xl