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