coccinelle release 0.2.5
[bpt/coccinelle.git] / parsing_cocci / ast0toast.ml
1 (*
2 * Copyright 2010, INRIA, University of Copenhagen
3 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
4 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
5 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
6 * This file is part of Coccinelle.
7 *
8 * Coccinelle is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, according to version 2 of the License.
11 *
12 * Coccinelle is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * The authors reserve the right to distribute this or future versions of
21 * Coccinelle under other licenses.
22 *)
23
24
25 (* Arities matter for the minus slice, but not for the plus slice. *)
26
27 (* + only allowed on code in a nest (in_nest = true). ? only allowed on
28 rule_elems, and on subterms if the context is ? also. *)
29
30 module Ast0 = Ast0_cocci
31 module Ast = Ast_cocci
32 module V0 = Visitor_ast0
33 module VT0 = Visitor_ast0_types
34
35 let unitary = Type_cocci.Unitary
36
37 let ctr = ref 0
38 let get_ctr _ =
39 let c = !ctr in
40 ctr := !ctr + 1;
41 c
42
43 (* --------------------------------------------------------------------- *)
44 (* Move plus tokens from the MINUS and CONTEXT structured nodes to the
45 corresponding leftmost and rightmost mcodes *)
46
47 let inline_mcodes =
48 let bind x y = () in
49 let option_default = () in
50 let mcode _ = () in
51 let do_nothing r k e =
52 k e;
53 let einfo = Ast0.get_info e in
54 match (Ast0.get_mcodekind e) with
55 Ast0.MINUS(replacements) ->
56 (match !replacements with
57 ([],_) -> ()
58 | replacements ->
59 let minus_try = function
60 (true,mc) ->
61 if List.for_all
62 (function
63 Ast0.MINUS(mreplacements) -> true | _ -> false)
64 mc
65 then
66 (List.iter
67 (function
68 Ast0.MINUS(mreplacements) ->
69 mreplacements := replacements
70 | _ -> ())
71 mc;
72 true)
73 else false
74 | _ -> false in
75 if not (minus_try(einfo.Ast0.attachable_start,
76 einfo.Ast0.mcode_start)
77 or
78 minus_try(einfo.Ast0.attachable_end,
79 einfo.Ast0.mcode_end))
80 then
81 failwith "minus tree should not have bad code on both sides")
82 | Ast0.CONTEXT(befaft)
83 | Ast0.MIXED(befaft) ->
84 let concat starter startinfo ender endinfo =
85 let lst =
86 match (starter,ender) with
87 ([],_) -> ender
88 | (_,[]) -> starter
89 | _ ->
90 if startinfo.Ast0.tline_end = endinfo.Ast0.tline_start
91 then (* put them in the same inner list *)
92 let last = List.hd (List.rev starter) in
93 let butlast = List.rev(List.tl(List.rev starter)) in
94 butlast @ (last@(List.hd ender)) :: (List.tl ender)
95 else starter @ ender in
96 (lst,
97 {endinfo with Ast0.tline_start = startinfo.Ast0.tline_start}) in
98 let attach_bef bef beforeinfo befit = function
99 (true,mcl) ->
100 List.iter
101 (function
102 Ast0.MINUS(mreplacements) ->
103 let (mrepl,tokeninfo) = !mreplacements in
104 mreplacements := concat bef beforeinfo mrepl tokeninfo
105 | Ast0.CONTEXT(mbefaft) ->
106 (match !mbefaft with
107 (Ast.BEFORE(mbef,it),mbeforeinfo,a) ->
108 let (newbef,newinfo) =
109 concat bef beforeinfo mbef mbeforeinfo in
110 let it = Ast.lub_count befit it in
111 mbefaft := (Ast.BEFORE(newbef,it),newinfo,a)
112 | (Ast.AFTER(maft,it),_,a) ->
113 let it = Ast.lub_count befit it in
114 mbefaft :=
115 (Ast.BEFOREAFTER(bef,maft,it),beforeinfo,a)
116 | (Ast.BEFOREAFTER(mbef,maft,it),mbeforeinfo,a) ->
117 let (newbef,newinfo) =
118 concat bef beforeinfo mbef mbeforeinfo in
119 let it = Ast.lub_count befit it in
120 mbefaft :=
121 (Ast.BEFOREAFTER(newbef,maft,it),newinfo,a)
122 | (Ast.NOTHING,_,a) ->
123 mbefaft :=
124 (Ast.BEFORE(bef,befit),beforeinfo,a))
125 | _ -> failwith "unexpected annotation")
126 mcl
127 | _ ->
128 Printf.printf "before %s\n" (Dumper.dump bef);
129 failwith
130 "context tree should not have bad code before" in
131 let attach_aft aft afterinfo aftit = function
132 (true,mcl) ->
133 List.iter
134 (function
135 Ast0.MINUS(mreplacements) ->
136 let (mrepl,tokeninfo) = !mreplacements in
137 mreplacements := concat mrepl tokeninfo aft afterinfo
138 | Ast0.CONTEXT(mbefaft) ->
139 (match !mbefaft with
140 (Ast.BEFORE(mbef,it),b,_) ->
141 let it = Ast.lub_count aftit it in
142 mbefaft :=
143 (Ast.BEFOREAFTER(mbef,aft,it),b,afterinfo)
144 | (Ast.AFTER(maft,it),b,mafterinfo) ->
145 let (newaft,newinfo) =
146 concat maft mafterinfo aft afterinfo in
147 let it = Ast.lub_count aftit it in
148 mbefaft := (Ast.AFTER(newaft,it),b,newinfo)
149 | (Ast.BEFOREAFTER(mbef,maft,it),b,mafterinfo) ->
150 let (newaft,newinfo) =
151 concat maft mafterinfo aft afterinfo in
152 let it = Ast.lub_count aftit it in
153 mbefaft :=
154 (Ast.BEFOREAFTER(mbef,newaft,it),b,newinfo)
155 | (Ast.NOTHING,b,_) ->
156 mbefaft := (Ast.AFTER(aft,aftit),b,afterinfo))
157 | _ -> failwith "unexpected annotation")
158 mcl
159 | _ ->
160 failwith
161 "context tree should not have bad code after" in
162 (match !befaft with
163 (Ast.BEFORE(bef,it),beforeinfo,_) ->
164 attach_bef bef beforeinfo it
165 (einfo.Ast0.attachable_start,einfo.Ast0.mcode_start)
166 | (Ast.AFTER(aft,it),_,afterinfo) ->
167 attach_aft aft afterinfo it
168 (einfo.Ast0.attachable_end,einfo.Ast0.mcode_end)
169 | (Ast.BEFOREAFTER(bef,aft,it),beforeinfo,afterinfo) ->
170 attach_bef bef beforeinfo it
171 (einfo.Ast0.attachable_start,einfo.Ast0.mcode_start);
172 attach_aft aft afterinfo it
173 (einfo.Ast0.attachable_end,einfo.Ast0.mcode_end)
174 | (Ast.NOTHING,_,_) -> ())
175 | Ast0.PLUS _ -> () in
176 V0.flat_combiner bind option_default
177 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
178 mcode mcode
179 do_nothing do_nothing do_nothing do_nothing do_nothing do_nothing
180 do_nothing do_nothing do_nothing do_nothing do_nothing do_nothing
181 do_nothing do_nothing do_nothing
182
183 (* --------------------------------------------------------------------- *)
184 (* For function declarations. Can't use the mcode at the root, because that
185 might be mixed when the function contains ()s, where agglomeration of -s is
186 not possible. *)
187
188 let check_allminus =
189 let donothing r k e = k e in
190 let bind x y = x && y in
191 let option_default = true in
192 let mcode (_,_,_,mc,_,_) =
193 match mc with
194 Ast0.MINUS(r) -> let (plusses,_) = !r in plusses = []
195 | _ -> false in
196
197 (* special case for disj *)
198 let ident r k e =
199 match Ast0.unwrap e with
200 Ast0.DisjId(starter,id_list,mids,ender) ->
201 List.for_all r.VT0.combiner_rec_ident id_list
202 | _ -> k e in
203
204 let expression r k e =
205 match Ast0.unwrap e with
206 Ast0.DisjExpr(starter,expr_list,mids,ender) ->
207 List.for_all r.VT0.combiner_rec_expression expr_list
208 | _ -> k e in
209
210 let declaration r k e =
211 match Ast0.unwrap e with
212 Ast0.DisjDecl(starter,decls,mids,ender) ->
213 List.for_all r.VT0.combiner_rec_declaration decls
214 | _ -> k e in
215
216 let typeC r k e =
217 match Ast0.unwrap e with
218 Ast0.DisjType(starter,decls,mids,ender) ->
219 List.for_all r.VT0.combiner_rec_typeC decls
220 | _ -> k e in
221
222 let statement r k e =
223 match Ast0.unwrap e with
224 Ast0.Disj(starter,statement_dots_list,mids,ender) ->
225 List.for_all r.VT0.combiner_rec_statement_dots statement_dots_list
226 | _ -> k e in
227
228 let case_line r k e =
229 match Ast0.unwrap e with
230 Ast0.DisjCase(starter,case_lines,mids,ender) ->
231 List.for_all r.VT0.combiner_rec_case_line case_lines
232 | _ -> k e in
233
234 V0.flat_combiner bind option_default
235 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
236 mcode mcode
237 donothing donothing donothing donothing donothing donothing
238 ident expression typeC donothing donothing declaration
239 statement case_line donothing
240
241 (* --------------------------------------------------------------------- *)
242 (* --------------------------------------------------------------------- *)
243
244 let get_option fn = function
245 None -> None
246 | Some x -> Some (fn x)
247
248 (* --------------------------------------------------------------------- *)
249 (* --------------------------------------------------------------------- *)
250 (* Mcode *)
251
252 let convert_info info =
253 let strings_to_s l =
254 List.map
255 (function (s,info) -> (s,info.Ast0.line_start,info.Ast0.column))
256 l in
257 { Ast.line = info.Ast0.pos_info.Ast0.line_start;
258 Ast.column = info.Ast0.pos_info.Ast0.column;
259 Ast.strbef = strings_to_s info.Ast0.strings_before;
260 Ast.straft = strings_to_s info.Ast0.strings_after;}
261
262 let convert_mcodekind adj = function
263 Ast0.MINUS(replacements) ->
264 let (replacements,_) = !replacements in
265 Ast.MINUS(Ast.NoPos,[],adj,replacements)
266 | Ast0.PLUS count -> Ast.PLUS count
267 | Ast0.CONTEXT(befaft) ->
268 let (befaft,_,_) = !befaft in Ast.CONTEXT(Ast.NoPos,befaft)
269 | Ast0.MIXED(_) -> failwith "not possible for mcode"
270
271 let pos_mcode(term,_,info,mcodekind,pos,adj) =
272 (* avoids a recursion problem *)
273 (term,convert_info info,convert_mcodekind adj mcodekind,Ast.NoMetaPos)
274
275 let mcode (term,_,info,mcodekind,pos,adj) =
276 let pos =
277 match !pos with
278 Ast0.MetaPos(pos,constraints,per) ->
279 Ast.MetaPos(pos_mcode pos,constraints,per,unitary,false)
280 | _ -> Ast.NoMetaPos in
281 (term,convert_info info,convert_mcodekind adj mcodekind,pos)
282
283 (* --------------------------------------------------------------------- *)
284 (* Dots *)
285 let wrap ast line isos =
286 {(Ast.make_term ast) with Ast.node_line = line;
287 Ast.iso_info = isos}
288
289 let rewrap ast0 isos ast =
290 wrap ast ((Ast0.get_info ast0).Ast0.pos_info.Ast0.line_start) isos
291
292 let no_isos = []
293
294 (* no isos on tokens *)
295 let tokenwrap (_,info,_,_) s ast = wrap ast info.Ast.line no_isos
296 let iso_tokenwrap (_,info,_,_) s ast iso = wrap ast info.Ast.line iso
297
298 let dots fn d =
299 rewrap d no_isos
300 (match Ast0.unwrap d with
301 Ast0.DOTS(x) -> Ast.DOTS(List.map fn x)
302 | Ast0.CIRCLES(x) -> Ast.CIRCLES(List.map fn x)
303 | Ast0.STARS(x) -> Ast.STARS(List.map fn x))
304
305 (* commas in dotted lists, here due to polymorphism restrictions *)
306
307 let add_comma is_comma make_comma itemlist =
308 match Ast0.unwrap itemlist with
309 Ast0.DOTS(x) ->
310 (match List.rev x with
311 [] -> itemlist
312 | e::es ->
313 if is_comma e
314 then itemlist
315 else
316 let comma =
317 match Ast0.get_mcodekind e with
318 Ast0.MINUS(_) -> (Ast0.make_minus_mcode ",")
319 | _ -> (Ast0.make_mcode ",") in
320 Ast0.rewrap itemlist
321 (Ast0.DOTS
322 (List.rev (Ast0.rewrap e (make_comma comma) :: (e::es)))))
323 | _ -> failwith "not possible"
324
325 let add_exp_comma =
326 add_comma
327 (function x -> match Ast0.unwrap x with Ast0.EComma _ -> true | _ -> false)
328 (function x -> Ast0.EComma x)
329
330 and add_init_comma =
331 add_comma
332 (function x -> match Ast0.unwrap x with Ast0.IComma _ -> true | _ -> false)
333 (function x -> Ast0.IComma x)
334
335 (* --------------------------------------------------------------------- *)
336 (* Identifier *)
337
338 let rec do_isos l = List.map (function (nm,x) -> (nm,anything x)) l
339
340 and ident i =
341 rewrap i (do_isos (Ast0.get_iso i))
342 (match Ast0.unwrap i with
343 Ast0.Id(name) -> Ast.Id(mcode name)
344 | Ast0.DisjId(_,id_list,_,_) ->
345 Ast.DisjId(List.map ident id_list)
346 | Ast0.MetaId(name,constraints,_) ->
347 Ast.MetaId(mcode name,constraints,unitary,false)
348 | Ast0.MetaFunc(name,constraints,_) ->
349 Ast.MetaFunc(mcode name,constraints,unitary,false)
350 | Ast0.MetaLocalFunc(name,constraints,_) ->
351 Ast.MetaLocalFunc(mcode name,constraints,unitary,false)
352 | Ast0.OptIdent(id) -> Ast.OptIdent(ident id)
353 | Ast0.UniqueIdent(id) -> Ast.UniqueIdent(ident id))
354
355 (* --------------------------------------------------------------------- *)
356 (* Expression *)
357
358 and expression e =
359 let e1 =
360 rewrap e (do_isos (Ast0.get_iso e))
361 (match Ast0.unwrap e with
362 Ast0.Ident(id) -> Ast.Ident(ident id)
363 | Ast0.Constant(const) ->
364 Ast.Constant(mcode const)
365 | Ast0.FunCall(fn,lp,args,rp) ->
366 let fn = expression fn in
367 let lp = mcode lp in
368 let args = dots expression args in
369 let rp = mcode rp in
370 Ast.FunCall(fn,lp,args,rp)
371 | Ast0.Assignment(left,op,right,simple) ->
372 Ast.Assignment(expression left,mcode op,expression right,simple)
373 | Ast0.CondExpr(exp1,why,exp2,colon,exp3) ->
374 let exp1 = expression exp1 in
375 let why = mcode why in
376 let exp2 = get_option expression exp2 in
377 let colon = mcode colon in
378 let exp3 = expression exp3 in
379 Ast.CondExpr(exp1,why,exp2,colon,exp3)
380 | Ast0.Postfix(exp,op) ->
381 Ast.Postfix(expression exp,mcode op)
382 | Ast0.Infix(exp,op) ->
383 Ast.Infix(expression exp,mcode op)
384 | Ast0.Unary(exp,op) ->
385 Ast.Unary(expression exp,mcode op)
386 | Ast0.Binary(left,op,right) ->
387 Ast.Binary(expression left,mcode op,expression right)
388 | Ast0.Nested(left,op,right) ->
389 Ast.Nested(expression left,mcode op,expression right)
390 | Ast0.Paren(lp,exp,rp) ->
391 Ast.Paren(mcode lp,expression exp,mcode rp)
392 | Ast0.ArrayAccess(exp1,lb,exp2,rb) ->
393 Ast.ArrayAccess(expression exp1,mcode lb,expression exp2,mcode rb)
394 | Ast0.RecordAccess(exp,pt,field) ->
395 Ast.RecordAccess(expression exp,mcode pt,ident field)
396 | Ast0.RecordPtAccess(exp,ar,field) ->
397 Ast.RecordPtAccess(expression exp,mcode ar,ident field)
398 | Ast0.Cast(lp,ty,rp,exp) ->
399 Ast.Cast(mcode lp,typeC ty,mcode rp,expression exp)
400 | Ast0.SizeOfExpr(szf,exp) ->
401 Ast.SizeOfExpr(mcode szf,expression exp)
402 | Ast0.SizeOfType(szf,lp,ty,rp) ->
403 Ast.SizeOfType(mcode szf, mcode lp,typeC ty,mcode rp)
404 | Ast0.TypeExp(ty) -> Ast.TypeExp(typeC ty)
405 | Ast0.MetaErr(name,cstrts,_) ->
406 Ast.MetaErr(mcode name,constraints cstrts,unitary,false)
407 | Ast0.MetaExpr(name,cstrts,ty,form,_) ->
408 Ast.MetaExpr(mcode name,constraints cstrts,unitary,ty,form,false)
409 | Ast0.MetaExprList(name,lenname,_) ->
410 Ast.MetaExprList(mcode name,do_lenname lenname,unitary,false)
411 | Ast0.EComma(cm) -> Ast.EComma(mcode cm)
412 | Ast0.DisjExpr(_,exps,_,_) ->
413 Ast.DisjExpr(List.map expression exps)
414 | Ast0.NestExpr(starter,exp_dots,ender,whencode,multi) ->
415 let starter = mcode starter in
416 let whencode = get_option expression whencode in
417 let ender = mcode ender in
418 Ast.NestExpr(starter,dots expression exp_dots,ender,whencode,multi)
419 | Ast0.Edots(dots,whencode) ->
420 let dots = mcode dots in
421 let whencode = get_option expression whencode in
422 Ast.Edots(dots,whencode)
423 | Ast0.Ecircles(dots,whencode) ->
424 let dots = mcode dots in
425 let whencode = get_option expression whencode in
426 Ast.Ecircles(dots,whencode)
427 | Ast0.Estars(dots,whencode) ->
428 let dots = mcode dots in
429 let whencode = get_option expression whencode in
430 Ast.Estars(dots,whencode)
431 | Ast0.OptExp(exp) -> Ast.OptExp(expression exp)
432 | Ast0.UniqueExp(exp) -> Ast.UniqueExp(expression exp)) in
433 if Ast0.get_test_exp e then Ast.set_test_exp e1 else e1
434
435 and expression_dots ed = dots expression ed
436
437 and constraints c =
438 match c with
439 Ast0.NoConstraint -> Ast.NoConstraint
440 | Ast0.NotIdCstrt idctrt -> Ast.NotIdCstrt idctrt
441 | Ast0.NotExpCstrt exps -> Ast.NotExpCstrt (List.map expression exps)
442 | Ast0.SubExpCstrt ids -> Ast.SubExpCstrt ids
443
444 and do_lenname = function
445 Ast0.MetaListLen(nm) -> Ast.MetaListLen(mcode nm,unitary,false)
446 | Ast0.CstListLen n -> Ast.CstListLen n
447 | Ast0.AnyListLen -> Ast.AnyListLen
448
449 (* --------------------------------------------------------------------- *)
450 (* Types *)
451
452 and rewrap_iso t t1 = rewrap t (do_isos (Ast0.get_iso t)) t1
453
454 and typeC t =
455 rewrap t (do_isos (Ast0.get_iso t))
456 (match Ast0.unwrap t with
457 Ast0.ConstVol(cv,ty) ->
458 let rec collect_disjs t =
459 match Ast0.unwrap t with
460 Ast0.DisjType(_,types,_,_) ->
461 if Ast0.get_iso t = []
462 then List.concat (List.map collect_disjs types)
463 else failwith "unexpected iso on a disjtype"
464 | _ -> [t] in
465 let res =
466 List.map
467 (function ty ->
468 Ast.Type
469 (Some (mcode cv),rewrap_iso ty (base_typeC ty)))
470 (collect_disjs ty) in
471 (* one could worry that isos are lost because we flatten the
472 disjunctions. but there should not be isos on the disjunctions
473 themselves. *)
474 (match res with
475 [ty] -> ty
476 | types -> Ast.DisjType(List.map (rewrap t no_isos) types))
477 | Ast0.BaseType(_) | Ast0.Signed(_,_) | Ast0.Pointer(_,_)
478 | Ast0.FunctionPointer(_,_,_,_,_,_,_) | Ast0.FunctionType(_,_,_,_)
479 | Ast0.Array(_,_,_,_) | Ast0.EnumName(_,_) | Ast0.StructUnionName(_,_)
480 | Ast0.StructUnionDef(_,_,_,_) | Ast0.EnumDef(_,_,_,_)
481 | Ast0.TypeName(_) | Ast0.MetaType(_,_) ->
482 Ast.Type(None,rewrap t no_isos (base_typeC t))
483 | Ast0.DisjType(_,types,_,_) -> Ast.DisjType(List.map typeC types)
484 | Ast0.OptType(ty) -> Ast.OptType(typeC ty)
485 | Ast0.UniqueType(ty) -> Ast.UniqueType(typeC ty))
486
487 and base_typeC t =
488 match Ast0.unwrap t with
489 Ast0.BaseType(ty,strings) -> Ast.BaseType(ty,List.map mcode strings)
490 | Ast0.Signed(sgn,ty) ->
491 Ast.SignedT(mcode sgn,
492 get_option (function x -> rewrap_iso x (base_typeC x)) ty)
493 | Ast0.Pointer(ty,star) -> Ast.Pointer(typeC ty,mcode star)
494 | Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
495 Ast.FunctionPointer
496 (typeC ty,mcode lp1,mcode star,mcode rp1,
497 mcode lp2,parameter_list params,mcode rp2)
498 | Ast0.FunctionType(ret,lp,params,rp) ->
499 let allminus = check_allminus.VT0.combiner_rec_typeC t in
500 Ast.FunctionType
501 (allminus,get_option typeC ret,mcode lp,
502 parameter_list params,mcode rp)
503 | Ast0.Array(ty,lb,size,rb) ->
504 Ast.Array(typeC ty,mcode lb,get_option expression size,mcode rb)
505 | Ast0.EnumName(kind,name) ->
506 Ast.EnumName(mcode kind,get_option ident name)
507 | Ast0.EnumDef(ty,lb,ids,rb) ->
508 let ids = add_exp_comma ids in
509 Ast.EnumDef(typeC ty,mcode lb,dots expression ids,mcode rb)
510 | Ast0.StructUnionName(kind,name) ->
511 Ast.StructUnionName(mcode kind,get_option ident name)
512 | Ast0.StructUnionDef(ty,lb,decls,rb) ->
513 Ast.StructUnionDef(typeC ty,mcode lb,
514 dots declaration decls,
515 mcode rb)
516 | Ast0.TypeName(name) -> Ast.TypeName(mcode name)
517 | Ast0.MetaType(name,_) ->
518 Ast.MetaType(mcode name,unitary,false)
519 | _ -> failwith "ast0toast: unexpected type"
520
521 (* --------------------------------------------------------------------- *)
522 (* Variable declaration *)
523 (* Even if the Cocci program specifies a list of declarations, they are
524 split out into multiple declarations of a single variable each. *)
525
526 and declaration d =
527 rewrap d (do_isos (Ast0.get_iso d))
528 (match Ast0.unwrap d with
529 Ast0.MetaDecl(name,_) -> Ast.MetaDecl(mcode name,unitary,false)
530 | Ast0.MetaField(name,_) -> Ast.MetaField(mcode name,unitary,false)
531 | Ast0.MetaFieldList(name,lenname,_) ->
532 Ast.MetaFieldList(mcode name,do_lenname lenname,unitary,false)
533 | Ast0.Init(stg,ty,id,eq,ini,sem) ->
534 let stg = get_option mcode stg in
535 let ty = typeC ty in
536 let id = ident id in
537 let eq = mcode eq in
538 let ini = initialiser ini in
539 let sem = mcode sem in
540 Ast.Init(stg,ty,id,eq,ini,sem)
541 | Ast0.UnInit(stg,ty,id,sem) ->
542 (match Ast0.unwrap ty with
543 Ast0.FunctionType(tyx,lp1,params,rp1) ->
544 let allminus = check_allminus.VT0.combiner_rec_declaration d in
545 Ast.UnInit(get_option mcode stg,
546 rewrap ty (do_isos (Ast0.get_iso ty))
547 (Ast.Type
548 (None,
549 rewrap ty no_isos
550 (Ast.FunctionType
551 (allminus,get_option typeC tyx,mcode lp1,
552 parameter_list params,mcode rp1)))),
553 ident id,mcode sem)
554 | _ -> Ast.UnInit(get_option mcode stg,typeC ty,ident id,mcode sem))
555 | Ast0.MacroDecl(name,lp,args,rp,sem) ->
556 let name = ident name in
557 let lp = mcode lp in
558 let args = dots expression args in
559 let rp = mcode rp in
560 let sem = mcode sem in
561 Ast.MacroDecl(name,lp,args,rp,sem)
562 | Ast0.TyDecl(ty,sem) -> Ast.TyDecl(typeC ty,mcode sem)
563 | Ast0.Typedef(stg,ty,id,sem) ->
564 let id = typeC id in
565 (match Ast.unwrap id with
566 Ast.Type(None,id) -> (* only MetaType or Id *)
567 Ast.Typedef(mcode stg,typeC ty,id,mcode sem)
568 | _ -> failwith "bad typedef")
569 | Ast0.DisjDecl(_,decls,_,_) -> Ast.DisjDecl(List.map declaration decls)
570 | Ast0.Ddots(dots,whencode) ->
571 let dots = mcode dots in
572 let whencode = get_option declaration whencode in
573 Ast.Ddots(dots,whencode)
574 | Ast0.OptDecl(decl) -> Ast.OptDecl(declaration decl)
575 | Ast0.UniqueDecl(decl) -> Ast.UniqueDecl(declaration decl))
576
577 and declaration_dots l = dots declaration l
578
579 (* --------------------------------------------------------------------- *)
580 (* Initialiser *)
581
582 and strip_idots initlist =
583 let isminus mc =
584 match Ast0.get_mcode_mcodekind mc with
585 Ast0.MINUS _ -> true
586 | _ -> false in
587 match Ast0.unwrap initlist with
588 Ast0.DOTS(l) ->
589 let l =
590 match List.rev l with
591 [] | [_] -> l
592 | x::y::xs ->
593 (match (Ast0.unwrap x,Ast0.unwrap y) with
594 (Ast0.IComma _,Ast0.Idots _) ->
595 (* drop comma that was added by add_comma *)
596 List.rev (y::xs)
597 | _ -> l) in
598 let (whencode,init,dotinfo) =
599 let rec loop = function
600 [] -> ([],[],[])
601 | x::rest ->
602 (match Ast0.unwrap x with
603 Ast0.Idots(dots,Some whencode) ->
604 let (restwhen,restinit,dotinfo) = loop rest in
605 (whencode :: restwhen, restinit,
606 (isminus dots)::dotinfo)
607 | Ast0.Idots(dots,None) ->
608 let (restwhen,restinit,dotinfo) = loop rest in
609 (restwhen, restinit, (isminus dots)::dotinfo)
610 | _ ->
611 let (restwhen,restinit,dotinfo) = loop rest in
612 (restwhen,x::restinit,dotinfo)) in
613 loop l in
614 let allminus =
615 if List.for_all (function x -> not x) dotinfo
616 then false (* false if no dots *)
617 else
618 if List.for_all (function x -> x) dotinfo
619 then true
620 else failwith "inconsistent annotations on initialiser list dots" in
621 (whencode, init, allminus)
622 | Ast0.CIRCLES(x) | Ast0.STARS(x) -> failwith "not possible for an initlist"
623
624 and initialiser i =
625 rewrap i no_isos
626 (match Ast0.unwrap i with
627 Ast0.MetaInit(name,_) -> Ast.MetaInit(mcode name,unitary,false)
628 | Ast0.InitExpr(exp) -> Ast.InitExpr(expression exp)
629 | Ast0.InitList(lb,initlist,rb,true) ->
630 let initlist = add_init_comma initlist in
631 Ast.ArInitList(mcode lb,dots initialiser initlist,mcode rb)
632 | Ast0.InitList(lb,initlist,rb,false) ->
633 let initlist = add_init_comma initlist in
634 let (whencode,initlist,allminus) = strip_idots initlist in
635 Ast.StrInitList
636 (allminus,mcode lb,List.map initialiser initlist,mcode rb,
637 List.map initialiser whencode)
638 | Ast0.InitGccExt(designators,eq,ini) ->
639 Ast.InitGccExt(List.map designator designators,mcode eq,
640 initialiser ini)
641 | Ast0.InitGccName(name,eq,ini) ->
642 Ast.InitGccName(ident name,mcode eq,initialiser ini)
643 | Ast0.IComma(comma) -> Ast.IComma(mcode comma)
644 | Ast0.Idots(dots,whencode) ->
645 let dots = mcode dots in
646 let whencode = get_option initialiser whencode in
647 Ast.Idots(dots,whencode)
648 | Ast0.OptIni(ini) -> Ast.OptIni(initialiser ini)
649 | Ast0.UniqueIni(ini) -> Ast.UniqueIni(initialiser ini))
650
651 and designator = function
652 Ast0.DesignatorField(dot,id) -> Ast.DesignatorField(mcode dot,ident id)
653 | Ast0.DesignatorIndex(lb,exp,rb) ->
654 Ast.DesignatorIndex(mcode lb, expression exp, mcode rb)
655 | Ast0.DesignatorRange(lb,min,dots,max,rb) ->
656 Ast.DesignatorRange(mcode lb,expression min,mcode dots,expression max,
657 mcode rb)
658
659 (* --------------------------------------------------------------------- *)
660 (* Parameter *)
661
662 and parameterTypeDef p =
663 rewrap p no_isos
664 (match Ast0.unwrap p with
665 Ast0.VoidParam(ty) -> Ast.VoidParam(typeC ty)
666 | Ast0.Param(ty,id) -> Ast.Param(typeC ty,get_option ident id)
667 | Ast0.MetaParam(name,_) ->
668 Ast.MetaParam(mcode name,unitary,false)
669 | Ast0.MetaParamList(name,lenname,_) ->
670 Ast.MetaParamList(mcode name,do_lenname lenname,unitary,false)
671 | Ast0.PComma(cm) -> Ast.PComma(mcode cm)
672 | Ast0.Pdots(dots) -> Ast.Pdots(mcode dots)
673 | Ast0.Pcircles(dots) -> Ast.Pcircles(mcode dots)
674 | Ast0.OptParam(param) -> Ast.OptParam(parameterTypeDef param)
675 | Ast0.UniqueParam(param) -> Ast.UniqueParam(parameterTypeDef param))
676
677 and parameter_list l = dots parameterTypeDef l
678
679 (* --------------------------------------------------------------------- *)
680 (* Top-level code *)
681
682 and statement s =
683 let rec statement seqible s =
684 let rewrap_stmt ast0 ast =
685 let befaft =
686 match Ast0.get_dots_bef_aft s with
687 Ast0.NoDots -> Ast.NoDots
688 | Ast0.DroppingBetweenDots s ->
689 Ast.DroppingBetweenDots (statement seqible s,get_ctr())
690 | Ast0.AddingBetweenDots s ->
691 Ast.AddingBetweenDots (statement seqible s,get_ctr()) in
692 Ast.set_dots_bef_aft befaft (rewrap ast0 no_isos ast) in
693 let rewrap_rule_elem ast0 ast =
694 rewrap ast0 (do_isos (Ast0.get_iso ast0)) ast in
695 rewrap_stmt s
696 (match Ast0.unwrap s with
697 Ast0.Decl((_,bef),decl) ->
698 Ast.Atomic(rewrap_rule_elem s
699 (Ast.Decl(convert_mcodekind (-1) bef,
700 check_allminus.VT0.combiner_rec_statement s,
701 declaration decl)))
702 | Ast0.Seq(lbrace,body,rbrace) ->
703 let lbrace = mcode lbrace in
704 let body = dots (statement seqible) body in
705 let rbrace = mcode rbrace in
706 Ast.Seq(iso_tokenwrap lbrace s (Ast.SeqStart(lbrace))
707 (do_isos (Ast0.get_iso s)),
708 body,
709 tokenwrap rbrace s (Ast.SeqEnd(rbrace)))
710 | Ast0.ExprStatement(exp,sem) ->
711 Ast.Atomic(rewrap_rule_elem s
712 (Ast.ExprStatement(expression exp,mcode sem)))
713 | Ast0.IfThen(iff,lp,exp,rp,branch,(_,aft)) ->
714 Ast.IfThen
715 (rewrap_rule_elem s
716 (Ast.IfHeader(mcode iff,mcode lp,expression exp,mcode rp)),
717 statement Ast.NotSequencible branch,
718 ([],[],[],convert_mcodekind (-1) aft))
719 | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,(_,aft)) ->
720 let els = mcode els in
721 Ast.IfThenElse
722 (rewrap_rule_elem s
723 (Ast.IfHeader(mcode iff,mcode lp,expression exp,mcode rp)),
724 statement Ast.NotSequencible branch1,
725 tokenwrap els s (Ast.Else(els)),
726 statement Ast.NotSequencible branch2,
727 ([],[],[],convert_mcodekind (-1) aft))
728 | Ast0.While(wh,lp,exp,rp,body,(_,aft)) ->
729 Ast.While(rewrap_rule_elem s
730 (Ast.WhileHeader
731 (mcode wh,mcode lp,expression exp,mcode rp)),
732 statement Ast.NotSequencible body,
733 ([],[],[],convert_mcodekind (-1) aft))
734 | Ast0.Do(d,body,wh,lp,exp,rp,sem) ->
735 let wh = mcode wh in
736 Ast.Do(rewrap_rule_elem s (Ast.DoHeader(mcode d)),
737 statement Ast.NotSequencible body,
738 tokenwrap wh s
739 (Ast.WhileTail(wh,mcode lp,expression exp,mcode rp,
740 mcode sem)))
741 | Ast0.For(fr,lp,exp1,sem1,exp2,sem2,exp3,rp,body,(_,aft)) ->
742 let fr = mcode fr in
743 let lp = mcode lp in
744 let exp1 = get_option expression exp1 in
745 let sem1 = mcode sem1 in
746 let exp2 = get_option expression exp2 in
747 let sem2= mcode sem2 in
748 let exp3 = get_option expression exp3 in
749 let rp = mcode rp in
750 let body = statement Ast.NotSequencible body in
751 Ast.For(rewrap_rule_elem s
752 (Ast.ForHeader(fr,lp,exp1,sem1,exp2,sem2,exp3,rp)),
753 body,([],[],[],convert_mcodekind (-1) aft))
754 | Ast0.Iterator(nm,lp,args,rp,body,(_,aft)) ->
755 Ast.Iterator(rewrap_rule_elem s
756 (Ast.IteratorHeader
757 (ident nm,mcode lp,
758 dots expression args,
759 mcode rp)),
760 statement Ast.NotSequencible body,
761 ([],[],[],convert_mcodekind (-1) aft))
762 | Ast0.Switch(switch,lp,exp,rp,lb,decls,cases,rb) ->
763 let switch = mcode switch in
764 let lp = mcode lp in
765 let exp = expression exp in
766 let rp = mcode rp in
767 let lb = mcode lb in
768 let decls = dots (statement seqible) decls in
769 let cases = List.map case_line (Ast0.undots cases) in
770 let rb = mcode rb in
771 Ast.Switch(rewrap_rule_elem s (Ast.SwitchHeader(switch,lp,exp,rp)),
772 tokenwrap lb s (Ast.SeqStart(lb)),
773 decls,cases,
774 tokenwrap rb s (Ast.SeqEnd(rb)))
775 | Ast0.Break(br,sem) ->
776 Ast.Atomic(rewrap_rule_elem s (Ast.Break(mcode br,mcode sem)))
777 | Ast0.Continue(cont,sem) ->
778 Ast.Atomic(rewrap_rule_elem s (Ast.Continue(mcode cont,mcode sem)))
779 | Ast0.Label(l,dd) ->
780 Ast.Atomic(rewrap_rule_elem s (Ast.Label(ident l,mcode dd)))
781 | Ast0.Goto(goto,l,sem) ->
782 Ast.Atomic
783 (rewrap_rule_elem s (Ast.Goto(mcode goto,ident l,mcode sem)))
784 | Ast0.Return(ret,sem) ->
785 Ast.Atomic(rewrap_rule_elem s (Ast.Return(mcode ret,mcode sem)))
786 | Ast0.ReturnExpr(ret,exp,sem) ->
787 Ast.Atomic
788 (rewrap_rule_elem s
789 (Ast.ReturnExpr(mcode ret,expression exp,mcode sem)))
790 | Ast0.MetaStmt(name,_) ->
791 Ast.Atomic(rewrap_rule_elem s
792 (Ast.MetaStmt(mcode name,unitary,seqible,false)))
793 | Ast0.MetaStmtList(name,_) ->
794 Ast.Atomic(rewrap_rule_elem s
795 (Ast.MetaStmtList(mcode name,unitary,false)))
796 | Ast0.TopExp(exp) ->
797 Ast.Atomic(rewrap_rule_elem s (Ast.TopExp(expression exp)))
798 | Ast0.Exp(exp) ->
799 Ast.Atomic(rewrap_rule_elem s (Ast.Exp(expression exp)))
800 | Ast0.TopInit(init) ->
801 Ast.Atomic(rewrap_rule_elem s (Ast.TopInit(initialiser init)))
802 | Ast0.Ty(ty) ->
803 Ast.Atomic(rewrap_rule_elem s (Ast.Ty(typeC ty)))
804 | Ast0.Disj(_,rule_elem_dots_list,_,_) ->
805 Ast.Disj(List.map (function x -> statement_dots seqible x)
806 rule_elem_dots_list)
807 | Ast0.Nest(starter,rule_elem_dots,ender,whn,multi) ->
808 Ast.Nest
809 (mcode starter,statement_dots Ast.Sequencible rule_elem_dots,
810 mcode ender,
811 List.map
812 (whencode (statement_dots Ast.Sequencible)
813 (statement Ast.NotSequencible))
814 whn,
815 multi,[],[])
816 | Ast0.Dots(d,whn) ->
817 let d = mcode d in
818 let whn =
819 List.map
820 (whencode (statement_dots Ast.Sequencible)
821 (statement Ast.NotSequencible))
822 whn in
823 Ast.Dots(d,whn,[],[])
824 | Ast0.Circles(d,whn) ->
825 let d = mcode d in
826 let whn =
827 List.map
828 (whencode (statement_dots Ast.Sequencible)
829 (statement Ast.NotSequencible))
830 whn in
831 Ast.Circles(d,whn,[],[])
832 | Ast0.Stars(d,whn) ->
833 let d = mcode d in
834 let whn =
835 List.map
836 (whencode (statement_dots Ast.Sequencible)
837 (statement Ast.NotSequencible))
838 whn in
839 Ast.Stars(d,whn,[],[])
840 | Ast0.FunDecl((_,bef),fi,name,lp,params,rp,lbrace,body,rbrace) ->
841 let fi = List.map fninfo fi in
842 let name = ident name in
843 let lp = mcode lp in
844 let params = parameter_list params in
845 let rp = mcode rp in
846 let lbrace = mcode lbrace in
847 let body = dots (statement seqible) body in
848 let rbrace = mcode rbrace in
849 let allminus = check_allminus.VT0.combiner_rec_statement s in
850 Ast.FunDecl(rewrap_rule_elem s
851 (Ast.FunHeader(convert_mcodekind (-1) bef,
852 allminus,fi,name,lp,params,rp)),
853 tokenwrap lbrace s (Ast.SeqStart(lbrace)),
854 body,
855 tokenwrap rbrace s (Ast.SeqEnd(rbrace)))
856 | Ast0.Include(inc,str) ->
857 Ast.Atomic(rewrap_rule_elem s (Ast.Include(mcode inc,mcode str)))
858 | Ast0.Undef(def,id) ->
859 Ast.Atomic(rewrap_rule_elem s (Ast.Undef(mcode def,ident id)))
860 | Ast0.Define(def,id,params,body) ->
861 Ast.Define
862 (rewrap_rule_elem s
863 (Ast.DefineHeader
864 (mcode def,ident id, define_parameters params)),
865 statement_dots Ast.NotSequencible (*not sure*) body)
866 | Ast0.OptStm(stm) -> Ast.OptStm(statement seqible stm)
867 | Ast0.UniqueStm(stm) -> Ast.UniqueStm(statement seqible stm))
868
869 and define_parameters p =
870 rewrap p no_isos
871 (match Ast0.unwrap p with
872 Ast0.NoParams -> Ast.NoParams
873 | Ast0.DParams(lp,params,rp) ->
874 Ast.DParams(mcode lp,
875 dots define_param params,
876 mcode rp))
877
878 and define_param p =
879 rewrap p no_isos
880 (match Ast0.unwrap p with
881 Ast0.DParam(id) -> Ast.DParam(ident id)
882 | Ast0.DPComma(comma) -> Ast.DPComma(mcode comma)
883 | Ast0.DPdots(d) -> Ast.DPdots(mcode d)
884 | Ast0.DPcircles(c) -> Ast.DPcircles(mcode c)
885 | Ast0.OptDParam(dp) -> Ast.OptDParam(define_param dp)
886 | Ast0.UniqueDParam(dp) -> Ast.UniqueDParam(define_param dp))
887
888 and whencode notfn alwaysfn = function
889 Ast0.WhenNot a -> Ast.WhenNot (notfn a)
890 | Ast0.WhenAlways a -> Ast.WhenAlways (alwaysfn a)
891 | Ast0.WhenModifier(x) -> Ast.WhenModifier(x)
892 | x ->
893 let rewrap_rule_elem ast0 ast =
894 rewrap ast0 (do_isos (Ast0.get_iso ast0)) ast in
895 match x with
896 Ast0.WhenNotTrue(e) ->
897 Ast.WhenNotTrue(rewrap_rule_elem e (Ast.Exp(expression e)))
898 | Ast0.WhenNotFalse(e) ->
899 Ast.WhenNotFalse(rewrap_rule_elem e (Ast.Exp(expression e)))
900 | _ -> failwith "not possible"
901
902 and process_list seqible isos = function
903 [] -> []
904 | x::rest ->
905 let first = statement seqible x in
906 let first =
907 if !Flag.track_iso_usage
908 then Ast.set_isos first (isos@(Ast.get_isos first))
909 else first in
910 (match Ast0.unwrap x with
911 Ast0.Dots(_,_) | Ast0.Nest(_) ->
912 first::(process_list (Ast.SequencibleAfterDots []) no_isos rest)
913 | _ ->
914 first::(process_list Ast.Sequencible no_isos rest))
915
916 and statement_dots seqible d =
917 let isos = do_isos (Ast0.get_iso d) in
918 rewrap d no_isos
919 (match Ast0.unwrap d with
920 Ast0.DOTS(x) -> Ast.DOTS(process_list seqible isos x)
921 | Ast0.CIRCLES(x) -> Ast.CIRCLES(process_list seqible isos x)
922 | Ast0.STARS(x) -> Ast.STARS(process_list seqible isos x))
923
924 (* the following is no longer used.
925 the goal was to let one put a statement at the very beginning of a function
926 pattern and have it skip over the declarations in the C code.
927 that feature was removed a long time ago, however, in favor of
928 ... when != S, which also causes whatever comes after it to match the
929 first real statement.
930 the separation of declarations from the rest of the body means that the
931 quantifier of any variable shared between them comes out too high, posing
932 problems when there is ... decl ... stmt, as the quantifier of any shared
933 variable will be around the whole thing, making variables not free enough
934 in the first ..., and thus not implementing the expected shortest path
935 condition. example: f() { ... int A; ... foo(A); }.
936 the quantifier for A should start just before int A, not at the top of the
937 function.
938 and separate_decls seqible d =
939 let rec collect_decls = function
940 [] -> ([],[])
941 | (x::xs) as l ->
942 (match Ast0.unwrap x with
943 Ast0.Decl(_) ->
944 let (decls,other) = collect_decls xs in
945 (x :: decls,other)
946 | Ast0.Dots(_,_) | Ast0.Nest(_,_,_,_,_) ->
947 let (decls,other) = collect_decls xs in
948 (match decls with
949 [] -> ([],x::other)
950 | _ -> (x :: decls,other))
951 | Ast0.Disj(starter,stmt_dots_list,mids,ender) ->
952 let disjs = List.map collect_dot_decls stmt_dots_list in
953 let all_decls = List.for_all (function (_,s) -> s=[]) disjs in
954 if all_decls
955 then
956 let (decls,other) = collect_decls xs in
957 (x :: decls,other)
958 else ([],l)
959 | _ -> ([],l))
960
961 and collect_dot_decls d =
962 match Ast0.unwrap d with
963 Ast0.DOTS(x) -> collect_decls x
964 | Ast0.CIRCLES(x) -> collect_decls x
965 | Ast0.STARS(x) -> collect_decls x in
966
967 let process l d fn =
968 let (decls,other) = collect_decls l in
969 (rewrap d no_isos (fn (List.map (statement seqible) decls)),
970 rewrap d no_isos
971 (fn (process_list seqible (do_isos (Ast0.get_iso d)) other))) in
972 match Ast0.unwrap d with
973 Ast0.DOTS(x) -> process x d (function x -> Ast.DOTS x)
974 | Ast0.CIRCLES(x) -> process x d (function x -> Ast.CIRCLES x)
975 | Ast0.STARS(x) -> process x d (function x -> Ast.STARS x) *) in
976
977 statement Ast.Sequencible s
978
979 and fninfo = function
980 Ast0.FStorage(stg) -> Ast.FStorage(mcode stg)
981 | Ast0.FType(ty) -> Ast.FType(typeC ty)
982 | Ast0.FInline(inline) -> Ast.FInline(mcode inline)
983 | Ast0.FAttr(attr) -> Ast.FAttr(mcode attr)
984
985 and option_to_list = function
986 Some x -> [x]
987 | None -> []
988
989 and case_line c =
990 rewrap c no_isos
991 (match Ast0.unwrap c with
992 Ast0.Default(def,colon,code) ->
993 let def = mcode def in
994 let colon = mcode colon in
995 let code = dots statement code in
996 Ast.CaseLine(rewrap c no_isos (Ast.Default(def,colon)),code)
997 | Ast0.Case(case,exp,colon,code) ->
998 let case = mcode case in
999 let exp = expression exp in
1000 let colon = mcode colon in
1001 let code = dots statement code in
1002 Ast.CaseLine(rewrap c no_isos (Ast.Case(case,exp,colon)),code)
1003 | Ast0.DisjCase(_,case_lines,_,_) ->
1004 failwith "not supported"
1005 (*Ast.CaseLine(Ast.DisjRuleElem(List.map case_line case_lines))*)
1006
1007 | Ast0.OptCase(case) -> Ast.OptCase(case_line case))
1008
1009 and statement_dots l = dots statement l
1010
1011 (* --------------------------------------------------------------------- *)
1012
1013 (* what is possible is only what is at the top level in an iso *)
1014 and anything = function
1015 Ast0.DotsExprTag(d) -> Ast.ExprDotsTag(expression_dots d)
1016 | Ast0.DotsParamTag(d) -> Ast.ParamDotsTag(parameter_list d)
1017 | Ast0.DotsInitTag(d) -> failwith "not possible"
1018 | Ast0.DotsStmtTag(d) -> Ast.StmtDotsTag(statement_dots d)
1019 | Ast0.DotsDeclTag(d) -> Ast.DeclDotsTag(declaration_dots d)
1020 | Ast0.DotsCaseTag(d) -> failwith "not possible"
1021 | Ast0.IdentTag(d) -> Ast.IdentTag(ident d)
1022 | Ast0.ExprTag(d) -> Ast.ExpressionTag(expression d)
1023 | Ast0.ArgExprTag(d) | Ast0.TestExprTag(d) ->
1024 failwith "only in isos, not converted to ast"
1025 | Ast0.TypeCTag(d) -> Ast.FullTypeTag(typeC d)
1026 | Ast0.ParamTag(d) -> Ast.ParamTag(parameterTypeDef d)
1027 | Ast0.InitTag(d) -> Ast.InitTag(initialiser d)
1028 | Ast0.DeclTag(d) -> Ast.DeclarationTag(declaration d)
1029 | Ast0.StmtTag(d) -> Ast.StatementTag(statement d)
1030 | Ast0.CaseLineTag(d) -> Ast.CaseLineTag(case_line d)
1031 | Ast0.TopTag(d) -> Ast.Code(top_level d)
1032 | Ast0.IsoWhenTag(_) -> failwith "not possible"
1033 | Ast0.IsoWhenTTag(_) -> failwith "not possible"
1034 | Ast0.IsoWhenFTag(_) -> failwith "not possible"
1035 | Ast0.MetaPosTag _ -> failwith "not possible"
1036
1037 (* --------------------------------------------------------------------- *)
1038 (* Function declaration *)
1039 (* top level isos are probably lost to tracking *)
1040
1041 and top_level t =
1042 rewrap t no_isos
1043 (match Ast0.unwrap t with
1044 Ast0.FILEINFO(old_file,new_file) ->
1045 Ast.FILEINFO(mcode old_file,mcode new_file)
1046 | Ast0.DECL(stmt) -> Ast.DECL(statement stmt)
1047 | Ast0.CODE(rule_elem_dots) ->
1048 Ast.CODE(statement_dots rule_elem_dots)
1049 | Ast0.ERRORWORDS(exps) -> Ast.ERRORWORDS(List.map expression exps)
1050 | Ast0.OTHER(_) -> failwith "eliminated by top_level")
1051
1052 (* --------------------------------------------------------------------- *)
1053 (* Entry point for minus code *)
1054
1055 (* Inline_mcodes is very important - sends + code attached to the - code
1056 down to the mcodes. The functions above can only be used when there is no
1057 attached + code, eg in + code itself. *)
1058 let ast0toast_toplevel x =
1059 inline_mcodes.VT0.combiner_rec_top_level x;
1060 top_level x
1061
1062 let ast0toast name deps dropped exists x is_exp ruletype =
1063 List.iter inline_mcodes.VT0.combiner_rec_top_level x;
1064 Ast.CocciRule
1065 (name,(deps,dropped,exists),List.map top_level x,is_exp,ruletype)