summaryrefslogtreecommitdiff
path: root/parsing/q_util.ml4
blob: da4329bb3e3c05c4cfc018094872babef5de6a9e (plain)
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
(************************************************************************)
(*  v      *   The Coq Proof Assistant  /  The Coq Development Team     *)
(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
(*   \VV/  **************************************************************)
(*    //   *      This file is distributed under the terms of the       *)
(*         *       GNU Lesser General Public License Version 2.1        *)
(************************************************************************)

(*i camlp4use: "q_MLast.cmo" i*)

(* $Id: q_util.ml4 11309 2008-08-06 10:30:35Z herbelin $ *)

(* This file defines standard combinators to build ml expressions *)

open Util

let not_impl name x =
  let desc =
    if Obj.is_block (Obj.repr x) then
      "tag = " ^ string_of_int (Obj.tag (Obj.repr x))
    else 
      "int_val = " ^ string_of_int (Obj.magic x)
  in
  failwith ("<Q_util." ^ name ^ ", not impl: " ^ desc)

let rec patt_of_expr e =
  let loc = MLast.loc_of_expr e in
  match e with
    | <:expr< $e1$.$e2$ >> -> <:patt< $patt_of_expr e1$.$patt_of_expr e2$ >>
    | <:expr< $e1$ $e2$ >> -> <:patt< $patt_of_expr e1$ $patt_of_expr e2$ >>
    | <:expr< loc >> -> <:patt< _ >>
    | <:expr< $lid:s$ >> -> <:patt< $lid:s$ >>
    | <:expr< $uid:s$ >> -> <:patt< $uid:s$ >>
    | <:expr< $str:s$ >> -> <:patt< $str:s$ >>
    | <:expr< $anti:e$ >> -> <:patt< $anti:patt_of_expr e$ >>
    | _ -> not_impl "patt_of_expr" e

let mlexpr_of_list f l =
  List.fold_right
    (fun e1 e2 ->
      let e1 = f e1 in
       let loc = join_loc (MLast.loc_of_expr e1) (MLast.loc_of_expr e2) in
       <:expr< [$e1$ :: $e2$] >>)
    l (let loc = dummy_loc in <:expr< [] >>)

let mlexpr_of_pair m1 m2 (a1,a2) =
  let e1 = m1 a1 and e2 = m2 a2 in
  let loc = join_loc (MLast.loc_of_expr e1) (MLast.loc_of_expr e2) in
  <:expr< ($e1$, $e2$) >>

let mlexpr_of_triple m1 m2 m3 (a1,a2,a3)=
  let e1 = m1 a1 and e2 = m2 a2 and e3 = m3 a3 in
  let loc = join_loc (MLast.loc_of_expr e1) (MLast.loc_of_expr e3) in
  <:expr< ($e1$, $e2$, $e3$) >>

let mlexpr_of_quadruple m1 m2 m3 m4 (a1,a2,a3,a4)=
  let e1 = m1 a1 and e2 = m2 a2 and e3 = m3 a3 and e4 = m4 a4 in
  let loc = join_loc (MLast.loc_of_expr e1) (MLast.loc_of_expr e4) in
  <:expr< ($e1$, $e2$, $e3$, $e4$) >>

(* We don't give location for tactic quotation! *)
let loc = dummy_loc


let mlexpr_of_bool = function
  | true -> <:expr< True >>
  | false -> <:expr< False >>

let mlexpr_of_int n = <:expr< $int:string_of_int n$ >>

let mlexpr_of_string s = <:expr< $str:s$ >>

let mlexpr_of_option f = function
  | None -> <:expr< None >>
  | Some e -> <:expr< Some $f e$ >>

open Vernacexpr
open Pcoq
open Genarg

let modifiers e =
<:expr<  Gramext.srules
    [([], Gramext.action(fun _loc -> []));
     ([Gramext.Stoken ("", "(");
       Gramext.Slist1sep ($e$, Gramext.Stoken ("", ","));
       Gramext.Stoken ("", ")")],
      Gramext.action (fun _ l _ _loc -> l))]
 >>

let rec interp_entry_name loc s sep =
  let l = String.length s in
  if l > 8 & String.sub s 0 3 = "ne_" & String.sub s (l-5) 5 = "_list" then
    let t, g = interp_entry_name loc (String.sub s 3 (l-8)) "" in
    List1ArgType t, <:expr< Gramext.Slist1 $g$ >>
  else if l > 12 & String.sub s 0 3 = "ne_" &
                   String.sub s (l-9) 9 = "_list_sep" then
    let t, g = interp_entry_name loc (String.sub s 3 (l-12)) "" in
    let sep = <:expr< Gramext.Stoken("",$str:sep$) >> in
    List1ArgType t, <:expr< Gramext.Slist1sep $g$ $sep$ >>
  else if l > 5 & String.sub s (l-5) 5 = "_list" then
    let t, g = interp_entry_name loc (String.sub s 0 (l-5)) "" in
    List0ArgType t, <:expr< Gramext.Slist0 $g$ >>
  else if l > 9 & String.sub s (l-9) 9 = "_list_sep" then
    let t, g = interp_entry_name loc (String.sub s 0 (l-9)) "" in
    let sep = <:expr< Gramext.Stoken("",$str:sep$) >> in
    List0ArgType t, <:expr< Gramext.Slist0sep $g$ $sep$ >>
  else if l > 4 & String.sub s (l-4) 4 = "_opt" then
    let t, g = interp_entry_name loc (String.sub s 0 (l-4)) "" in
    OptArgType t, <:expr< Gramext.Sopt $g$ >>
  else if l > 5 & String.sub s (l-5) 5 = "_mods" then
    let t, g = interp_entry_name loc (String.sub s 0 (l-1)) "" in
    List0ArgType t, modifiers g
  else
    let s = if s = "hyp" then "var" else s in
    let t, se, lev =
      match tactic_genarg_level s with
        | Some 5 ->
            Some (ExtraArgType s), <:expr< Tactic. binder_tactic >>, None
	| Some n ->
            Some (ExtraArgType s), <:expr< Tactic. tactic_expr >>, Some n
	| None ->
      match Pcoq.entry_type (Pcoq.get_univ "prim") s with
	| Some _ as x -> x, <:expr< Prim. $lid:s$ >>, None
	| None -> 
      match Pcoq.entry_type (Pcoq.get_univ "constr") s with
	| Some _ as x -> x, <:expr< Constr. $lid:s$ >>, None
	| None -> 
      match Pcoq.entry_type (Pcoq.get_univ "tactic") s with
	| Some _ as x -> x, <:expr< Tactic. $lid:s$ >>, None
	| None -> None, <:expr< $lid:s$ >>, None in
    let t =
      match t with
	| Some t -> t
	| None -> ExtraArgType s in
    let entry = match lev with
      | Some n ->
	  let s = string_of_int n in
	  <:expr< Gramext.Snterml (Pcoq.Gram.Entry.obj $se$, $str:s$) >>
      | None -> 
	  <:expr< Gramext.Snterm (Pcoq.Gram.Entry.obj $se$) >>
    in t, entry