Release coccinelle-0.2.5-rc2
[bpt/coccinelle.git] / parsing_cocci / arity.ml
CommitLineData
c491d8ee
C
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
34e49164
C
25(* Arities matter for the minus slice, but not for the plus slice. *)
26
27(* ? only allowed on rule_elems, and on subterms if the context is ? also. *)
28
29module Ast0 = Ast0_cocci
30module Ast = Ast_cocci
31
32(* --------------------------------------------------------------------- *)
33
34let warning s = Printf.printf "warning: %s\n" s
35
36let fail w str =
37 failwith
0708f913
C
38 (Printf.sprintf "cocci line %d: %s"
39 ((Ast0.get_info w).Ast0.pos_info.Ast0.line_start)
34e49164
C
40 str)
41
42let make_opt_unique optfn uniquefn info tgt arity term =
43 let term = Ast0.rewrap info term in
44 if tgt = arity
45 then term
46 else (* tgt must be NONE *)
47 match arity with
48 Ast0.OPT -> Ast0.copywrap info (optfn term)
49 | Ast0.UNIQUE -> Ast0.copywrap info (uniquefn term)
50 | Ast0.NONE -> failwith "tgt must be NONE"
51
52let all_same opt_allowed tgt line arities =
53 let tgt =
54 match tgt with
55 Ast0.NONE ->
56 (match List.hd arities with
57 Ast0.OPT when not opt_allowed ->
58 failwith "opt only allowed for the elements of a statement list"
59 | x -> x)
60 | _ -> tgt in
61 if not(List.for_all (function x -> x = tgt) arities)
62 then warning (Printf.sprintf "incompatible arity found on line %d" line);
63 tgt
64
65let get_option fn = function
66 None -> None
67 | Some x -> Some (fn x)
68
69let anyopt l fn = List.exists (function w -> fn(Ast0.unwrap w)) l
70
71let allopt l fn =
72 let rec loop = function
73 [] -> []
74 | x::xs ->
75 match fn (Ast0.unwrap x) with
76 Some x -> x :: (loop xs)
77 | None -> [] in
78 let res = loop l in
79 if List.length res = List.length l then Some res else None
80
81(* --------------------------------------------------------------------- *)
82(* --------------------------------------------------------------------- *)
83(* Mcode *)
84
708f4980
C
85let mcode2line (_,_,info,_,_,_) = info.Ast0.pos_info.Ast0.line_start
86let mcode2arity (_,arity,_,_,_,_) = arity
34e49164
C
87
88let mcode x = x (* nothing to do ... *)
89
90(* --------------------------------------------------------------------- *)
91(* Dots *)
92
93let dots fn d =
94 Ast0.rewrap d
95 (match Ast0.unwrap d with
96 Ast0.DOTS(x) -> Ast0.DOTS(List.map fn x)
97 | Ast0.CIRCLES(x) -> Ast0.CIRCLES(List.map fn x)
98 | Ast0.STARS(x) -> Ast0.STARS(List.map fn x))
99
100let only_dots l =
101 not
102 (List.exists
103 (function x ->
104 match Ast0.unwrap x with
105 Ast0.Circles(_,_) | Ast0.Stars(_,_) -> true
106 | _ -> false)
107 l)
108
109let only_circles l =
110 not (List.exists
111 (function x ->
112 match Ast0.unwrap x with
113 Ast0.Dots(_,_) | Ast0.Stars(_,_) -> true
114 | _ -> false)
115 l)
116
117let only_stars l =
118 not (List.exists
119 (function x ->
120 match Ast0.unwrap x with
121 Ast0.Dots(_,_) | Ast0.Circles(_,_) -> true
122 | _ -> false)
123 l)
124
125let concat_dots fn d =
126 Ast0.rewrap d
127 (match Ast0.unwrap d with
128 Ast0.DOTS(x) ->
129 let l = List.map fn x in
130 if only_dots l
131 then Ast0.DOTS(l)
132 else fail d "inconsistent dots usage"
133 | Ast0.CIRCLES(x) ->
134 let l = List.map fn x in
135 if only_circles l
136 then Ast0.CIRCLES(l)
137 else fail d "inconsistent dots usage"
138 | Ast0.STARS(x) ->
139 let l = List.map fn x in
140 if only_stars l
141 then Ast0.STARS(l)
142 else fail d "inconsistent dots usage")
143
144let flat_concat_dots fn d =
145 match Ast0.unwrap d with
146 Ast0.DOTS(x) -> List.map fn x
147 | Ast0.CIRCLES(x) -> List.map fn x
148 | Ast0.STARS(x) -> List.map fn x
149
150(* --------------------------------------------------------------------- *)
151(* Identifier *)
152
153let make_id =
154 make_opt_unique
155 (function x -> Ast0.OptIdent x)
156 (function x -> Ast0.UniqueIdent x)
157
158let ident opt_allowed tgt i =
159 match Ast0.unwrap i with
951c7801
C
160 Ast0.Id(name) ->
161 let arity =
162 all_same opt_allowed tgt (mcode2line name)
163 [mcode2arity name] in
164 let name = mcode name in
165 make_id i tgt arity (Ast0.Id(name))
166 | Ast0.MetaId(name,constraints,pure) ->
167 let arity =
168 all_same opt_allowed tgt (mcode2line name)
169 [mcode2arity name] in
170 let name = mcode name in
171 make_id i tgt arity (Ast0.MetaId(name,constraints,pure))
172 | Ast0.MetaFunc(name,constraints,pure) ->
173 let arity =
174 all_same opt_allowed tgt (mcode2line name)
175 [mcode2arity name] in
176 let name = mcode name in
177 make_id i tgt arity (Ast0.MetaFunc(name,constraints,pure))
178 | Ast0.MetaLocalFunc(name,constraints,pure) ->
179 let arity =
180 all_same opt_allowed tgt (mcode2line name)
181 [mcode2arity name] in
182 let name = mcode name in
183 make_id i tgt arity (Ast0.MetaLocalFunc(name,constraints,pure))
184 | Ast0.OptIdent(_) | Ast0.UniqueIdent(_) ->
185 failwith "unexpected code"
34e49164
C
186
187(* --------------------------------------------------------------------- *)
188(* Expression *)
189
190let make_exp =
191 make_opt_unique
192 (function x -> Ast0.OptExp x)
193 (function x -> Ast0.UniqueExp x)
194
195let rec top_expression opt_allowed tgt expr =
196 let exp_same = all_same opt_allowed tgt in
197 match Ast0.unwrap expr with
198 Ast0.Ident(id) ->
199 let new_id = ident opt_allowed tgt id in
200 Ast0.rewrap expr
201 (match Ast0.unwrap new_id with
202 Ast0.OptIdent(id) ->
203 Ast0.OptExp(Ast0.rewrap expr (Ast0.Ident(id)))
204 | Ast0.UniqueIdent(id) ->
205 Ast0.UniqueExp(Ast0.rewrap expr (Ast0.Ident(id)))
206 | _ -> Ast0.Ident(new_id))
207 | Ast0.Constant(const) ->
208 let arity = exp_same (mcode2line const) [mcode2arity const] in
209 let const = mcode const in
210 make_exp expr tgt arity (Ast0.Constant(const))
211 | Ast0.FunCall(fn,lp,args,rp) ->
212 let arity = exp_same (mcode2line lp) [mcode2arity lp;mcode2arity rp] in
213 let fn = expression arity fn in
214 let lp = mcode lp in
215 let args = dots (expression arity) args in
216 let rp = mcode rp in
217 make_exp expr tgt arity (Ast0.FunCall(fn,lp,args,rp))
218 | Ast0.Assignment(left,op,right,simple) ->
219 let arity = exp_same (mcode2line op) [mcode2arity op] in
220 let left = expression arity left in
221 let op = mcode op in
222 let right = expression arity right in
223 make_exp expr tgt arity (Ast0.Assignment(left,op,right,simple))
224 | Ast0.CondExpr(exp1,why,exp2,colon,exp3) ->
225 let arity =
226 exp_same (mcode2line why) [mcode2arity why; mcode2arity colon] in
227 let exp1 = expression arity exp1 in
228 let why = mcode why in
229 let exp2 = get_option (expression arity) exp2 in
230 let colon = mcode colon in
231 let exp3 = expression arity exp3 in
232 make_exp expr tgt arity (Ast0.CondExpr(exp1,why,exp2,colon,exp3))
233 | Ast0.Postfix(exp,op) ->
234 let arity = exp_same (mcode2line op) [mcode2arity op] in
235 let exp = expression arity exp in
236 let op = mcode op in
237 make_exp expr tgt arity (Ast0.Postfix(exp,op))
238 | Ast0.Infix(exp,op) ->
239 let arity = exp_same (mcode2line op) [mcode2arity op] in
240 let exp = expression arity exp in
241 let op = mcode op in
242 make_exp expr tgt arity (Ast0.Infix(exp,op))
243 | Ast0.Unary(exp,op) ->
244 let arity = exp_same (mcode2line op) [mcode2arity op] in
245 let exp = expression arity exp in
246 let op = mcode op in
247 make_exp expr tgt arity (Ast0.Unary(exp,op))
248 | Ast0.Binary(left,op,right) ->
249 let arity = exp_same (mcode2line op) [mcode2arity op] in
250 let left = expression arity left in
251 let op = mcode op in
252 let right = expression arity right in
253 make_exp expr tgt arity (Ast0.Binary(left,op,right))
254 | Ast0.Nested(left,op,right) -> failwith "nested in arity not possible"
255 | Ast0.Paren(lp,exp,rp) ->
256 let arity = exp_same (mcode2line lp) [mcode2arity lp;mcode2arity rp] in
257 let lp = mcode lp in
258 let exp = expression arity exp in
259 let rp = mcode rp in
260 make_exp expr tgt arity (Ast0.Paren(lp,exp,rp))
261 | Ast0.ArrayAccess(exp1,lb,exp2,rb) ->
262 let arity = exp_same (mcode2line lb) [mcode2arity lb; mcode2arity rb] in
263 let exp1 = expression arity exp1 in
264 let lb = mcode lb in
265 let exp2 = expression arity exp2 in
266 let rb = mcode rb in
267 make_exp expr tgt arity (Ast0.ArrayAccess(exp1,lb,exp2,rb))
268 | Ast0.RecordAccess(exp,pt,field) ->
269 let arity = exp_same (mcode2line pt) [mcode2arity pt] in
270 let exp = expression arity exp in
271 let pt = mcode pt in
272 let field = ident false arity field in
273 make_exp expr tgt arity (Ast0.RecordAccess(exp,pt,field))
274 | Ast0.RecordPtAccess(exp,ar,field) ->
275 let arity = exp_same (mcode2line ar) [mcode2arity ar] in
276 let exp = expression arity exp in
277 let ar = mcode ar in
278 let field = ident false arity field in
279 make_exp expr tgt arity (Ast0.RecordPtAccess(exp,ar,field))
280 | Ast0.Cast(lp,ty,rp,exp) ->
281 let arity = exp_same (mcode2line lp) [mcode2arity lp;mcode2arity rp] in
282 let lp = mcode lp in
283 let ty = typeC arity ty in
284 let rp = mcode rp in
285 let exp = expression arity exp in
286 make_exp expr tgt arity (Ast0.Cast(lp,ty,rp,exp))
287 | Ast0.SizeOfExpr(szf,exp) ->
288 let arity = exp_same (mcode2line szf) [mcode2arity szf] in
289 let szf = mcode szf in
290 let exp = expression arity exp in
291 make_exp expr tgt arity (Ast0.SizeOfExpr(szf,exp))
292 | Ast0.SizeOfType(szf,lp,ty,rp) ->
293 let arity =
294 exp_same (mcode2line szf) (List.map mcode2arity [szf;lp;rp]) in
295 let szf = mcode szf in
296 let lp = mcode lp in
297 let ty = typeC arity ty in
298 let rp = mcode rp in
299 make_exp expr tgt arity (Ast0.SizeOfType(szf,lp,ty,rp))
300 | Ast0.TypeExp(ty) -> Ast0.rewrap expr (Ast0.TypeExp(typeC tgt ty))
301 | Ast0.MetaErr(name,constraints,pure) ->
302 let arity = exp_same (mcode2line name) [mcode2arity name] in
303 let name = mcode name in
304 make_exp expr tgt arity (Ast0.MetaErr(name,constraints,pure))
305 | Ast0.MetaExpr(name,constraints,ty,form,pure) ->
306 let arity = exp_same (mcode2line name) [mcode2arity name] in
307 let name = mcode name in
308 make_exp expr tgt arity (Ast0.MetaExpr(name,constraints,ty,form,pure))
309 | Ast0.MetaExprList(name,lenname,pure) ->
310 let arity = exp_same (mcode2line name) [mcode2arity name] in
311 let name = mcode name in
312 make_exp expr tgt arity (Ast0.MetaExprList(name,lenname,pure))
313 | Ast0.EComma(cm) ->
314 let arity = exp_same (mcode2line cm) [mcode2arity cm] in
315 let cm = mcode cm in
316 make_exp expr tgt arity (Ast0.EComma(cm))
317 | Ast0.DisjExpr(starter,exps,mids,ender) ->
318 let exps = List.map (top_expression opt_allowed tgt) exps in
319 (match List.rev exps with
320 _::xs ->
321 if anyopt xs (function Ast0.OptExp(_) -> true | _ -> false)
322 then fail expr "opt only allowed in the last disjunct"
323 | _ -> ());
324 Ast0.rewrap expr (Ast0.DisjExpr(starter,exps,mids,ender))
325 | Ast0.NestExpr(starter,exp_dots,ender,whencode,multi) ->
326 let res =
327 Ast0.NestExpr(starter,
328 dots (top_expression true Ast0.NONE) exp_dots,
329 ender,whencode,multi) in
330 Ast0.rewrap expr res
331 | Ast0.Edots(dots,whencode) ->
332 let arity = exp_same (mcode2line dots) [mcode2arity dots] in
333 let dots = mcode dots in
334 let whencode = get_option (expression Ast0.NONE) whencode in
335 make_exp expr tgt arity (Ast0.Edots(dots,whencode))
336 | Ast0.Ecircles(dots,whencode) ->
337 let arity = exp_same (mcode2line dots) [mcode2arity dots] in
338 let dots = mcode dots in
339 let whencode = get_option (expression Ast0.NONE) whencode in
340 make_exp expr tgt arity (Ast0.Ecircles(dots,whencode))
341 | Ast0.Estars(dots,whencode) ->
342 let arity = exp_same (mcode2line dots) [mcode2arity dots] in
343 let dots = mcode dots in
344 let whencode = get_option (expression Ast0.NONE) whencode in
345 make_exp expr tgt arity (Ast0.Estars(dots,whencode))
fc1ad971 346 (* why does optexp exist???? *)
34e49164
C
347 | Ast0.OptExp(_) | Ast0.UniqueExp(_) ->
348 failwith "unexpected code"
349
350and expression tgt exp = top_expression false tgt exp
351
352(* --------------------------------------------------------------------- *)
353(* Types *)
354
355and make_typeC =
356 make_opt_unique
357 (function x -> Ast0.OptType x)
358 (function x -> Ast0.UniqueType x)
359
360and top_typeC tgt opt_allowed typ =
361 match Ast0.unwrap typ with
362 Ast0.ConstVol(cv,ty) ->
363 let arity = all_same opt_allowed tgt (mcode2line cv)
364 [mcode2arity cv] in
365 let cv = mcode cv in
366 let ty = typeC arity ty in
367 make_typeC typ tgt arity (Ast0.ConstVol(cv,ty))
faf9a90c 368 | Ast0.BaseType(ty,strings) ->
34e49164 369 let arity =
faf9a90c
C
370 all_same opt_allowed tgt (mcode2line (List.hd strings))
371 (List.map mcode2arity strings) in
372 let strings = List.map mcode strings in
373 make_typeC typ tgt arity (Ast0.BaseType(ty,strings))
374 | Ast0.Signed(sign,ty) ->
34e49164
C
375 let arity =
376 all_same opt_allowed tgt (mcode2line sign) [mcode2arity sign] in
377 let sign = mcode sign in
faf9a90c
C
378 let ty = get_option (typeC arity) ty in
379 make_typeC typ tgt arity (Ast0.Signed(sign,ty))
34e49164
C
380 | Ast0.Pointer(ty,star) ->
381 let arity =
382 all_same opt_allowed tgt (mcode2line star) [mcode2arity star] in
383 let ty = typeC arity ty in
384 let star = mcode star in
385 make_typeC typ tgt arity (Ast0.Pointer(ty,star))
386 | Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2) ->
387 let arity =
388 all_same opt_allowed tgt (mcode2line lp1)
389 (List.map mcode2arity [lp1;star;rp1;lp2;rp2]) in
390 let ty = typeC arity ty in
391 let params = parameter_list tgt params in
392 make_typeC typ tgt arity
393 (Ast0.FunctionPointer(ty,lp1,star,rp1,lp2,params,rp2))
394 | Ast0.FunctionType(ty,lp1,params,rp1) ->
395 let arity =
396 all_same opt_allowed tgt (mcode2line lp1)
397 (List.map mcode2arity [lp1;rp1]) in
398 let ty = get_option (typeC arity) ty in
399 let params = parameter_list tgt params in
400 make_typeC typ tgt arity (Ast0.FunctionType(ty,lp1,params,rp1))
401 | Ast0.Array(ty,lb,size,rb) ->
402 let arity =
403 all_same opt_allowed tgt (mcode2line lb)
404 [mcode2arity lb;mcode2arity rb] in
405 let ty = typeC arity ty in
406 let lb = mcode lb in
407 let size = get_option (expression arity) size in
408 let rb = mcode rb in
409 make_typeC typ tgt arity (Ast0.Array(ty,lb,size,rb))
faf9a90c
C
410 | Ast0.EnumName(kind,name) ->
411 let arity =
412 all_same opt_allowed tgt (mcode2line kind) [mcode2arity kind] in
413 let kind = mcode kind in
c491d8ee 414 let name = get_option (ident false arity) name in
faf9a90c 415 make_typeC typ tgt arity (Ast0.EnumName(kind,name))
c491d8ee
C
416 | Ast0.EnumDef(ty,lb,decls,rb) ->
417 let arity =
418 all_same opt_allowed tgt (mcode2line lb)
419 (List.map mcode2arity [lb;rb]) in
420 let ty = typeC arity ty in
421 let lb = mcode lb in
422 let ids = dots (expression tgt) decls in
423 let rb = mcode rb in
424 make_typeC typ tgt arity (Ast0.EnumDef(ty,lb,ids,rb))
34e49164
C
425 | Ast0.StructUnionName(kind,name) ->
426 let arity =
427 all_same opt_allowed tgt (mcode2line kind)
428 [mcode2arity kind] in
429 let kind = mcode kind in
430 let name = get_option (ident false arity) name in
431 make_typeC typ tgt arity (Ast0.StructUnionName(kind,name))
432 | Ast0.StructUnionDef(ty,lb,decls,rb) ->
433 let arity =
434 all_same opt_allowed tgt (mcode2line lb)
435 (List.map mcode2arity [lb;rb]) in
436 let ty = typeC arity ty in
437 let lb = mcode lb in
438 let decls = dots (declaration tgt) decls in
439 let rb = mcode rb in
440 make_typeC typ tgt arity (Ast0.StructUnionDef(ty,lb,decls,rb))
441 | Ast0.TypeName(name) ->
442 let arity =
443 all_same opt_allowed tgt (mcode2line name) [mcode2arity name] in
444 let name = mcode name in
445 make_typeC typ tgt arity (Ast0.TypeName(name))
446 | Ast0.MetaType(name,pure) ->
447 let arity =
448 all_same opt_allowed tgt (mcode2line name) [mcode2arity name] in
449 let name = mcode name in
450 make_typeC typ tgt arity (Ast0.MetaType(name,pure))
451 | Ast0.DisjType(starter,types,mids,ender) ->
452 let types = List.map (typeC tgt) types in
453 (match List.rev types with
454 _::xs ->
455 if anyopt xs (function Ast0.OptType(_) -> true | _ -> false)
456 then fail typ "opt only allowed in the last disjunct"
457 | _ -> ());
458 let res = Ast0.DisjType(starter,types,mids,ender) in
459 Ast0.rewrap typ res
460 | Ast0.OptType(_) | Ast0.UniqueType(_) ->
461 failwith "unexpected code"
462
463and typeC tgt ty = top_typeC tgt false ty
464
465(* --------------------------------------------------------------------- *)
466(* Variable declaration *)
467(* Even if the Cocci program specifies a list of declarations, they are
468 split out into multiple declarations of a single variable each. *)
469
470and make_decl =
471 make_opt_unique
472 (function x -> Ast0.OptDecl x)
473 (function x -> Ast0.UniqueDecl x)
474
475and declaration tgt decl =
476 match Ast0.unwrap decl with
413ffc02
C
477 Ast0.MetaDecl(name,pure) ->
478 let arity = all_same true tgt (mcode2line name) [mcode2arity name] in
479 let name = mcode name in
480 make_decl decl tgt arity (Ast0.MetaDecl(name,pure))
481 | Ast0.MetaField(name,pure) ->
482 let arity = all_same true tgt (mcode2line name) [mcode2arity name] in
483 let name = mcode name in
484 make_decl decl tgt arity (Ast0.MetaField(name,pure))
485 | Ast0.Init(stg,ty,id,eq,exp,sem) ->
34e49164
C
486 let arity =
487 all_same true tgt (mcode2line eq)
488 ((match stg with None -> [] | Some x -> [mcode2arity x]) @
489 (List.map mcode2arity [eq;sem])) in
490 let stg = get_option mcode stg in
491 let ty = typeC arity ty in
492 let id = ident false arity id in
493 let eq = mcode eq in
494 let exp = initialiser arity exp in
495 let sem = mcode sem in
496 make_decl decl tgt arity (Ast0.Init(stg,ty,id,eq,exp,sem))
497 | Ast0.UnInit(stg,ty,id,sem) ->
498 let arity =
499 all_same true tgt (mcode2line sem)
500 ((match stg with None -> [] | Some x -> [mcode2arity x]) @
501 [mcode2arity sem]) in
502 let stg = get_option mcode stg in
503 let ty = typeC arity ty in
504 let id = ident false arity id in
505 let sem = mcode sem in
506 make_decl decl tgt arity (Ast0.UnInit(stg,ty,id,sem))
507 | Ast0.MacroDecl(name,lp,args,rp,sem) ->
508 let arity =
509 all_same true tgt (mcode2line lp) (List.map mcode2arity [lp;rp;sem]) in
510 let name = ident false arity name in
511 let lp = mcode lp in
512 let args = dots (expression arity) args in
513 let rp = mcode rp in
514 let sem = mcode sem in
515 make_decl decl tgt arity (Ast0.MacroDecl(name,lp,args,rp,sem))
516 | Ast0.TyDecl(ty,sem) ->
517 let arity =
518 all_same true tgt (mcode2line sem) [mcode2arity sem] in
519 let ty = typeC arity ty in
520 let sem = mcode sem in
521 make_decl decl tgt arity (Ast0.TyDecl(ty,sem))
522 | Ast0.Typedef(stg,ty,id,sem) ->
523 let arity =
524 all_same true tgt (mcode2line sem)
525 [mcode2arity stg;mcode2arity sem] in
526 let stg = mcode stg in
527 let ty = typeC arity ty in
528 let id = typeC arity id in
529 let sem = mcode sem in
530 make_decl decl tgt arity (Ast0.Typedef(stg,ty,id,sem))
531 | Ast0.DisjDecl(starter,decls,mids,ender) ->
532 let decls = List.map (declaration tgt) decls in
533 (match List.rev decls with
534 _::xs ->
535 if anyopt xs (function Ast0.OptDecl(_) -> true | _ -> false)
536 then fail decl "opt only allowed in the last disjunct"
537 | _ -> ());
538 let res = Ast0.DisjDecl(starter,decls,mids,ender) in
539 Ast0.rewrap decl res
540 | Ast0.Ddots(dots,whencode) ->
541 let arity = all_same true tgt (mcode2line dots) [mcode2arity dots] in
542 let dots = mcode dots in
543 let whencode = get_option (declaration Ast0.NONE) whencode in
544 make_decl decl tgt arity (Ast0.Ddots(dots,whencode))
545 | Ast0.OptDecl(_) | Ast0.UniqueDecl(_) ->
546 failwith "unexpected code"
547
548(* --------------------------------------------------------------------- *)
549(* Initializer *)
550
551and make_init =
552 make_opt_unique
553 (function x -> Ast0.OptIni x)
554 (function x -> Ast0.UniqueIni x)
555
556and initialiser tgt i =
557 let init_same = all_same true tgt in
558 match Ast0.unwrap i with
113803cf
C
559 Ast0.MetaInit(name,pure) ->
560 let arity = init_same (mcode2line name) [mcode2arity name] in
561 let name = mcode name in
562 make_init i tgt arity (Ast0.MetaInit(name,pure))
563 | Ast0.InitExpr(exp) ->
34e49164 564 Ast0.rewrap i (Ast0.InitExpr(expression tgt exp))
c491d8ee 565 | Ast0.InitList(lb,initlist,rb,ordered) ->
34e49164
C
566 let arity = init_same (mcode2line lb) [mcode2arity lb; mcode2arity rb] in
567 let lb = mcode lb in
568 let initlist = dots (initialiser arity) initlist in
569 let rb = mcode rb in
c491d8ee 570 make_init i tgt arity (Ast0.InitList(lb,initlist,rb,ordered))
113803cf
C
571 | Ast0.InitGccExt(designators,eq,ini) ->
572 let arity = init_same (mcode2line eq) [mcode2arity eq] in
573 let designators = List.map (designator arity) designators in
34e49164
C
574 let eq = mcode eq in
575 let ini = initialiser arity ini in
113803cf 576 make_init i tgt arity (Ast0.InitGccExt(designators,eq,ini))
34e49164
C
577 | Ast0.InitGccName(name,eq,ini) ->
578 let arity = init_same (mcode2line eq) [mcode2arity eq] in
579 let name = ident true arity name in
580 let eq = mcode eq in
581 let ini = initialiser arity ini in
582 make_init i tgt arity (Ast0.InitGccName(name,eq,ini))
34e49164
C
583 | Ast0.IComma(cm) ->
584 let arity = init_same (mcode2line cm) [mcode2arity cm] in
585 let cm = mcode cm in
586 make_init i tgt arity (Ast0.IComma(cm))
587 | Ast0.Idots(dots,whencode) ->
588 let arity = init_same (mcode2line dots) [mcode2arity dots] in
589 let dots = mcode dots in
590 let whencode = get_option (initialiser Ast0.NONE) whencode in
591 make_init i tgt arity (Ast0.Idots(dots,whencode))
592 | Ast0.OptIni(_) | Ast0.UniqueIni(_) ->
593 failwith "unexpected code"
594
113803cf
C
595and designator tgt d =
596 let dsame = all_same false tgt in
597 match d with
598 Ast0.DesignatorField(dot,id) ->
599 let arity = dsame (mcode2line dot) [mcode2arity dot] in
600 let dot = mcode dot in
601 let id = ident false arity id in
602 Ast0.DesignatorField(dot,id)
603 | Ast0.DesignatorIndex(lb,exp,rb) ->
604 let arity = dsame (mcode2line lb) [mcode2arity lb;mcode2arity rb] in
605 let lb = mcode lb in
606 let exp = top_expression false arity exp in
607 let rb = mcode rb in
608 Ast0.DesignatorIndex(lb,exp,rb)
609 | Ast0.DesignatorRange(lb,min,dots,max,rb) ->
610 let arity =
611 dsame (mcode2line lb)
612 [mcode2arity lb;mcode2arity dots;mcode2arity rb] in
613 let lb = mcode lb in
614 let min = top_expression false arity min in
615 let dots = mcode dots in
616 let max = top_expression false arity max in
617 let rb = mcode rb in
618 Ast0.DesignatorRange(lb,min,dots,max,rb)
619
34e49164
C
620(* --------------------------------------------------------------------- *)
621(* Parameter *)
622
623and make_param =
624 make_opt_unique
625 (function x -> Ast0.OptParam x)
626 (function x -> Ast0.UniqueParam x)
627
628and parameterTypeDef tgt param =
629 let param_same = all_same true tgt in
630 match Ast0.unwrap param with
631 Ast0.VoidParam(ty) -> Ast0.rewrap param (Ast0.VoidParam(typeC tgt ty))
632 | Ast0.Param(ty,Some id) ->
633 let ty = top_typeC tgt true ty in
634 let id = ident true tgt id in
faf9a90c 635 Ast0.rewrap param
34e49164
C
636 (match (Ast0.unwrap ty,Ast0.unwrap id) with
637 (Ast0.OptType(ty),Ast0.OptIdent(id)) ->
638 Ast0.OptParam(Ast0.rewrap param (Ast0.Param(ty,Some id)))
639 | (Ast0.UniqueType(ty),Ast0.UniqueIdent(id)) ->
640 Ast0.UniqueParam(Ast0.rewrap param (Ast0.Param(ty,Some id)))
641 | (Ast0.OptType(ty),_) ->
642 fail param "arity mismatch in param declaration"
643 | (_,Ast0.OptIdent(id)) ->
644 fail param "arity mismatch in param declaration"
645 | _ -> Ast0.Param(ty,Some id))
646 | Ast0.Param(ty,None) ->
647 let ty = top_typeC tgt true ty in
faf9a90c 648 Ast0.rewrap param
34e49164
C
649 (match Ast0.unwrap ty with
650 Ast0.OptType(ty) ->
651 Ast0.OptParam(Ast0.rewrap param (Ast0.Param(ty,None)))
652 | Ast0.UniqueType(ty) ->
653 Ast0.UniqueParam(Ast0.rewrap param (Ast0.Param(ty,None)))
654 | _ -> Ast0.Param(ty,None))
655 | Ast0.MetaParam(name,pure) ->
656 let arity = param_same (mcode2line name) [mcode2arity name] in
657 let name = mcode name in
658 make_param param tgt arity (Ast0.MetaParam(name,pure))
659 | Ast0.MetaParamList(name,lenname,pure) ->
660 let arity = param_same (mcode2line name) [mcode2arity name] in
661 let name = mcode name in
662 make_param param tgt arity (Ast0.MetaParamList(name,lenname,pure))
663 | Ast0.PComma(cm) ->
664 let arity = param_same (mcode2line cm) [mcode2arity cm] in
665 let cm = mcode cm in
666 make_param param tgt arity (Ast0.PComma(cm))
667 | Ast0.Pdots(dots) ->
668 let arity = param_same (mcode2line dots) [mcode2arity dots] in
669 let dots = mcode dots in
670 make_param param tgt arity (Ast0.Pdots(dots))
671 | Ast0.Pcircles(dots) ->
672 let arity = param_same (mcode2line dots) [mcode2arity dots] in
673 let dots = mcode dots in
674 make_param param tgt arity (Ast0.Pcircles(dots))
675 | Ast0.OptParam(_) | Ast0.UniqueParam(_) ->
676 failwith "unexpected code"
677
678and parameter_list tgt = dots (parameterTypeDef tgt)
679
680(* --------------------------------------------------------------------- *)
681(* Top-level code *)
682
683and make_rule_elem x =
684 make_opt_unique
685 (function x -> Ast0.OptStm x)
686 (function x -> Ast0.UniqueStm x)
687 x
688
689and statement tgt stm =
690 let stm_same = all_same true tgt in
691 match Ast0.unwrap stm with
692 Ast0.Decl(bef,decl) ->
693 let new_decl = declaration tgt decl in
faf9a90c 694 Ast0.rewrap stm
34e49164
C
695 (match Ast0.unwrap new_decl with
696 Ast0.OptDecl(decl) ->
697 Ast0.OptStm(Ast0.rewrap stm (Ast0.Decl(bef,decl)))
698 | Ast0.UniqueDecl(decl) ->
699 Ast0.UniqueStm(Ast0.rewrap stm (Ast0.Decl(bef,decl)))
700 | _ -> Ast0.Decl(bef,new_decl))
faf9a90c 701 | Ast0.Seq(lbrace,body,rbrace) ->
34e49164
C
702 let arity =
703 stm_same (mcode2line lbrace)
704 [mcode2arity lbrace; mcode2arity rbrace] in
705 let lbrace = mcode lbrace in
706 let body = dots (statement arity) body in
707 let rbrace = mcode rbrace in
708 make_rule_elem stm tgt arity (Ast0.Seq(lbrace,body,rbrace))
709 | Ast0.ExprStatement(exp,sem) ->
710 let arity = stm_same (mcode2line sem) [mcode2arity sem] in
711 let exp = expression arity exp in
712 let sem = mcode sem in
713 make_rule_elem stm tgt arity (Ast0.ExprStatement(exp,sem))
714 | Ast0.IfThen(iff,lp,exp,rp,branch,aft) ->
715 let arity =
716 stm_same (mcode2line iff) (List.map mcode2arity [iff;lp;rp]) in
717 let iff = mcode iff in
718 let lp = mcode lp in
719 let exp = expression arity exp in
720 let rp = mcode rp in
721 let branch = statement arity branch in
722 make_rule_elem stm tgt arity (Ast0.IfThen(iff,lp,exp,rp,branch,aft))
723 | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,aft) ->
724 let arity =
725 stm_same (mcode2line iff) (List.map mcode2arity [iff;lp;rp;els]) in
726 let iff = mcode iff in
727 let lp = mcode lp in
728 let exp = expression arity exp in
729 let rp = mcode rp in
730 let branch1 = statement arity branch1 in
731 let els = mcode els in
732 let branch2 = statement arity branch2 in
733 make_rule_elem stm tgt arity
734 (Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,aft))
735 | Ast0.While(wh,lp,exp,rp,body,aft) ->
736 let arity =
737 stm_same (mcode2line wh)
738 (List.map mcode2arity [wh;lp;rp]) in
739 let wh = mcode wh in
740 let lp = mcode lp in
741 let exp = expression arity exp in
742 let rp = mcode rp in
743 let body = statement arity body in
744 make_rule_elem stm tgt arity (Ast0.While(wh,lp,exp,rp,body,aft))
745 | Ast0.Do(d,body,wh,lp,exp,rp,sem) ->
746 let arity =
747 stm_same (mcode2line wh) (List.map mcode2arity [d;wh;lp;rp;sem]) in
748 let d = mcode d in
749 let body = statement arity body in
750 let wh = mcode wh in
751 let lp = mcode lp in
752 let exp = expression arity exp in
753 let rp = mcode rp in
754 let sem = mcode sem in
755 make_rule_elem stm tgt arity (Ast0.Do(d,body,wh,lp,exp,rp,sem))
756 | Ast0.For(fr,lp,exp1,sem1,exp2,sem2,exp3,rp,body,aft) ->
757 let arity =
758 stm_same (mcode2line fr) (List.map mcode2arity [fr;lp;sem1;sem2;rp]) in
759 let fr = mcode fr in
760 let lp = mcode lp in
761 let exp1 = get_option (expression arity) exp1 in
762 let sem1 = mcode sem1 in
763 let exp2 = get_option (expression arity) exp2 in
764 let sem2= mcode sem2 in
765 let exp3 = get_option (expression arity) exp3 in
766 let rp = mcode rp in
767 let body = statement arity body in
768 make_rule_elem stm tgt arity
769 (Ast0.For(fr,lp,exp1,sem1,exp2,sem2,exp3,rp,body,aft))
770 | Ast0.Iterator(nm,lp,args,rp,body,aft) ->
771 let arity = stm_same (mcode2line lp) (List.map mcode2arity [lp;rp]) in
772 let nm = ident false arity nm in
773 let lp = mcode lp in
774 let args = dots (expression arity) args in
775 let rp = mcode rp in
776 let body = statement arity body in
777 make_rule_elem stm tgt arity (Ast0.Iterator(nm,lp,args,rp,body,aft))
fc1ad971 778 | Ast0.Switch(switch,lp,exp,rp,lb,decls,cases,rb) ->
34e49164
C
779 let arity =
780 stm_same (mcode2line switch)
781 (List.map mcode2arity [switch;lp;rp;lb;rb]) in
782 let switch = mcode switch in
783 let lp = mcode lp in
784 let exp = expression arity exp in
785 let rp = mcode rp in
786 let lb = mcode lb in
fc1ad971 787 let decls = dots (statement arity) decls in
34e49164
C
788 let cases = dots (case_line arity) cases in
789 let rb = mcode rb in
790 make_rule_elem stm tgt arity
fc1ad971 791 (Ast0.Switch(switch,lp,exp,rp,lb,decls,cases,rb))
34e49164
C
792 | Ast0.Break(br,sem) ->
793 let arity = stm_same (mcode2line br) (List.map mcode2arity [br;sem]) in
794 let br = mcode br in
795 let sem = mcode sem in
796 make_rule_elem stm tgt arity (Ast0.Break(br,sem))
797 | Ast0.Continue(cont,sem) ->
798 let arity =
799 stm_same (mcode2line cont) (List.map mcode2arity [cont;sem]) in
800 let cont = mcode cont in
801 let sem = mcode sem in
802 make_rule_elem stm tgt arity (Ast0.Continue(cont,sem))
803 | Ast0.Label(l,dd) ->
804 let arity = mcode2arity dd in
805 let l = ident false tgt l in
806 let dd = mcode dd in
807 make_rule_elem stm tgt arity (Ast0.Label(l,dd))
808 | Ast0.Goto(goto,l,sem) ->
809 let arity =
810 stm_same (mcode2line goto) (List.map mcode2arity [goto;sem]) in
811 let goto = mcode goto in
5636bb2c 812 let l = ident false arity l in
34e49164
C
813 let sem = mcode sem in
814 make_rule_elem stm tgt arity (Ast0.Goto(goto,l,sem))
815 | Ast0.Return(ret,sem) ->
816 let arity = stm_same (mcode2line ret) (List.map mcode2arity [ret;sem]) in
817 let ret = mcode ret in
818 let sem = mcode sem in
819 make_rule_elem stm tgt arity (Ast0.Return(ret,sem))
820 | Ast0.ReturnExpr(ret,exp,sem) ->
821 let arity = stm_same (mcode2line ret) (List.map mcode2arity [ret;sem]) in
822 let ret = mcode ret in
823 let exp = expression arity exp in
824 let sem = mcode sem in
825 make_rule_elem stm tgt arity (Ast0.ReturnExpr(ret,exp,sem))
826 | Ast0.MetaStmt(name,pure) ->
827 let arity = stm_same (mcode2line name) [mcode2arity name] in
828 let name = mcode name in
829 make_rule_elem stm tgt arity (Ast0.MetaStmt(name,pure))
830 | Ast0.MetaStmtList(name,pure) ->
831 let arity = stm_same (mcode2line name) [mcode2arity name] in
832 let name = mcode name in
833 make_rule_elem stm tgt arity (Ast0.MetaStmtList(name,pure))
834 | Ast0.Exp(exp) ->
835 let new_exp = top_expression true tgt exp in
faf9a90c 836 Ast0.rewrap stm
34e49164
C
837 (match Ast0.unwrap new_exp with
838 Ast0.OptExp(exp) ->
839 Ast0.OptStm(Ast0.rewrap stm (Ast0.Exp(exp)))
840 | Ast0.UniqueExp(exp) ->
841 Ast0.UniqueStm(Ast0.rewrap stm (Ast0.Exp(exp)))
842 | _ -> Ast0.Exp(new_exp))
843 | Ast0.TopExp(exp) ->
844 let new_exp = top_expression true tgt exp in
faf9a90c 845 Ast0.rewrap stm
34e49164
C
846 (match Ast0.unwrap new_exp with
847 Ast0.OptExp(exp) ->
848 Ast0.OptStm(Ast0.rewrap stm (Ast0.TopExp(exp)))
849 | Ast0.UniqueExp(exp) ->
850 Ast0.UniqueStm(Ast0.rewrap stm (Ast0.TopExp(exp)))
851 | _ -> Ast0.TopExp(new_exp))
852 | Ast0.Ty(ty) ->
853 let new_ty = typeC tgt ty in (* opt makes no sense alone at top level *)
faf9a90c 854 Ast0.rewrap stm
34e49164
C
855 (match Ast0.unwrap new_ty with
856 Ast0.OptType(ty) ->
857 Ast0.OptStm(Ast0.rewrap stm (Ast0.Ty(ty)))
858 | Ast0.UniqueType(ty) ->
859 Ast0.UniqueStm(Ast0.rewrap stm (Ast0.Ty(ty)))
860 | _ -> Ast0.Ty(new_ty))
1be43e12
C
861 | Ast0.TopInit(init) ->
862 let new_init = initialiser tgt init in
863 Ast0.rewrap stm
864 (match Ast0.unwrap new_init with
865 Ast0.OptIni(init) ->
866 Ast0.OptStm(Ast0.rewrap stm (Ast0.TopInit(init)))
867 | Ast0.UniqueIni(init) ->
868 Ast0.UniqueStm(Ast0.rewrap stm (Ast0.TopInit(init)))
869 | _ -> Ast0.TopInit(new_init))
34e49164
C
870 | Ast0.Disj(starter,rule_elem_dots_list,mids,ender) ->
871 let stms =
872 List.map (function x -> concat_dots (statement tgt) x)
873 rule_elem_dots_list in
874 let (found_opt,unopt) =
875 List.fold_left
876 (function (found_opt,lines) ->
877 function x ->
878 let rebuild l =
879 (* previously just checked the last thing in the list,
880 but everything should be optional for the whole thing to
881 be optional *)
882 let is_opt x =
883 match Ast0.unwrap x with
884 Ast0.OptStm(x) -> true
885 | _ -> false in
886 let unopt x =
887 match Ast0.unwrap x with
888 Ast0.OptStm(x) -> x
889 | _ -> x in
890 if List.for_all is_opt l
891 then (true,List.map unopt l)
892 else (false, l) in
893 let (l,k) =
894 match Ast0.unwrap x with
895 Ast0.DOTS(l) ->
896 (l,function l -> Ast0.rewrap x (Ast0.DOTS l))
897 | Ast0.CIRCLES(l) ->
898 (l,function l -> Ast0.rewrap x (Ast0.CIRCLES l))
899 | Ast0.STARS(l) ->
900 (l,function l -> Ast0.rewrap x (Ast0.STARS l)) in
901 let (found_opt,l) = rebuild l in
902 (found_opt,(k l)::lines))
903 (false,[]) stms in
904 let unopt = List.rev unopt in
905 if found_opt
906 then
907 make_rule_elem stm tgt Ast0.OPT (Ast0.Disj(starter,unopt,mids,ender))
908 else Ast0.rewrap stm (Ast0.Disj(starter,stms,mids,ender))
909 | Ast0.Nest(starter,rule_elem_dots,ender,whn,multi) ->
910 let new_rule_elem_dots =
911 concat_dots (statement Ast0.NONE) rule_elem_dots in
912 let whn =
913 List.map
1be43e12
C
914 (whencode (concat_dots (statement Ast0.NONE)) (statement Ast0.NONE)
915 (expression Ast0.NONE))
34e49164
C
916 whn in
917 Ast0.rewrap stm
918 (Ast0.Nest(starter,new_rule_elem_dots,ender,whn,multi))
919 | Ast0.Dots(dots,whn) ->
920 let arity = stm_same (mcode2line dots) [mcode2arity dots] in
921 let dots = mcode dots in
922 let whn =
923 List.map
1be43e12
C
924 (whencode (concat_dots (statement Ast0.NONE)) (statement Ast0.NONE)
925 (expression Ast0.NONE))
34e49164
C
926 whn in
927 make_rule_elem stm tgt arity (Ast0.Dots(dots,whn))
928 | Ast0.Circles(dots,whn) ->
929 let arity = stm_same (mcode2line dots) [mcode2arity dots] in
930 let dots = mcode dots in
931 let whn =
932 List.map
1be43e12
C
933 (whencode (concat_dots (statement Ast0.NONE)) (statement Ast0.NONE)
934 (expression Ast0.NONE))
34e49164
C
935 whn in
936 make_rule_elem stm tgt arity (Ast0.Circles(dots,whn))
937 | Ast0.Stars(dots,whn) ->
938 let arity = stm_same (mcode2line dots) [mcode2arity dots] in
939 let dots = mcode dots in
940 let whn =
941 List.map
1be43e12
C
942 (whencode (concat_dots (statement Ast0.NONE)) (statement Ast0.NONE)
943 (expression Ast0.NONE))
34e49164
C
944 whn in
945 make_rule_elem stm tgt arity (Ast0.Stars(dots,whn))
946 | Ast0.FunDecl(bef,fi,name,lp,params,rp,lbrace,body,rbrace) ->
947 let arity =
948 all_same true tgt (mcode2line lp)
949 ((List.map mcode2arity [lp;rp;lbrace;rbrace]) @ (fninfo2arity fi)) in
950 let fi = List.map (fninfo arity) fi in
951 let name = ident false arity name in
952 let lp = mcode lp in
953 let params = parameter_list arity params in
954 let rp = mcode rp in
955 let lbrace = mcode lbrace in
956 let body = dots (statement arity) body in
957 let rbrace = mcode rbrace in
958 make_rule_elem stm tgt arity
959 (Ast0.FunDecl(bef,fi,name,lp,params,rp,lbrace,body,rbrace))
faf9a90c 960 | Ast0.Include(inc,s) ->
34e49164
C
961 let arity =
962 all_same true tgt (mcode2line inc) [mcode2arity inc; mcode2arity s] in
963 let inc = mcode inc in
964 let s = mcode s in
965 make_rule_elem stm tgt arity (Ast0.Include(inc,s))
3a314143
C
966 | Ast0.Undef(def,id) ->
967 let arity = all_same true tgt (mcode2line def) [mcode2arity def] in
968 let def = mcode def in
969 let id = ident false arity id in
970 make_rule_elem stm tgt arity (Ast0.Undef(def,id))
34e49164
C
971 | Ast0.Define(def,id,params,body) ->
972 let arity = all_same true tgt (mcode2line def) [mcode2arity def] in
973 let def = mcode def in
974 let id = ident false arity id in
975 let params = define_parameters arity params in
976 let body = dots (statement arity) body in
977 make_rule_elem stm tgt arity (Ast0.Define(def,id,params,body))
978 | Ast0.OptStm(_) | Ast0.UniqueStm(_) ->
979 failwith "unexpected code"
980
981and define_parameters tgt params =
982 match Ast0.unwrap params with
983 Ast0.NoParams -> params
984 | Ast0.DParams(lp,params,rp) ->
985 let arity =
986 all_same true tgt (mcode2line lp) [mcode2arity lp;mcode2arity rp] in
987 let lp = mcode lp in
988 let params = dots (define_param arity) params in
989 let rp = mcode rp in
990 Ast0.rewrap params (Ast0.DParams(lp,params,rp))
991
992and make_define_param x =
993 make_opt_unique
994 (function x -> Ast0.OptDParam x)
995 (function x -> Ast0.UniqueDParam x)
996 x
997
998and define_param tgt param =
999 match Ast0.unwrap param with
1000 Ast0.DParam(id) ->
1001 let new_id = ident true tgt id in
1002 Ast0.rewrap param
1003 (match Ast0.unwrap new_id with
1004 Ast0.OptIdent(id) ->
1005 Ast0.OptDParam(Ast0.rewrap param (Ast0.DParam(id)))
1006 | Ast0.UniqueIdent(decl) ->
1007 Ast0.UniqueDParam(Ast0.rewrap param (Ast0.DParam(id)))
1008 | _ -> Ast0.DParam(new_id))
1009 | Ast0.DPComma(cm) ->
1010 let arity =
1011 all_same true tgt (mcode2line cm) [mcode2arity cm] in
1012 let cm = mcode cm in
1013 make_define_param param tgt arity (Ast0.DPComma(cm))
1014 | Ast0.DPdots(dots) ->
1015 let arity =
1016 all_same true tgt (mcode2line dots) [mcode2arity dots] in
1017 let dots = mcode dots in
1018 make_define_param param tgt arity (Ast0.DPdots(dots))
1019 | Ast0.DPcircles(circles) ->
1020 let arity =
1021 all_same true tgt (mcode2line circles) [mcode2arity circles] in
1022 let circles = mcode circles in
1023 make_define_param param tgt arity (Ast0.DPcircles(circles))
1024 | Ast0.OptDParam(dp) | Ast0.UniqueDParam(dp) ->
1025 failwith "unexpected code"
1026
1027and fninfo arity = function
1028 Ast0.FStorage(stg) -> Ast0.FStorage(mcode stg)
1029 | Ast0.FType(ty) -> Ast0.FType(typeC arity ty)
1030 | Ast0.FInline(inline) -> Ast0.FInline(mcode inline)
1031 | Ast0.FAttr(attr) -> Ast0.FAttr(mcode attr)
1032
1033and fninfo2arity fninfo =
1034 List.concat
1035 (List.map
1036 (function
1037 Ast0.FStorage(stg) -> [mcode2arity stg]
1038 | Ast0.FType(ty) -> []
1039 | Ast0.FInline(inline) -> [mcode2arity inline]
1040 | Ast0.FAttr(attr) -> [mcode2arity attr])
1041 fninfo)
1042
1be43e12 1043and whencode notfn alwaysfn expression = function
34e49164
C
1044 Ast0.WhenNot a -> Ast0.WhenNot (notfn a)
1045 | Ast0.WhenAlways a -> Ast0.WhenAlways (alwaysfn a)
1046 | Ast0.WhenModifier(x) -> Ast0.WhenModifier(x)
1be43e12
C
1047 | Ast0.WhenNotTrue a -> Ast0.WhenNotTrue (expression a)
1048 | Ast0.WhenNotFalse a -> Ast0.WhenNotFalse (expression a)
34e49164
C
1049
1050and make_case_line =
1051 make_opt_unique
1052 (function x -> Ast0.OptCase x)
1053 (function x -> failwith "unique not allowed for case_line")
1054
1055and case_line tgt c =
1056 match Ast0.unwrap c with
1057 Ast0.Default(def,colon,code) ->
1058 let arity =
1059 all_same true tgt (mcode2line def)
1060 [mcode2arity def; mcode2arity colon] in
1061 let def = mcode def in
1062 let colon = mcode colon in
1063 let code = dots (statement arity) code in
1064 make_case_line c tgt arity (Ast0.Default(def,colon,code))
1065 | Ast0.Case(case,exp,colon,code) ->
1066 let arity =
1067 all_same true tgt (mcode2line case)
1068 [mcode2arity case; mcode2arity colon] in
1069 let case = mcode case in
1070 let exp = expression arity exp in
1071 let colon = mcode colon in
1072 let code = dots (statement arity) code in
1073 make_case_line c tgt arity (Ast0.Case(case,exp,colon,code))
fc1ad971
C
1074 | Ast0.DisjCase(starter,case_lines,mids,ender) ->
1075 let case_lines = List.map (case_line tgt) case_lines in
1076 (match List.rev case_lines with
1077 _::xs ->
1078 if anyopt xs (function Ast0.OptCase(_) -> true | _ -> false)
1079 then fail c "opt only allowed in the last disjunct"
1080 | _ -> ());
1081 Ast0.rewrap c (Ast0.DisjCase(starter,case_lines,mids,ender))
34e49164
C
1082 | Ast0.OptCase(_) -> failwith "unexpected OptCase"
1083
1084(* --------------------------------------------------------------------- *)
1085(* Function declaration *)
1086(* Haven't thought much about arity here... *)
1087
1088let top_level tgt t =
1089 Ast0.rewrap t
1090 (match Ast0.unwrap t with
faf9a90c 1091 Ast0.FILEINFO(old_file,new_file) ->
34e49164
C
1092 if mcode2arity old_file = Ast0.NONE && mcode2arity new_file = Ast0.NONE
1093 then Ast0.FILEINFO(mcode old_file,mcode new_file)
1094 else fail t "unexpected arity for file info"
1095 | Ast0.DECL(stmt) ->
1096 Ast0.DECL(statement tgt stmt)
1097 | Ast0.CODE(rule_elem_dots) ->
1098 Ast0.CODE(concat_dots (statement tgt) rule_elem_dots)
1099 | Ast0.ERRORWORDS(exps) ->
1100 Ast0.ERRORWORDS(List.map (top_expression false Ast0.NONE) exps)
1101 | Ast0.OTHER(_) -> fail t "eliminated by top_level")
1102
1103let rule tgt = List.map (top_level tgt)
1104
1105(* --------------------------------------------------------------------- *)
1106(* Entry points *)
1107
1108let minus_arity code =
1109 rule Ast0.NONE code