(* camlp4r *) (* This file has been generated by program: do not edit! *) (* Added statements: At toplevel (structure item): DEFINE DEFINE = DEFINE () = IFDEF THEN (END | ENDIF) IFDEF THEN ELSE (END | ENDIF) IFNDEF THEN (END | ENDIF) IFNDEF THEN ELSE (END | ENDIF) INCLUDE In expressions: IFDEF THEN ELSE (END | ENDIF) IFNDEF THEN ELSE (END | ENDIF) __FILE__ __LOCATION__ In patterns: IFDEF THEN ELSE (END | ENDIF) IFNDEF THEN ELSE (END | ENDIF) As Camlp4 options: -D define -U undefine it -I add to the search path for INCLUDE'd files After having used a DEFINE followed by "= ", you can use it in expressions *and* in patterns. If the expression defining the macro cannot be used as a pattern, there is an error message if it is used in a pattern. The toplevel statement INCLUDE can be used to include a file containing macro definitions; note that files included in such a way can not have any non-macro toplevel items. The included files are looked up in directories passed in via the -I option, falling back to the current directory. The expression __FILE__ returns the current compiled file name. The expression __LOCATION__ returns the current location of itself. *) (* #load "pa_extend.cmo" *) (* #load "q_MLast.cmo" *) open Pcaml;; type 'a item_or_def = SdStr of 'a | SdDef of string * (string list * MLast.expr) option | SdUnd of string | SdITE of string * 'a item_or_def list * 'a item_or_def list | SdInc of string ;; let rec list_remove x = function (y, _) :: l when y = x -> l | d :: l -> d :: list_remove x l | [] -> [] ;; let defined = ref [];; let is_defined i = List.mem_assoc i !defined;; let _loc = let nowhere = {(Lexing.dummy_pos) with Lexing.pos_lnum = 1; Lexing.pos_cnum = 0} in nowhere, nowhere ;; let subst mloc env = let rec loop = function MLast.ExLet (_, rf, pel, e) -> let pel = List.map (fun (p, e) -> p, loop e) pel in MLast.ExLet (_loc, rf, pel, loop e) | MLast.ExIfe (_, e1, e2, e3) -> MLast.ExIfe (_loc, loop e1, loop e2, loop e3) | MLast.ExApp (_, e1, e2) -> MLast.ExApp (_loc, loop e1, loop e2) | MLast.ExFun (_, [args, None, e]) -> MLast.ExFun (_loc, [args, None, loop e]) | MLast.ExFun (_, peoel) -> MLast.ExFun (_loc, List.map loop_peoel peoel) | MLast.ExLid (_, x) | MLast.ExUid (_, x) as e -> begin try MLast.ExAnt (_loc, List.assoc x env) with Not_found -> e end | MLast.ExTup (_, x) -> MLast.ExTup (_loc, List.map loop x) | MLast.ExSeq (_, x) -> MLast.ExSeq (_loc, List.map loop x) | MLast.ExRec (_, pel, None) -> let pel = List.map (fun (p, e) -> p, loop e) pel in MLast.ExRec (_loc, pel, None) | MLast.ExMat (_, e, peoel) -> MLast.ExMat (_loc, loop e, List.map loop_peoel peoel) | MLast.ExTry (_, e, pel) -> let loop' = function p, Some e1, e2 -> p, Some (loop e1), loop e2 | p, None, e2 -> p, None, loop e2 in MLast.ExTry (_loc, loop e, List.map loop' pel) | e -> e and loop_peoel = function p, Some e1, e2 -> p, Some (loop e1), loop e2 | p, None, e2 -> p, None, loop e2 in loop ;; let substp mloc env = let rec loop = function MLast.ExApp (_, e1, e2) -> MLast.PaApp (_loc, loop e1, loop e2) | MLast.ExLid (_, x) -> begin try MLast.PaAnt (_loc, List.assoc x env) with Not_found -> MLast.PaLid (_loc, x) end | MLast.ExUid (_, x) -> begin try MLast.PaAnt (_loc, List.assoc x env) with Not_found -> MLast.PaUid (_loc, x) end | MLast.ExInt (_, x) -> MLast.PaInt (_loc, x) | MLast.ExStr (_, s) -> MLast.PaStr (_loc, s) | MLast.ExTup (_, x) -> MLast.PaTup (_loc, List.map loop x) | MLast.ExRec (_, pel, None) -> let ppl = List.map (fun (p, e) -> p, loop e) pel in MLast.PaRec (_loc, ppl) | x -> Stdpp.raise_with_loc mloc (Failure "this macro cannot be used in a pattern (see its definition)") in loop ;; let incorrect_number loc l1 l2 = Stdpp.raise_with_loc loc (Failure (Printf.sprintf "expected %d parameters; found %d" (List.length l2) (List.length l1))) ;; let define eo x = begin match eo with Some ([], e) -> Grammar.extend [Grammar.Entry.obj (expr : 'expr Grammar.Entry.e), Some (Gramext.Level "simple"), [None, None, [[Gramext.Stoken ("UIDENT", x)], Gramext.action (fun _ (_loc : Lexing.position * Lexing.position) -> (Pcaml.expr_reloc (fun _ -> _loc) (fst _loc) e : 'expr))]]; Grammar.Entry.obj (patt : 'patt Grammar.Entry.e), Some (Gramext.Level "simple"), [None, None, [[Gramext.Stoken ("UIDENT", x)], Gramext.action (fun _ (_loc : Lexing.position * Lexing.position) -> (let p = substp _loc [] e in Pcaml.patt_reloc (fun _ -> _loc) (fst _loc) p : 'patt))]]] | Some (sl, e) -> Grammar.extend [Grammar.Entry.obj (expr : 'expr Grammar.Entry.e), Some (Gramext.Level "apply"), [None, None, [[Gramext.Stoken ("UIDENT", x); Gramext.Sself], Gramext.action (fun (param : 'expr) _ (_loc : Lexing.position * Lexing.position) -> (let el = match param with MLast.ExTup (_, el) -> el | e -> [e] in if List.length el = List.length sl then let env = List.combine sl el in let e = subst _loc env e in Pcaml.expr_reloc (fun _ -> _loc) (fst _loc) e else incorrect_number _loc el sl : 'expr))]]; Grammar.Entry.obj (patt : 'patt Grammar.Entry.e), Some (Gramext.Level "simple"), [None, None, [[Gramext.Stoken ("UIDENT", x); Gramext.Sself], Gramext.action (fun (param : 'patt) _ (_loc : Lexing.position * Lexing.position) -> (let pl = match param with MLast.PaTup (_, pl) -> pl | p -> [p] in if List.length pl = List.length sl then let env = List.combine sl pl in let p = substp _loc env e in Pcaml.patt_reloc (fun _ -> _loc) (fst _loc) p else incorrect_number _loc pl sl : 'patt))]]] | None -> () end; defined := (x, eo) :: !defined ;; let undef x = try let eo = List.assoc x !defined in begin match eo with Some ([], _) -> Grammar.delete_rule expr [Gramext.Stoken ("UIDENT", x)]; Grammar.delete_rule patt [Gramext.Stoken ("UIDENT", x)] | Some (_, _) -> Grammar.delete_rule expr [Gramext.Stoken ("UIDENT", x); Gramext.Sself]; Grammar.delete_rule patt [Gramext.Stoken ("UIDENT", x); Gramext.Sself] | None -> () end; defined := list_remove x !defined with Not_found -> () ;; (* This is a list of directories to search for INCLUDE statements. *) let include_dirs = ref [];; (* Add something to the above, make sure it ends with a slash. *) let add_include_dir str = if str <> "" then let str = if String.get str (String.length str - 1) = '/' then str else str ^ "/" in include_dirs := !include_dirs @ [str] ;; let smlist = Grammar.Entry.create Pcaml.gram "smlist";; let parse_include_file = let dir_ok file dir = Sys.file_exists (dir ^ file) in fun file -> let file = try List.find (dir_ok file) (!include_dirs @ ["./"]) ^ file with Not_found -> file in let ch = open_in file in let st = Stream.of_channel ch in let old_input = !(Pcaml.input_file) in let (bol_ref, lnum_ref, name_ref) = !(Pcaml.position) in let (old_bol, old_lnum, old_name) = !bol_ref, !lnum_ref, !name_ref in let restore () = close_in ch; bol_ref := old_bol; lnum_ref := old_lnum; name_ref := old_name; Pcaml.input_file := old_input in bol_ref := 0; lnum_ref := 1; name_ref := file; Pcaml.input_file := file; try let items = Grammar.Entry.parse smlist st in restore (); items with exn -> restore (); raise exn ;; let rec execute_macro = function SdStr i -> [i] | SdDef (x, eo) -> define eo x; [] | SdUnd x -> undef x; [] | SdITE (i, l1, l2) -> execute_macro_list (if is_defined i then l1 else l2) | SdInc f -> execute_macro_list (parse_include_file f) and execute_macro_list = function [] -> [] | hd :: tl -> let il1 = execute_macro hd in let il2 = execute_macro_list tl in il1 @ il2 ;; Grammar.extend (let _ = (expr : 'expr Grammar.Entry.e) and _ = (patt : 'patt Grammar.Entry.e) and _ = (str_item : 'str_item Grammar.Entry.e) and _ = (sig_item : 'sig_item Grammar.Entry.e) and _ = (smlist : 'smlist Grammar.Entry.e) in let grammar_entry_create s = Grammar.Entry.create (Grammar.of_entry expr) s in let macro_def : 'macro_def Grammar.Entry.e = grammar_entry_create "macro_def" and endif : 'endif Grammar.Entry.e = grammar_entry_create "endif" and str_item_or_macro : 'str_item_or_macro Grammar.Entry.e = grammar_entry_create "str_item_or_macro" and opt_macro_value : 'opt_macro_value Grammar.Entry.e = grammar_entry_create "opt_macro_value" and uident : 'uident Grammar.Entry.e = grammar_entry_create "uident" in [Grammar.Entry.obj (str_item : 'str_item Grammar.Entry.e), Some Gramext.First, [None, None, [[Gramext.Snterm (Grammar.Entry.obj (macro_def : 'macro_def Grammar.Entry.e))], Gramext.action (fun (x : 'macro_def) (_loc : Lexing.position * Lexing.position) -> (match execute_macro x with [si] -> si | sil -> MLast.StDcl (_loc, sil) : 'str_item))]]; Grammar.Entry.obj (macro_def : 'macro_def Grammar.Entry.e), None, [None, None, [[Gramext.Stoken ("", "INCLUDE"); Gramext.Stoken ("STRING", "")], Gramext.action (fun (fname : string) _ (_loc : Lexing.position * Lexing.position) -> (SdInc fname : 'macro_def)); [Gramext.Stoken ("", "IFNDEF"); Gramext.Snterm (Grammar.Entry.obj (uident : 'uident Grammar.Entry.e)); Gramext.Stoken ("", "THEN"); Gramext.Snterm (Grammar.Entry.obj (smlist : 'smlist Grammar.Entry.e)); Gramext.Stoken ("", "ELSE"); Gramext.Snterm (Grammar.Entry.obj (smlist : 'smlist Grammar.Entry.e)); Gramext.Snterm (Grammar.Entry.obj (endif : 'endif Grammar.Entry.e))], Gramext.action (fun (_ : 'endif) (dl2 : 'smlist) _ (dl1 : 'smlist) _ (i : 'uident) _ (_loc : Lexing.position * Lexing.position) -> (SdITE (i, dl2, dl1) : 'macro_def)); [Gramext.Stoken ("", "IFNDEF"); Gramext.Snterm (Grammar.Entry.obj (uident : 'uident Grammar.Entry.e)); Gramext.Stoken ("", "THEN"); Gramext.Snterm (Grammar.Entry.obj (smlist : 'smlist Grammar.Entry.e)); Gramext.Snterm (Grammar.Entry.obj (endif : 'endif Grammar.Entry.e))], Gramext.action (fun (_ : 'endif) (dl : 'smlist) _ (i : 'uident) _ (_loc : Lexing.position * Lexing.position) -> (SdITE (i, [], dl) : 'macro_def)); [Gramext.Stoken ("", "IFDEF"); Gramext.Snterm (Grammar.Entry.obj (uident : 'uident Grammar.Entry.e)); Gramext.Stoken ("", "THEN"); Gramext.Snterm (Grammar.Entry.obj (smlist : 'smlist Grammar.Entry.e)); Gramext.Stoken ("", "ELSE"); Gramext.Snterm (Grammar.Entry.obj (smlist : 'smlist Grammar.Entry.e)); Gramext.Snterm (Grammar.Entry.obj (endif : 'endif Grammar.Entry.e))], Gramext.action (fun (_ : 'endif) (dl2 : 'smlist) _ (dl1 : 'smlist) _ (i : 'uident) _ (_loc : Lexing.position * Lexing.position) -> (SdITE (i, dl1, dl2) : 'macro_def)); [Gramext.Stoken ("", "IFDEF"); Gramext.Snterm (Grammar.Entry.obj (uident : 'uident Grammar.Entry.e)); Gramext.Stoken ("", "THEN"); Gramext.Snterm (Grammar.Entry.obj (smlist : 'smlist Grammar.Entry.e)); Gramext.Snterm (Grammar.Entry.obj (endif : 'endif Grammar.Entry.e))], Gramext.action (fun (_ : 'endif) (dl : 'smlist) _ (i : 'uident) _ (_loc : Lexing.position * Lexing.position) -> (SdITE (i, dl, []) : 'macro_def)); [Gramext.Stoken ("", "UNDEF"); Gramext.Snterm (Grammar.Entry.obj (uident : 'uident Grammar.Entry.e))], Gramext.action (fun (i : 'uident) _ (_loc : Lexing.position * Lexing.position) -> (SdUnd i : 'macro_def)); [Gramext.Stoken ("", "DEFINE"); Gramext.Snterm (Grammar.Entry.obj (uident : 'uident Grammar.Entry.e)); Gramext.Snterm (Grammar.Entry.obj (opt_macro_value : 'opt_macro_value Grammar.Entry.e))], Gramext.action (fun (def : 'opt_macro_value) (i : 'uident) _ (_loc : Lexing.position * Lexing.position) -> (SdDef (i, def) : 'macro_def))]]; Grammar.Entry.obj (smlist : 'smlist Grammar.Entry.e), None, [None, None, [[Gramext.Slist1 (Gramext.Snterm (Grammar.Entry.obj (str_item_or_macro : 'str_item_or_macro Grammar.Entry.e)))], Gramext.action (fun (sml : 'str_item_or_macro list) (_loc : Lexing.position * Lexing.position) -> (sml : 'smlist))]]; Grammar.Entry.obj (endif : 'endif Grammar.Entry.e), None, [None, None, [[Gramext.Stoken ("", "ENDIF")], Gramext.action (fun _ (_loc : Lexing.position * Lexing.position) -> (() : 'endif)); [Gramext.Stoken ("", "END")], Gramext.action (fun _ (_loc : Lexing.position * Lexing.position) -> (() : 'endif))]]; Grammar.Entry.obj (str_item_or_macro : 'str_item_or_macro Grammar.Entry.e), None, [None, None, [[Gramext.Snterm (Grammar.Entry.obj (str_item : 'str_item Grammar.Entry.e))], Gramext.action (fun (si : 'str_item) (_loc : Lexing.position * Lexing.position) -> (SdStr si : 'str_item_or_macro)); [Gramext.Snterm (Grammar.Entry.obj (macro_def : 'macro_def Grammar.Entry.e))], Gramext.action (fun (d : 'macro_def) (_loc : Lexing.position * Lexing.position) -> (d : 'str_item_or_macro))]]; Grammar.Entry.obj (opt_macro_value : 'opt_macro_value Grammar.Entry.e), None, [None, None, [[], Gramext.action (fun (_loc : Lexing.position * Lexing.position) -> (None : 'opt_macro_value)); [Gramext.Stoken ("", "="); Gramext.Snterm (Grammar.Entry.obj (expr : 'expr Grammar.Entry.e))], Gramext.action (fun (e : 'expr) _ (_loc : Lexing.position * Lexing.position) -> (Some ([], e) : 'opt_macro_value)); [Gramext.Stoken ("", "("); Gramext.Slist1sep (Gramext.Stoken ("LIDENT", ""), Gramext.Stoken ("", ",")); Gramext.Stoken ("", ")"); Gramext.Stoken ("", "="); Gramext.Snterm (Grammar.Entry.obj (expr : 'expr Grammar.Entry.e))], Gramext.action (fun (e : 'expr) _ _ (pl : string list) _ (_loc : Lexing.position * Lexing.position) -> (Some (pl, e) : 'opt_macro_value))]]; Grammar.Entry.obj (expr : 'expr Grammar.Entry.e), Some (Gramext.Level "top"), [None, None, [[Gramext.Stoken ("", "IFNDEF"); Gramext.Snterm (Grammar.Entry.obj (uident : 'uident Grammar.Entry.e)); Gramext.Stoken ("", "THEN"); Gramext.Sself; Gramext.Stoken ("", "ELSE"); Gramext.Sself; Gramext.Snterm (Grammar.Entry.obj (endif : 'endif Grammar.Entry.e))], Gramext.action (fun (_ : 'endif) (e2 : 'expr) _ (e1 : 'expr) _ (i : 'uident) _ (_loc : Lexing.position * Lexing.position) -> (if is_defined i then e2 else e1 : 'expr)); [Gramext.Stoken ("", "IFDEF"); Gramext.Snterm (Grammar.Entry.obj (uident : 'uident Grammar.Entry.e)); Gramext.Stoken ("", "THEN"); Gramext.Sself; Gramext.Stoken ("", "ELSE"); Gramext.Sself; Gramext.Snterm (Grammar.Entry.obj (endif : 'endif Grammar.Entry.e))], Gramext.action (fun (_ : 'endif) (e2 : 'expr) _ (e1 : 'expr) _ (i : 'uident) _ (_loc : Lexing.position * Lexing.position) -> (if is_defined i then e1 else e2 : 'expr))]]; Grammar.Entry.obj (expr : 'expr Grammar.Entry.e), Some (Gramext.Level "simple"), [None, None, [[Gramext.Stoken ("LIDENT", "__LOCATION__")], Gramext.action (fun _ (_loc : Lexing.position * Lexing.position) -> (let bp = string_of_int (fst _loc).Lexing.pos_cnum in let ep = string_of_int (snd _loc).Lexing.pos_cnum in MLast.ExTup (_loc, [MLast.ExInt (_loc, bp); MLast.ExInt (_loc, ep)]) : 'expr)); [Gramext.Stoken ("LIDENT", "__FILE__")], Gramext.action (fun _ (_loc : Lexing.position * Lexing.position) -> (MLast.ExStr (_loc, !(Pcaml.input_file)) : 'expr))]]; Grammar.Entry.obj (patt : 'patt Grammar.Entry.e), None, [None, None, [[Gramext.Stoken ("", "IFNDEF"); Gramext.Snterm (Grammar.Entry.obj (uident : 'uident Grammar.Entry.e)); Gramext.Stoken ("", "THEN"); Gramext.Sself; Gramext.Stoken ("", "ELSE"); Gramext.Sself; Gramext.Snterm (Grammar.Entry.obj (endif : 'endif Grammar.Entry.e))], Gramext.action (fun (_ : 'endif) (p2 : 'patt) _ (p1 : 'patt) _ (i : 'uident) _ (_loc : Lexing.position * Lexing.position) -> (if is_defined i then p2 else p1 : 'patt)); [Gramext.Stoken ("", "IFDEF"); Gramext.Snterm (Grammar.Entry.obj (uident : 'uident Grammar.Entry.e)); Gramext.Stoken ("", "THEN"); Gramext.Sself; Gramext.Stoken ("", "ELSE"); Gramext.Sself; Gramext.Snterm (Grammar.Entry.obj (endif : 'endif Grammar.Entry.e))], Gramext.action (fun (_ : 'endif) (p2 : 'patt) _ (p1 : 'patt) _ (i : 'uident) _ (_loc : Lexing.position * Lexing.position) -> (if is_defined i then p1 else p2 : 'patt))]]; Grammar.Entry.obj (uident : 'uident Grammar.Entry.e), None, [None, None, [[Gramext.Stoken ("UIDENT", "")], Gramext.action (fun (i : string) (_loc : Lexing.position * Lexing.position) -> (i : 'uident))]]]);; Pcaml.add_option "-D" (Arg.String (define None)) " Define for IFDEF instruction.";; Pcaml.add_option "-U" (Arg.String undef) " Undefine for IFDEF instruction.";; Pcaml.add_option "-I" (Arg.String add_include_dir) " Add a directory to INCLUDE search path.";;