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