aboutsummaryrefslogtreecommitdiffhomepage
path: root/parsing/printer.ml
blob: e7d53dabb94e2181939a67566e86bc672f209082 (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
250
251
252
253
254
255
256
257
258

(* $Id$ *)

open Pp
open Util
open Names
open Term
open Sign
open Global
open Declare
open Coqast

let print_arguments = ref false
let print_casts = ref false
let print_emacs = ref false

let emacs_str s =
  if !print_emacs then s else "" 

let section_path sl s =
  let sl = List.rev sl in
  make_path (List.tl sl) (id_of_string (List.hd sl)) (kind_of_string s)

let with_implicits f x =
  let oimpl = !Termast.print_implicits in
  Termast.print_implicits := true; 
  try
    let r = f x in
    Termast.print_implicits := oimpl;
    r
  with e -> 
    Termast.print_implicits := oimpl; raise e

let pr_global dflt k oper =
  try 
    let id = id_of_global oper in
    if is_existential_oper oper then
      [< 'sTR (string_of_id id) >]
    else 
      let (oper',_) = global_operator (Nametab.sp_of_id k id) id in 
      if oper = oper' then
        [< 'sTR(string_of_id id) >]
      else 
	dflt
  with 
    | Failure _ | Not_found ->
	[< 'sTR"[Error printing " ; dflt ; 'sTR"]" >]
    | _ -> 
	[< 'sTR"Error [Nasty error printing " ; dflt ; 'sTR"]" >]

let dfltpr ast = [< 'sTR"#GENTERM " ; Ast.print_ast ast >]

let globpr k gt = match gt with
  | Nvar(_,s) -> [< 'sTR s >]
  | Node(_,"CONST",(Path(_,sl,s))::_) ->
      if !print_arguments then 
	dfltpr gt
      else 
	pr_global (dfltpr gt) k (Const (section_path sl s))
  | Node(_,"MUTIND",(Path(_,sl,s))::(Num(_,tyi))::_) ->
      if !print_arguments then 
	(dfltpr gt)
      else 
	pr_global (dfltpr gt) k (MutInd(section_path sl s,tyi))
  | Node(_,"MUTCONSTRUCT",(Path(_,sl,s))::(Num(_,tyi))::(Num(_,i))::_) ->
      if !print_arguments then 
	(dfltpr gt)
      else 
	pr_global (dfltpr gt) k (MutConstruct((section_path sl s,tyi),i))
  | gt -> dfltpr gt

let apply_prec = Some (("Term",(9,0,0)),Extend.L)
let apply_tacprec = Some (("Tactic",(9,0,0)),Extend.L)

let rec gencompr k gt =
  let uni = match k with
    | CCI | FW -> "constr"
    | _ -> "<undefined>" 
  in
  let rec gpr gt =
    Esyntax.genprint uni
      (function
         | Node(_,"PPUNI$COMMAND",[Str(_,"CCI");c]) -> gencompr CCI c
         | Node(_,"PPUNI$COMMAND",[c]) -> gencompr CCI c
         | Node(_,"PPUNI$COMMAND",[Str(_,"FW");c]) -> gencompr FW c
         | gt -> globpr k gt)
      apply_prec
      gt
  in 
  gpr gt


(* [at_top] means ids of env must be avoided in bound variables *)
let gentermpr_core at_top k env t =
  let uenv = unitize_env env in
  try 
    let ogt = 
      if !print_casts then 
	Termast.bdize at_top uenv t
      else 
	Termast.bdize_no_casts at_top uenv t
    in 
    gencompr k ogt
  with Failure _ | Anomaly _ | UserError _ | Not_found ->
    [< 'sTR"<PP error: non-printable term>" >]

let term0_at_top a = gentermpr_core true CCI a
let gentermpr a = gentermpr_core false a

let term0 a = gentermpr CCI a
let prterm = term0 (gLOB nil_sign)
let fterm0 a = gentermpr FW a
let fprterm = fterm0 (gLOB nil_sign)

let prtype_env env typ =
  if !print_casts then 
    term0 env (mkCast typ.body (mkSort typ.typ))
  else 
    prterm typ.body

let prtype = prtype_env (gLOB nil_sign)

let fprtype_env env typ =
  if !print_casts then 
    fterm0 env (mkCast typ.body (mkSort typ.typ))
  else 
    fterm0 env typ.body

let fprtype = fprtype_env (gLOB nil_sign)

let genpatternpr k t =
  try 
    gencompr k (Termast.ast_of_pattern t)
  with Failure _ | Anomaly _ | UserError _ | Not_found ->
       [< 'sTR"<PP error: non-printable term>" >];;

let prpattern = genpatternpr CCI

let genrawtermpr k env t =
  let uenv = unitize_env env in
    try 
      gencompr k (Termast.ast_of_rawconstr uenv t)
    with Failure _ | Anomaly _ | UserError _ | Not_found ->
      [< 'sTR"<PP error: non-printable term>" >];;

let prrawterm = genrawtermpr CCI (gLOB nil_sign)

let gentacpr gt =
  let rec gpr gt =
    Esyntax.genprint "tactic"
      (function 
         | Nvar(_,s) -> [< 'sTR s >]
         | Node(_,"PPUNI$COMMAND",[Str(_,"CCI");c]) -> gencompr CCI c
         | Node(_,"PPUNI$COMMAND",[c]) -> gencompr CCI c
         | Node(_,"PPUNI$COMMAND",[Str(_,"FW");c]) -> gencompr FW c
         | gt -> default_tacpr gt)
      apply_tacprec
      gt
  and default_tacpr = function
    | Node(_,s,[]) -> [< 'sTR s >]
    | Node(_,s,ta) ->
	[< 'sTR s; 'bRK(1,2); hOV 0 (prlist_with_sep pr_spc gpr ta) >]
    | gt -> dfltpr gt
  in 
  gpr gt

let print_decl k sign (s,typ) =
  let ptyp = gentermpr k (gLOB sign) typ.body in
  [< print_id s ; 'sTR" : "; ptyp >]

let print_binding k env (na,typ) =
  let ptyp = gentermpr k env typ.body in
  match na with
    | Anonymous -> [< 'sTR"<>" ; 'sTR" : " ; ptyp >]
    | Name id -> [< print_id id ; 'sTR" : "; ptyp >]


(* Prints out an "env" in a nice format.  We print out the
 * signature,then a horizontal bar, then the debruijn environment.
 * It's printed out from outermost to innermost, so it's readable. *)

let sign_it_with f sign e =
  snd (sign_it (fun id t (sign,e) -> (add_sign (id,t) sign, f id t sign e))
         sign (nil_sign,e))

let sign_it_with_i f sign e =
  let (_,_,e') = 
    (sign_it (fun id t (i,sign,e) -> (i+1,add_sign (id,t) sign,
				      f i id t sign e))
       sign (0,nil_sign,e))
  in 
  e'

let dbenv_it_with f env e =
  snd (dbenv_it (fun na t (env,e) -> (add_rel (na,t) env, f na t env e))
         env (gLOB(get_globals env),e))

(* Prints a signature, all declarations on the same line if possible *)
let pr_sign sign =
  hV 0 [< (sign_it_with (fun id t sign pps ->
                           [<  pps ; 'wS 2 ; print_decl CCI sign (id,t) >])
             sign) [< >] >]

(* Prints an env (variables and de Bruijn). Separator: newline *)
let pr_env k env =
  let sign_env =
    sign_it_with
      (fun id t sign pps ->
         let pidt =  print_decl k sign (id,t) in [<  pps ; 'fNL ; pidt >])
      (get_globals env) [< >] 
  in
  let db_env =
    dbenv_it_with 
      (fun na t env pps ->
         let pnat = print_binding k env (na,t) in [<  pps ; 'fNL ; pnat >])
      env [< >]
  in 
  [< sign_env; db_env >]

let pr_ne_env header k = function
  | ENVIRON (([],[]),[]) -> [< >]
  | env -> let penv = pr_env k env in [< header; penv >]

let pr_env_limit n env =
  let sign = get_globals env in
  let lgsign = sign_length sign in
  if n >= lgsign then 
    pr_env CCI env
  else
    let k = lgsign-n in
    let sign_env =
      sign_it_with_i
        (fun i id t sign pps -> 
           if i < k then 
	     [< pps ;'sTR "." >] 
	   else
             let pidt = print_decl CCI sign (id,t) in
	     [< pps ; 'fNL ;
		'sTR (emacs_str (String.make 1 (Char.chr 253)));
		pidt >])
        (get_globals env) [< >] 
    in
    let db_env =
      dbenv_it_with
        (fun na t env pps ->
           let pnat = print_binding CCI env (na,t) in
	   [< pps ; 'fNL ;
	      'sTR (emacs_str (String.make 1 (Char.chr 253)));
	      pnat >])
        env [< >]
    in 
    [< sign_env; db_env >]

let pr_env_opt env = match Options.print_hyps_limit () with 
  | None -> hV 0 (pr_env CCI env)
  | Some n -> hV 0 (pr_env_limit n env)

let emacs_str s = if !Options.print_emacs then s else ""