aboutsummaryrefslogtreecommitdiff
path: root/contrib/subtac/sparser.ml4
blob: b2dffa28f7d7360f048063016af31adf9d822a50 (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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
(************************************************************************)
(*  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        *)
(************************************************************************)

(*
  Syntax for the subtac terms and types.
  Elaborated from correctness/psyntax.ml4 by Jean-Christophe Filli�tre *)

(* $Id$ *)

(*i camlp4deps: "parsing/grammar.cma" i*)

open Options
open Util
open Names
open Nameops
open Vernacentries
open Reduction
open Term
open Libnames
open Topconstr

open Sast

(* We define new entries for programs, with the use of this module
 * Subtac. These entries are named Subtac.<foo>
 *)

module Gram = Pcoq.Gram
module Constr = Pcoq.Constr
module Tactic = Pcoq.Tactic

module Subtac =
  struct
    let gec s = Gram.Entry.create ("Subtac."^s)
    (* types *)
    let subtac_spec : type_loc Gram.Entry.e = gec "subtac_spec"
    let subtac_term : term_loc Gram.Entry.e = gec "subtac_term"

    (* Hack to parse "(x:=t)" as an explicit argument without conflicts with the *)
    (* admissible notation "(x t)" 
       taken from g_constrnew.ml4 *)
    let test_lpar_id_coloneq =
      Gram.Entry.of_parser "test_lpar_id_coloneq"
	(fun strm ->
	   Pp.msgnl (Pp.str ("Testing lpar_id_coloneq:" ^ 
			       (snd (List.hd (Stream.npeek 1 strm)))));
	   
	   match Stream.npeek 1 strm with
             | [("","(")] ->
		 (match Stream.npeek 2 strm with
		    | [_; ("IDENT",s)] ->
			(match Stream.npeek 3 strm with
			   | [_; _; ("", ":=")] ->
                               Stream.junk strm; Stream.junk strm; Stream.junk strm;
			       Pp.msgnl (Pp.str "Success");
                               Names.id_of_string s
			   | _ -> raise Stream.Failure)
		    | _ -> raise Stream.Failure)
             | _ -> raise Stream.Failure)

    let test_id_coloneq =
      Gram.Entry.of_parser "test_id_coloneq"
	(fun strm ->
	   Pp.msgnl (Pp.str ("Testing id_coloneq:" ^ 
			       (snd (List.hd (Stream.npeek 1 strm)))));
	   
	   (match Stream.npeek 1 strm with
	      | [("IDENT",s)] ->
		  (match Stream.npeek 2 strm with
		     | [_; ("", ":=")] ->
                         Stream.junk strm; Stream.junk strm;
			 Pp.msgnl (Pp.str "Success");
                         Names.id_of_string s
		     | _ -> raise Stream.Failure)
	      | _ -> raise Stream.Failure))
end 

open Subtac
open Util
open Coqast

if not !Options.v7 then
GEXTEND Gram
  GLOBAL: subtac_spec subtac_term;

  (* Types ******************************************************************)
  subtac_spec: 
    [ 
      "10" LEFTA
	[ t = subtac_spec; t' = subtac_spec -> loc, TApp (t, t') ]
    
    | [ t = subtac_spec_no_app -> t ]
    ];

  subtac_spec_no_app: 
    [ [      
	  "(" ; t = subtac_spec_lpar_open -> t
	| "[" ; x = subtac_binder_opt; "]"; t = subtac_spec -> 
	    loc, TSigma (x, t)
	| "{" ; x = subtac_binder; "|"; p = subtac_spec; "}"; "->"; t = subtac_spec ->
	    let ((locx, i), tx) = x in
	      loc, TPi (((locx, Name i), (loc, TSubset (x, p))), t)
	| "{" ; x = subtac_binder; "|"; p = subtac_spec; "}" ->
	    loc, TSubset(x, p)
	| t = subtac_type_ident; f = subtac_spec_tident -> f t
	]
    ]
  ;
  
  subtac_spec_no_app_loc: 
    [ [ x = subtac_spec_no_app -> (loc, x) ] 
  ];

  subtac_spec_tident:
    [ [
	"->"; t' = subtac_spec -> 
	  fun t -> loc, TPi (((dummy_loc, Anonymous), t), t')
      | -> (fun x -> x)
      ]
    ]
  ;

  subtac_spec_lpar_open:
    [
      [ s = subtac_identifier; t = subtac_spec_lpar_name -> t s 
      | s = subtac_spec; ")" -> s ]
    ]
  ;

  subtac_spec_lpar_name:
    [
      [ ":" ; y = subtac_spec; ")"; t = subtac_spec -> 
	  (fun s -> loc, TPi ((((fst s), Name (snd s)), y), t))
      | l = LIST1 subtac_spec_no_app_loc; ")" -> fun s -> 
	  List.fold_left (fun acc x -> 
			    (join_loc (fst acc) (fst x), TApp (acc, snd x)))
	    (fst s, TIdent s) l
      ]
    ]
  ;

  subtac_binder:
    [ [ s = subtac_identifier; ":"; t = subtac_spec -> let (l,s) = s in
	  ((loc, s), t) 
    | "{"; x = subtac_binder; "|"; p = subtac_spec; "}" -> 
	let ((l, s), t) = x in 
	  ((l, s), (loc, TSubset (x, p)))
      ]
    ]
  ;

  subtac_identifier:
    [ [ s = IDENT -> (loc, id_of_string s) ] ]
  ;

  subtac_real_name:
    [ [ s = IDENT -> (loc, Name (id_of_string s))
      (* | "_" -> loc, Anonymous111 *)
      ] ]
  ;
  
  subtac_name:
    [ [ n = OPT subtac_real_name -> match n with Some n -> n | None -> loc, Anonymous ] ]
  ;
  
  subtac_binder_opt:
    [ [ s = subtac_name; ":"; t = subtac_spec -> (s, t) ] ]
  ;
  
  subtac_type_ident:
    [ [ s = subtac_identifier -> loc, TIdent s ] ]
  ;

  subtac_term:
    [ 
      "20" LEFTA
	[ t = subtac_term; t' = subtac_term -> 
	    let loc = join_loc (fst t) (fst t') in
	      loc, SApp (t, t')
	]
    | "10"
    	[ 
	  i = subtac_identifier -> loc, SIdent i
	| "fun"; bl = LIST1 subtac_binder; "=>"; p = subtac_term ->
	    (List.fold_left 
	       (fun acc (((loc, s), (loc', t)) as b) -> 
		  (join_loc loc (fst acc), SLambda (b, acc))) p bl)
	| "let"; "("; nl = LIST0 subtac_name SEP ","; ")" ; "="; t = subtac_term;
	  "in"; t' = subtac_term ->
	    loc, (SLetTuple (nl, t, t'))
	| "let"; i = subtac_name; "="; t = subtac_term; "in"; t' = subtac_term ->
	    loc, (SLetIn (i, t, t'))
	| "if"; b = subtac_term; "then"; t = subtac_term; "else"; t' = subtac_term ->
	    loc, SIfThenElse (b, t, t')
	| "("; t = subtac_lpar_term -> t
	]
	
    ]
  ;

  subtac_lpar_term:
    [ [
	x = test_id_coloneq; t = subtac_term; ","; 
	t' = subtac_term; ":"; tt = subtac_spec; ")" ->
	  (loc, (SSumDep (((dummy_loc, x), t), (t', tt))))
      | t = subtac_term; f = subtac_lpar_term_term -> f t
      ]
    ]
  ;

  subtac_lpar_term_term:
    [ [
	","; t' = subtac_term; ")" ->
	  (fun t -> loc, (SSumInf (t, t')))
      | ")" -> (fun x -> x)
      ] ]
  ;

  END
else (* Developped with Coq 8.0 *) ()

type type_loc_argtype = (type_loc, constr_expr, Tacexpr.raw_tactic_expr) Genarg.abstract_argument_type
type term_loc_argtype = (term_loc, constr_expr, Tacexpr.raw_tactic_expr) Genarg.abstract_argument_type

let (wit_subtac_spec : type_loc_argtype),
  (globwit_subtac_spec : type_loc_argtype),
  (rawwit_subtac_spec  : type_loc_argtype) =
  Genarg.create_arg "subtac_spec"

let (wit_subtac_term : term_loc_argtype),
  (globwit_subtac_term : term_loc_argtype),
  (rawwit_subtac_term  : term_loc_argtype) =
  Genarg.create_arg "subtac_term"


VERNAC COMMAND EXTEND SubtacRec
    [ "Recursive" "program" ident(id) "(" ident(recid) ":" subtac_spec(rect) ")" ":" subtac_spec(s) ":=" subtac_term(t) ] -> 
      [ Rewrite.subtac (Some (recid, rect)) id (s, t) ]
END

VERNAC COMMAND EXTEND Subtac
  [ "Program" ident(id) ":" subtac_spec(s) ":=" subtac_term(t) ] -> 
    [ Rewrite.subtac None id (s, t) ]
END