File: extfun.ml

package info (click to toggle)
camlp5 8.04.00-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 11,968 kB
  • sloc: ml: 137,918; makefile: 2,055; perl: 1,729; sh: 1,653; python: 38
file content (118 lines) | stat: -rw-r--r-- 2,712 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
(* camlp5r *)
(* extfun.ml,v *)
(* Copyright (c) INRIA 2007-2017 *)

(* Extensible Functions *)

type ('a, 'b) t = ('a, 'b) matching list
and ('a, 'b) matching = { patt : patt; has_when : bool; expr : ('a, 'b) expr }
and patt =
    Eapp of patt list
  | Eacc of patt list
  | Econ of string
  | Estr of string
  | Eint of string
  | Etup of patt list
  | Erec of (patt * patt) list
  | Evar of unit
and ('a, 'b) expr = 'a -> 'b option;;

exception Failure;;

let empty = [];;

(*** Apply ***)

let rec apply_matchings a =
  function
    m :: ml ->
      begin match m.expr a with
        None -> apply_matchings a ml
      | x -> x
      end
  | [] -> None
;;

let apply ef a =
  match apply_matchings a ef with
    Some x -> x
  | None -> raise Failure
;;

(*** Trace ***)

let rec list_iter_sep f s =
  function
    [] -> ()
  | [x] -> f x
  | x :: l -> f x; s (); list_iter_sep f s l
;;

let rec print_patt =
  function
    Eapp pl -> list_iter_sep print_patt2 (fun () -> print_string " ") pl
  | p -> print_patt2 p
and print_labeled_patt_pair (p1, p2) =
  print_patt p1; print_string " = "; print_patt p2
and print_patt2 =
  function
    Eacc pl -> list_iter_sep print_patt1 (fun () -> print_string ".") pl
  | p -> print_patt1 p
and print_patt1 =
  function
    Econ s -> print_string s
  | Estr s -> print_string "\""; print_string s; print_string "\""
  | Eint s -> print_string s
  | Evar () -> print_string "_"
  | Etup pl ->
      print_string "(";
      list_iter_sep print_patt (fun () -> print_string ", ") pl;
      print_string ")"
  | Erec l ->
      print_string "{";
      list_iter_sep print_labeled_patt_pair (fun () -> print_string "; ") l;
      print_string "}"
  | Eapp _ | Eacc _ as p -> print_string "("; print_patt p; print_string ")"
;;

let print ef =
  List.iter
    (fun m ->
       print_patt m.patt;
       if m.has_when then print_string " when ...";
       print_newline ())
    ef
;;

(*** Extension ***)

let compare_patt p1 p2 =
  match p1, p2 with
    Evar _, _ -> 1
  | _, Evar _ -> -1
  | _ -> compare p1 p2
;;

let insert_matching matchings (patt, has_when, expr) =
  let m1 = {patt = patt; has_when = has_when; expr = expr} in
  let rec loop =
    function
      m :: ml as gml ->
        if m1.has_when && not m.has_when then m1 :: gml
        else if not m1.has_when && m.has_when then m :: loop ml
        else
          let c = compare_patt m1.patt m.patt in
          if c < 0 then m1 :: gml
          else if c > 0 then m :: loop ml
          else if m.has_when then m1 :: gml
          else m1 :: ml
    | [] -> [m1]
  in
  loop matchings
;;

(* available extension function *)

let extend ef matchings_def =
  List.fold_left insert_matching ef matchings_def
;;