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