}
type text_out_spec = {out : string -> unit;
- path : M.path -> unit;
- query : M.query -> unit;
- result : M.result -> unit
+ path : (string -> unit) -> M.path -> unit;
+ query : (string -> unit) -> string -> M.query -> unit;
+ result : (string -> unit) -> string -> M.result -> unit
}
+type text_in_spec = {result_in : Lexing.lexbuf -> M.result}
+
type fun_spec = {arity_p : arity_t;
arity_s : arity_t;
- body : eval_spec -> text_out_spec ->
+ body : eval_spec -> text_out_spec -> text_in_spec ->
M.path list -> M.query list -> M.result;
- txt_out : text_out_spec ->
+ txt_out : text_out_spec ->
M.path list -> M.query list -> unit
}
+type gen_spec = {arity : arity_t;
+ code : eval_spec -> M.query list -> M.query
+ }
+
exception ArityError of M.path * arity_t * int
exception NameError of M.path
exception NumberError of M.result
+type std_text_out_spec = {s_out : string -> unit;
+ s_path : M.path -> unit;
+ s_query : M.query -> unit;
+ s_result : M.result -> unit
+}
+
+let check_arity p i = function
+ | Const k when i = k -> ()
+ | Positive when i > 0 -> ()
+ | Any -> ()
+ | a -> raise (ArityError (p, a, i))
+
(* external functions implementation ****************************************)
-let int_of_set s =
- try match s with
- | [s, _] -> int_of_string s
+let std o =
+ {s_out = o.out; s_path = o.path o.out;
+ s_query = o.query o.out ""; s_result = o.result o.out "\n"
+ }
+
+type t = End
+ | Space
+ | Figure of int
+ | Error
+
+let my_int_of_string s =
+ let l = String.length s in
+ let get_t i =
+ if i = l then End else
+ match s.[i] with
+ | ' ' | '\t' | '\r' | 'n' -> Space
+ | '0' .. '9' -> Figure (Char.code s.[i] - Char.code '0')
+ | _ -> Error
+ in
+ let rec aux i xv = match get_t i, xv with
+ | Error, _
+ | End, None -> raise (Failure "int_of_string")
+ | End, Some v -> v
+ | Space, xv -> aux (succ i) xv
+ | Figure f, None -> aux (succ i) (Some f)
+ | Figure f, Some v -> aux (succ i) (Some (10 * v + f))
+ in
+ aux 0 None
+
+let int_of_set r =
+ try match r with
+ | [s, _] -> my_int_of_string s
| _ -> raise (Failure "int_of_string")
- with Failure "int_of_string" -> raise (NumberError s)
+ with Failure "int_of_string" -> raise (NumberError r)
let out_txt2 o n x1 x2 =
- o.out "(" ; o.query x1; o.out (" " ^ n ^ " "); o.query x2; o.out ")"
+ o.s_out "(" ; o.s_query x1; o.s_out (" " ^ n ^ " "); o.s_query x2; o.s_out ")"
let out_txt_ o p xl =
- if p <> [] then begin o.path p; o.out " " end;
- o.out "{"; P.flat_list o.out o.query ", " xl; o.out "}"
+ if p <> [] then begin o.s_path p; o.s_out " " end;
+ o.s_out "{"; P.flat_list o.s_out o.s_query ", " xl; o.s_out "}"
let out_txt_full o p pl xl =
- o.path p; o.out " {"; P.flat_list o.out o.path ", " pl; o.out "} {";
- P.flat_list o.out o.query ", " xl; o.out "}"
+ o.s_path p; o.s_out " {"; P.flat_list o.s_out o.s_path ", " pl; o.s_out "} {";
+ P.flat_list o.s_out o.s_query ", " xl; o.s_out "}"
let arity0 n r =
let arity_p = Const 0 in
let arity_s = Const 0 in
- let body _ _ _ _ = U.mql_true in
- let txt_out o _ _ = o.out n in
+ let body _ _ _ _ _ = r in
+ let txt_out o _ _ = (std o).s_out n in
{arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
let arity1 n f =
let arity_p = Const 0 in
let arity_s = Const 1 in
- let body e _ _ = function
+ let body e _ _ _ = function
| [x] -> f (e.eval x)
| _ -> assert false
in
let txt_out o _ = function
- | [x] -> o.out (n ^ " "); o.query x
+ | [x] -> let o = std o in o.s_out (n ^ " "); o.s_query x
| _ -> assert false
in
{arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
let arity2 n f =
let arity_p = Const 0 in
let arity_s = Const 2 in
- let body e _ _ = function
+ let body e _ _ _ = function
| [x1; x2] -> f (e.eval x1) (e.eval x2)
| _ -> assert false
in
let txt_out o _ = function
- | [x1; x2] -> out_txt2 o n x1 x2
+ | [x1; x2] -> let o = std o in out_txt2 o n x1 x2
| _ -> assert false
in
{arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
let count_fun =
let aux r = [string_of_int (List.length r), []] in
arity1 "#" aux
-
+
+let peek_fun =
+ let aux = function [] -> [] | hd :: _ -> [hd] in
+ arity1 "peek" aux
+
let diff_fun = arity2 "diff" U.mql_diff
let xor_fun = arity2 "xor" U.xor
let stat_fun =
let arity_p = Const 0 in
let arity_s = Const 1 in
- let body e o _ = function
+ let body e o _ _ = function
| [x] ->
let t = P.start_time () in
let r = (e.eval x) in
| _ -> assert false
in
let txt_out o _ = function
- | [x] -> o.out "stat "; o.query x
+ | [x] -> let o = std o in o.s_out "stat "; o.s_query x
| _ -> assert false
in
{arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
let log_fun xml src =
let log_src e o x =
- let t = P.start_time () in o.query x;
+ let t = P.start_time () in o.s_query x;
let s = P.stop_time t in
- if C.set e.conn C.Stat then o.out (Printf.sprintf "Log source: %s\n" s);
+ if C.set e.conn C.Stat then o.s_out (Printf.sprintf "Log source: %s\n" s);
e.eval x
in
let log_res e o x =
let s = e.eval x in
- let t = P.start_time () in o.result s;
+ let t = P.start_time () in o.s_result s;
let r = P.stop_time t in
- if C.set e.conn C.Stat then o.out (Printf.sprintf "Log: %s\n" r); s
+ if C.set e.conn C.Stat then o.s_out (Printf.sprintf "Log: %s\n" r); s
in
let txt_log o =
- if xml then o.out "xml ";
- if src then o.out "source "
+ if xml then o.s_out "xml ";
+ if src then o.s_out "source "
in
let arity_p = Const 0 in
let arity_s = Const 1 in
- let body e o _ = function
- | [x] -> if src then log_src e o x else log_res e o x
+ let body e o _ _ = function
+ | [x] -> let o = std o in if src then log_src e o x else log_res e o x
| _ -> assert false
in
let txt_out o _ = function
- | [x] -> o.out "log "; txt_log o; o.query x
+ | [x] -> let o = std o in o.s_out "log "; txt_log o; o.s_query x
+ | _ -> assert false
+ in
+ {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
+
+let render_fun =
+ let arity_p = Const 0 in
+ let arity_s = Const 1 in
+ let body e o _ _ = function
+ | [x] ->
+ let rs = ref "" in
+ let out s = rs := ! rs ^ s in
+ o.result out " " (e.eval x);
+ [! rs, []]
+ | _ -> assert false
+ in
+ let txt_out o _ = function
+ | [x] -> let o = std o in o.s_out "render "; o.s_query x
+ | _ -> assert false
+ in
+ {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
+
+let read_fun =
+ let arity_p = Const 0 in
+ let arity_s = Const 1 in
+ let body e o i _ = function
+ | [x] ->
+ let aux av =
+ let ich = open_in (fst av) in
+ let r = i.result_in (Lexing.from_channel ich) in
+ close_in ich; r
+ in
+ U.mql_iter aux (e.eval x)
+ | _ -> assert false
+ in
+ let txt_out o _ = function
+ | [x] -> let o = std o in o.s_out "read "; o.s_query x
| _ -> assert false
in
{arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
in
let arity_p = Const 0 in
let arity_s = Const 2 in
- let body e _ _ = function
+ let body e _ _ _ = function
| [y; x] ->
let l = int_of_set (e.eval y) in
U.mql_iter (aux l) (e.eval x)
| _ -> assert false
in
let txt_out o _ = function
- | [y; x] -> o.out "align "; o.query y; o.out " in "; o.query x
+ | [y; x] ->
+ let o = std o in
+ o.s_out "align "; o.s_query y; o.s_out " in "; o.s_query x
| _ -> assert false
in
{arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
let if_fun =
let arity_p = Const 0 in
let arity_s = Const 3 in
- let body e _ _ = function
+ let body e _ _ _ = function
| [y; x1; x2] ->
if (e.eval y) = U.mql_false then (e.eval x2) else (e.eval x1)
| _ -> assert false
in
let txt_out o _ = function
| [y; x1; x2] ->
- o.out "if "; o.query y; o.out " then "; o.query x1;
- o.out " else "; o.query x2
+ let o = std o in
+ o.s_out "if "; o.s_query y; o.s_out " then "; o.s_query x1;
+ o.s_out " else "; o.s_query x2
| _ -> assert false
in
{arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
in
let arity_p = Const 0 in
let arity_s = Positive in
- let body e _ _ xl = iter e.eval xl in
+ let body e _ _ _ xl = iter e.eval xl in
let txt_out o _ = function
| [] -> assert false
- | [x1; x2] -> out_txt2 o "/\\" x1 x2
- | xl -> out_txt_ o ["intersect"] xl
+ | [x1; x2] -> let o = std o in out_txt2 o "/\\" x1 x2
+ | xl -> let o = std o in out_txt_ o ["intersect"] xl
in
{arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
let union_fun =
let arity_p = Const 0 in
let arity_s = Any in
- let body e _ _ xl = U.mql_iter e.eval xl in
- let txt_out o _ xl = out_txt_ o [] xl
+ let body e _ _ _ xl = U.mql_iter e.eval xl in
+ let txt_out o _ xl = let o = std o in out_txt_ o [] xl
in
{arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
in
let arity_p = Const 0 in
let arity_s = Any in
- let body e _ _ xl = iter e.eval xl in
+ let body e _ _ _ xl = iter e.eval xl in
let txt_out o _ = function
- | [x1; x2] -> out_txt2 o "||" x1 x2
- | xl -> out_txt_ o ["or"] xl
+ | [x1; x2] -> let o = std o in out_txt2 o "||" x1 x2
+ | xl -> let o = std o in out_txt_ o ["or"] xl
in
{arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
let and_fun =
let rec iter f = function
| [] -> U.mql_true
+ | [head] -> f head
| head :: tail ->
if f head = U.mql_false then U.mql_false else iter f tail
in
let arity_p = Const 0 in
let arity_s = Any in
- let body e _ _ xl = iter e.eval xl in
+ let body e _ _ _ xl = iter e.eval xl in
let txt_out o _ = function
- | [x1; x2] -> out_txt2 o "&&" x1 x2
- | xl -> out_txt_ o ["and"] xl
+ | [x1; x2] -> let o = std o in out_txt2 o "&&" x1 x2
+ | xl -> let o = std o in out_txt_ o ["and"] xl
in
{arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
let seq_fun =
let rec iter f = function
| [] -> U.mql_true
+ | [head] -> f head
| head :: tail -> ignore (f head); iter f tail
in
let arity_p = Const 0 in
let arity_s = Any in
- let body e _ _ xl = iter e.eval xl in
+ let body e _ _ _ xl = iter e.eval xl in
let txt_out o _ = function
- | [x1; x2] -> o.query x1; o.out " ;; "; o.query x2
- | xl -> out_txt_ o ["seq"] xl
+ | [x1; x2] ->
+ let o = std o in o.s_query x1; o.s_out " ;; "; o.s_query x2
+ | xl -> let o = std o in out_txt_ o ["seq"] xl
in
{arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
let proj_set p (_, g) = U.mql_iter (proj_group p) g in
let arity_p = Const 1 in
let arity_s = Const 1 in
- let body e _ pl xl =
+ let body e _ _ pl xl =
match pl, xl with
| [p], [x] -> U.mql_iter (proj_set p) (e.eval x)
| _ -> assert false
in
let txt_out o pl xl =
match pl, xl with
- | [p], [x] -> o.out "proj "; o.path p; o.out " of "; o.query x
+ | [p], [x] ->
+ let o = std o in
+ o.s_out "proj "; o.s_path p; o.s_out " of "; o.s_query x
| _ -> assert false
in
{arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
if kg = [] then g else kg :: g
in
let keep_av l (s, g) = (s, List.fold_right (keep_set l) g []) in
- let txt_allbut o = if b then o.out "allbut " in
- let txt_path_list o l = P.flat_list o.out o.path ", " l in
+ let txt_allbut o = if b then o.s_out "allbut " in
+ let txt_path_list o l = P.flat_list o.s_out o.s_path ", " l in
let arity_p = Any in
let arity_s = Const 1 in
- let body e _ pl xl =
+ let body e _ _ pl xl =
match b, pl, xl with
| true, [], [x] -> e.eval x
| false, [], [x] -> List.map proj (e.eval x)
in
let txt_out o pl xl =
match pl, xl with
- | [], [x] -> o.out "keep "; txt_allbut o; o.query x
+ | [], [x] ->
+ let o = std o in
+ o.s_out "keep "; txt_allbut o; o.s_query x
| l, [x] ->
- o.out "keep "; txt_allbut o; txt_path_list o l;
- o.out " in "; o.query x
+ let o = std o in
+ o.s_out "keep "; txt_allbut o; txt_path_list o l;
+ o.s_out " in "; o.s_query x
| _ -> assert false
in
{arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
(* external functions interface *********************************************)
-let get_spec = function
+let fun_get_spec = function
| ["empty"] -> false_fun false
| ["false"] -> false_fun true
| ["true"] -> true_fun
| ["stat"] -> stat_fun
| ["log"; "text"; "result"] -> log_fun false false
| ["log"; "text"; "source"] -> log_fun false true
+ | ["render"] -> render_fun
+ | ["read"] -> read_fun
+ | ["peek"] -> peek_fun
| ["diff"] -> diff_fun
| ["xor"] -> xor_fun
| ["sub"] -> sub_fun
| ["keep"; "allbut"] -> keep_fun true
| p -> raise (NameError p)
-let check_arity p m n =
- let aux i = function
- | Const k when i = k -> ()
- | Positive when i > 0 -> ()
- | Any -> ()
- | a -> raise (ArityError (p, a, i))
- in
- aux m (get_spec p).arity_p; aux n (get_spec p).arity_s
+let fun_arity p m n =
+ check_arity p m (fun_get_spec p).arity_p;
+ check_arity p n (fun_get_spec p).arity_s
+
+let fun_eval e o i p pl xl = (fun_get_spec p).body e o i pl xl
+
+let fun_txt_out o p pl xl =
+ try (fun_get_spec p).txt_out o pl xl
+ with NameError q when q = p -> out_txt_full (std o) p pl xl
+
+(* generator functions implementation ***************************************)
+
+let helm_vars_gen =
+ let mk_let v s x = M.Let (v, M.Const [(s, [])], x) in
+ let arity = Const 1 in
+ let code _ = function
+ | [x] -> mk_let "SET" "Set" x
+ | _ -> assert false
+ in
+ {arity = arity; code = code}
+
+(* generator functions interface ********************************************)
+
+let gen_get_spec = function
+ | ["helm"; "vars"] -> helm_vars_gen
+ | p -> raise (NameError p)
-let eval e o p pl xl = (get_spec p).body e o pl xl
+let gen_arity p n = check_arity p n (gen_get_spec p).arity
-let txt_out o p pl xl =
- try (get_spec p).txt_out o pl xl
- with NameError q when q = p -> out_txt_full o p pl xl
+let gen_eval e p xl = (gen_get_spec p).code e xl