2 * Copyright 2005-2010, 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.
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.
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.
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/>.
18 * The authors reserve the right to distribute this or future versions of
19 * Coccinelle under other licenses.
24 * Copyright 2005-2010, Ecole des Mines de Nantes, University of Copenhagen
25 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
26 * This file is part of Coccinelle.
28 * Coccinelle is free software: you can redistribute it and/or modify
29 * it under the terms of the GNU General Public License as published by
30 * the Free Software Foundation, according to version 2 of the License.
32 * Coccinelle is distributed in the hope that it will be useful,
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 * GNU General Public License for more details.
37 * You should have received a copy of the GNU General Public License
38 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
40 * The authors reserve the right to distribute this or future versions of
41 * Coccinelle under other licenses.
45 (* exports everything, used only by parser_cocci_menhir.mly *)
46 module Ast0
= Ast0_cocci
47 module Ast
= Ast_cocci
49 (* types for metavariable tokens *)
50 type info
= Ast.meta_name
* Ast0.pure
* Data.clt
51 type idinfo
= Ast.meta_name
* Data.iconstraints
* Ast0.pure
* Data.clt
52 type expinfo
= Ast.meta_name
* Data.econstraints
* Ast0.pure
* Data.clt
53 type tyinfo
= Ast.meta_name
* Ast0.typeC list
* Ast0.pure
* Data.clt
54 type list_info
= Ast.meta_name
* Ast.meta_name
option * Ast0.pure
* Data.clt
56 Ast.meta_name
* Data.econstraints
* Ast0.pure
*
57 Type_cocci.typeC list
option * Data.clt
58 type pos_info
= Ast.meta_name
* Data.pconstraints
* Ast.meta_collect
* Data.clt
60 let get_option fn
= function
62 | Some x
-> Some
(fn x
)
64 let make_info line logical_line offset col strbef straft
=
66 {Ast0.line_start
= line
; Ast0.line_end
= line
;
67 Ast0.logical_start
= logical_line
; Ast0.logical_end
= logical_line
;
68 Ast0.column
= col
; Ast0.offset
= offset
; } in
69 { Ast0.pos_info
= new_pos_info;
70 Ast0.attachable_start
= true; Ast0.attachable_end
= true;
71 Ast0.mcode_start
= []; Ast0.mcode_end
= [];
72 Ast0.strings_before
= strbef
; Ast0.strings_after
= straft
; }
74 let clt2info (_
,line
,logical_line
,offset
,col
,strbef
,straft
,pos
) =
75 make_info line logical_line offset col strbef straft
77 let drop_bef (arity
,line
,lline
,offset
,col
,strbef
,straft
,pos
) =
78 (arity
,line
,lline
,offset
,col
,[],straft
,pos
)
80 let drop_aft (arity
,line
,lline
,offset
,col
,strbef
,straft
,pos
) =
81 (arity
,line
,lline
,offset
,col
,strbef
,[],pos
)
83 let drop_pos (arity
,line
,lline
,offset
,col
,strbef
,straft
,pos
) =
84 (arity
,line
,lline
,offset
,col
,strbef
,straft
,Ast0.NoMetaPos
)
86 let clt2mcode str
= function
87 (Data.MINUS
,line
,lline
,offset
,col
,strbef
,straft
,pos
) ->
88 (str
,Ast0.NONE
,make_info line lline offset col strbef straft
,
89 Ast0.MINUS
(ref([],Ast0.default_token_info
)),ref pos
,-1)
90 | (Data.OPTMINUS
,line
,lline
,offset
,col
,strbef
,straft
,pos
) ->
91 (str
,Ast0.OPT
,make_info line lline offset col strbef straft
,
92 Ast0.MINUS
(ref([],Ast0.default_token_info
)),ref pos
,-1)
93 | (Data.UNIQUEMINUS
,line
,lline
,offset
,col
,strbef
,straft
,pos
) ->
94 (str
,Ast0.UNIQUE
,make_info line lline offset col strbef straft
,
95 Ast0.MINUS
(ref([],Ast0.default_token_info
)),ref pos
,-1)
96 | (Data.PLUS
,line
,lline
,offset
,col
,strbef
,straft
,pos
) ->
97 (str
,Ast0.NONE
,make_info line lline offset col strbef straft
,
98 Ast0.PLUS
(Ast.ONE
),ref pos
,-1)
99 | (Data.PLUSPLUS
,line
,lline
,offset
,col
,strbef
,straft
,pos
) ->
100 (str
,Ast0.NONE
,make_info line lline offset col strbef straft
,
101 Ast0.PLUS
(Ast.MANY
),ref pos
,-1)
102 | (Data.CONTEXT
,line
,lline
,offset
,col
,strbef
,straft
,pos
) ->
103 (str
,Ast0.NONE
,make_info line lline offset col strbef straft
,
104 Ast0.CONTEXT
(ref(Ast.NOTHING
,
105 Ast0.default_token_info
,Ast0.default_token_info
)),
107 | (Data.OPT
,line
,lline
,offset
,col
,strbef
,straft
,pos
) ->
108 (str
,Ast0.OPT
,make_info line lline offset col strbef straft
,
109 Ast0.CONTEXT
(ref(Ast.NOTHING
,
110 Ast0.default_token_info
,Ast0.default_token_info
)),
112 | (Data.UNIQUE
,line
,lline
,offset
,col
,strbef
,straft
,pos
) ->
113 (str
,Ast0.UNIQUE
,make_info line lline offset col strbef straft
,
114 Ast0.CONTEXT
(ref(Ast.NOTHING
,
115 Ast0.default_token_info
,Ast0.default_token_info
)),
118 let id2name (name
, clt
) = name
119 let id2clt (name
, clt
) = clt
120 let id2mcode (name
, clt
) = clt2mcode name clt
122 let mkdots str
(dot
,whencode
) =
124 "..." -> Ast0.wrap
(Ast0.Dots
(clt2mcode str dot
, whencode
))
125 | "ooo" -> Ast0.wrap
(Ast0.Circles
(clt2mcode str dot
, whencode
))
126 | "***" -> Ast0.wrap
(Ast0.Stars
(clt2mcode str dot
, whencode
))
127 | _
-> failwith
"cannot happen"
129 let mkedots str
(dot
,whencode
) =
131 "..." -> Ast0.wrap
(Ast0.Edots
(clt2mcode str dot
, whencode
))
132 | "ooo" -> Ast0.wrap
(Ast0.Ecircles
(clt2mcode str dot
, whencode
))
133 | "***" -> Ast0.wrap
(Ast0.Estars
(clt2mcode str dot
, whencode
))
134 | _
-> failwith
"cannot happen"
136 let mkdpdots str dot
=
138 "..." -> Ast0.wrap
(Ast0.DPdots
(clt2mcode str dot
))
139 | "ooo" -> Ast0.wrap
(Ast0.DPcircles
(clt2mcode str dot
))
140 | _
-> failwith
"cannot happen"
142 let mkidots str
(dot
,whencode
) =
144 "..." -> Ast0.wrap
(Ast0.Idots
(clt2mcode str dot
, whencode
))
145 | _
-> failwith
"cannot happen"
147 let mkddots str
(dot
,whencode
) =
148 match (str
,whencode
) with
149 ("...",None
) -> Ast0.wrap
(Ast0.Ddots
(clt2mcode str dot
, None
))
150 | ("...",Some
[w
]) -> Ast0.wrap
(Ast0.Ddots
(clt2mcode str dot
, Some w
))
151 | _
-> failwith
"cannot happen"
153 let mkpdots str dot
=
155 "..." -> Ast0.wrap
(Ast0.Pdots
(clt2mcode str dot
))
156 | "ooo" -> Ast0.wrap
(Ast0.Pcircles
(clt2mcode str dot
))
157 | _
-> failwith
"cannot happen"
159 let arith_op ast_op left op right
=
161 (Ast0.Binary
(left
, clt2mcode (Ast.Arith ast_op
) op
, right
))
163 let logic_op ast_op left op right
=
165 (Ast0.Binary
(left
, clt2mcode (Ast.Logical ast_op
) op
, right
))
168 match cv
with None
-> ty
| Some x
-> Ast0.wrap
(Ast0.ConstVol
(x
,ty
))
172 match Ast0.unwrap x
with Ast0.Circles
(_
) -> true | _
-> false in
174 match Ast0.unwrap x
with Ast0.Stars
(_
) -> true | _
-> false in
175 if List.exists
circle l
176 then Ast0.wrap
(Ast0.CIRCLES
(l
))
178 if List.exists
star l
179 then Ast0.wrap
(Ast0.STARS
(l
))
180 else Ast0.wrap
(Ast0.DOTS
(l
))
182 (* here the offset is that of the first in the sequence of *s, not that of
183 each * individually *)
184 let pointerify ty m
=
188 Ast0.wrap
(Ast0.Pointer
(inner
,clt2mcode "*" cur
)))
191 let ty_pointerify ty m
=
193 (function inner
-> function cur
-> Type_cocci.Pointer
(inner
))
196 (* Left is <=>, Right is =>. Collect <=>s. *)
197 (* The parser should have done this, with precedences. But whatever... *)
198 let iso_adjust first_fn fn first rest
=
199 let rec loop = function
201 | (Common.Left x
)::rest
->
202 (match loop rest
with
203 front
::after
-> (fn x
::front
)::after
204 | _
-> failwith
"not possible")
205 | (Common.Right x
)::rest
->
206 (match loop rest
with
207 front
::after
-> []::(fn x
::front
)::after
208 | _
-> failwith
"not possible") in
210 front
::after
-> (first_fn first
::front
)::after
211 | _
-> failwith
"not possible"
213 let check_meta_tyopt type_irrelevant tok
=
214 let lookup rule name
=
216 let info = Hashtbl.find
Data.all_metadecls rule
in
217 List.find
(function mv
-> Ast.get_meta_name mv
= (rule
,name
)) info
221 (Semantic_cocci.Semantic
222 ("bad rule "^rule^
" or bad variable "^name
)) in
224 Ast.MetaIdDecl
(Ast.NONE
,(rule
,name
)) ->
225 (match lookup rule name
with
226 Ast.MetaIdDecl
(_
,_
) | Ast.MetaFreshIdDecl
(_
,_
) -> ()
229 (Semantic_cocci.Semantic
230 ("incompatible inheritance declaration "^name
)))
231 | Ast.MetaFreshIdDecl
((rule
,name
),seed
) ->
233 (Semantic_cocci.Semantic
234 "can't inherit the freshness of an identifier")
235 | Ast.MetaListlenDecl
((rule
,name
)) ->
236 (match lookup rule name
with
237 Ast.MetaListlenDecl
(_
) -> ()
240 (Semantic_cocci.Semantic
241 ("incompatible inheritance declaration "^name
)))
242 | Ast.MetaTypeDecl
(Ast.NONE
,(rule
,name
)) ->
243 (match lookup rule name
with
244 Ast.MetaTypeDecl
(_
,_
) -> ()
247 (Semantic_cocci.Semantic
248 ("incompatible inheritance declaration "^name
)))
249 | Ast.MetaInitDecl
(Ast.NONE
,(rule
,name
)) ->
250 (match lookup rule name
with
251 Ast.MetaInitDecl
(_
,_
) -> ()
254 (Semantic_cocci.Semantic
255 ("incompatible inheritance declaration "^name
)))
256 | Ast.MetaParamDecl
(Ast.NONE
,(rule
,name
)) ->
257 (match lookup rule name
with
258 Ast.MetaParamDecl
(_
,_
) -> ()
261 (Semantic_cocci.Semantic
262 ("incompatible inheritance declaration "^name
)))
263 | Ast.MetaParamListDecl
(Ast.NONE
,(rule
,name
),len_name
) ->
264 (match lookup rule name
with
265 Ast.MetaParamListDecl
(_
,_
,_
) -> ()
268 (Semantic_cocci.Semantic
269 ("incompatible inheritance declaration "^name
)))
270 | Ast.MetaErrDecl
(Ast.NONE
,(rule
,name
)) ->
271 (match lookup rule name
with
272 Ast.MetaErrDecl
(_
,_
) -> ()
275 (Semantic_cocci.Semantic
276 ("incompatible inheritance declaration "^name
)))
277 | Ast.MetaExpDecl
(Ast.NONE
,(rule
,name
),ty
) ->
278 (match lookup rule name
with
279 Ast.MetaExpDecl
(_
,_
,ty1
) when type_irrelevant
or ty
= ty1
-> ()
282 (Semantic_cocci.Semantic
283 ("incompatible inheritance declaration "^name
)))
284 | Ast.MetaIdExpDecl
(Ast.NONE
,(rule
,name
),ty
) ->
285 (match lookup rule name
with
286 Ast.MetaIdExpDecl
(_
,_
,ty1
) when type_irrelevant
or ty
= ty1
-> ()
289 (Semantic_cocci.Semantic
290 ("incompatible inheritance declaration "^name
)))
291 | Ast.MetaLocalIdExpDecl
(Ast.NONE
,(rule
,name
),ty
) ->
292 (match lookup rule name
with
293 Ast.MetaLocalIdExpDecl
(_
,_
,ty1
) when type_irrelevant
or ty
= ty1
-> ()
296 (Semantic_cocci.Semantic
297 ("incompatible inheritance declaration "^name
)))
298 | Ast.MetaExpListDecl
(Ast.NONE
,(rule
,name
),len_name
) ->
299 (match lookup rule name
with
300 Ast.MetaExpListDecl
(_
,_
,_
) -> ()
301 | Ast.MetaParamListDecl
(_
,_
,_
) when not
(!Flag.make_hrule
= None
) -> ()
304 (Semantic_cocci.Semantic
305 ("incompatible inheritance declaration "^name
)))
306 | Ast.MetaStmDecl
(Ast.NONE
,(rule
,name
)) ->
307 (match lookup rule name
with
308 Ast.MetaStmDecl
(_
,_
) -> ()
311 (Semantic_cocci.Semantic
312 ("incompatible inheritance declaration "^name
)))
313 | Ast.MetaStmListDecl
(Ast.NONE
,(rule
,name
)) ->
314 (match lookup rule name
with
315 Ast.MetaStmListDecl
(_
,_
) -> ()
318 (Semantic_cocci.Semantic
319 ("incompatible inheritance declaration "^name
)))
320 | Ast.MetaFuncDecl
(Ast.NONE
,(rule
,name
)) ->
321 (match lookup rule name
with
322 Ast.MetaFuncDecl
(_
,_
) -> ()
325 (Semantic_cocci.Semantic
326 ("incompatible inheritance declaration "^name
)))
327 | Ast.MetaLocalFuncDecl
(Ast.NONE
,(rule
,name
)) ->
328 (match lookup rule name
with
329 Ast.MetaLocalFuncDecl
(_
,_
) -> ()
332 (Semantic_cocci.Semantic
333 ("incompatible inheritance declaration "^name
)))
334 | Ast.MetaConstDecl
(Ast.NONE
,(rule
,name
),ty
) ->
335 (match lookup rule name
with
336 Ast.MetaConstDecl
(_
,_
,ty1
) when type_irrelevant
or ty
= ty1
-> ()
339 (Semantic_cocci.Semantic
340 ("incompatible inheritance declaration "^name
)))
341 | Ast.MetaPosDecl
(Ast.NONE
,(rule
,name
)) ->
342 (match lookup rule name
with
343 Ast.MetaPosDecl
(_
,_
) ->
344 if not
(List.mem rule
!Data.inheritable_positions
)
347 (Semantic_cocci.Semantic
348 ("position cannot be inherited over modifications: "^name
))
351 (Semantic_cocci.Semantic
352 ("incompatible inheritance declaration "^name
)))
355 (Semantic_cocci.Semantic
("arity not allowed on imported declaration"))
357 let check_meta m
= check_meta_tyopt false m
359 let check_inherited_constraint meta_name fn
=
361 (None
,_
) -> failwith
"constraint must be an inherited variable"
362 | (Some rule
,name
) ->
363 let i = (rule
,name
) in
364 check_meta_tyopt true (fn
i);
367 let create_metadec ar ispure kindfn ids current_rule
=
370 (function (rule
,nm
) ->
373 None
-> ((current_rule
,nm
),function x
-> [Common.Left x
])
376 function x
-> check_meta x
; [Common.Right x
]) in
377 kindfn ar rule ispure checker
)
381 let create_metadec_virt ar ispure kindfn ids current_rule
=
385 let checker = function x
-> [Common.Right x
] in
386 kindfn ar nm ispure
checker !Flag.defined_virtual_env
)
389 let create_fresh_metadec kindfn ids current_rule
=
392 (function ((rule
,nm
),seed
) ->
395 None
-> ((current_rule
,nm
),function x
-> [Common.Left x
])
398 function x
-> check_meta x
; [Common.Right x
]) in
399 kindfn rule
checker seed
)
402 let create_metadec_with_constraints ar ispure kindfn ids current_rule
=
405 (function ((rule
,nm
),constraints
) ->
408 None
-> ((current_rule
,nm
),function x
-> [Common.Left x
])
411 function x
-> check_meta x
; [Common.Right x
]) in
412 kindfn ar rule ispure
checker constraints
)
415 let create_metadec_ty ar ispure kindfn ids current_rule
=
418 (function ((rule
,nm
),constraints
) ->
421 None
-> ((current_rule
,nm
),function x
-> [Common.Left x
])
424 function x
-> check_meta x
; [Common.Right x
]) in
425 kindfn ar rule ispure
checker constraints
)
428 let create_len_metadec ar ispure kindfn lenid ids current_rule
=
430 create_metadec Ast.NONE
Ast0.Impure
431 (fun _ name _
check_meta -> check_meta(Ast.MetaListlenDecl
(name
)))
432 [lenid
] current_rule
in
435 [Common.Left
(Ast.MetaListlenDecl
(x
))] -> x
436 | [Common.Right
(Ast.MetaListlenDecl
(x
))] -> x
437 | _
-> failwith
"unexpected length declaration" in
438 lendec@(create_metadec ar ispure
(kindfn
lenname) ids current_rule
)
440 (* ---------------------------------------------------------------------- *)
443 let elements = Str.split
(Str.regexp
"/") s
in
444 List.map
(function "..." -> Ast.IncDots
| s
-> Ast.IncPath s
) elements
446 (* ---------------------------------------------------------------------- *)
450 let (nm
,pure
,clt
) = name
in
451 Ast0.wrap
(Ast0.MetaStmt
(clt2mcode nm clt
,pure
))
454 Ast0.wrap
(Ast0.ExprStatement
(exp
, clt2mcode ";" pv
))
456 let ifthen iff lp tst rp thn
=
457 Ast0.wrap
(Ast0.IfThen
(clt2mcode "if" iff
,
458 clt2mcode "(" lp
,tst
,clt2mcode ")" rp
,thn
,
459 (Ast0.default_info
(),Ast0.context_befaft
())))
461 let ifthenelse iff lp tst rp thn e els
=
462 Ast0.wrap
(Ast0.IfThenElse
(clt2mcode "if" iff
,
463 clt2mcode "(" lp
,tst
,clt2mcode ")" rp
,thn
,
464 clt2mcode "else" e
,els
,
465 (Ast0.default_info
(),Ast0.context_befaft
())))
467 let forloop fr lp e1 sc1 e2 sc2 e3 rp s
=
468 Ast0.wrap
(Ast0.For
(clt2mcode "for" fr
,clt2mcode "(" lp
,e1
,
469 clt2mcode ";" sc1
,e2
,
470 clt2mcode ";" sc2
,e3
,clt2mcode ")" rp
,s
,
471 (Ast0.default_info
(),Ast0.context_befaft
())))
473 let whileloop w lp e rp s
=
474 Ast0.wrap
(Ast0.While
(clt2mcode "while" w
,clt2mcode "(" lp
,
475 e
,clt2mcode ")" rp
,s
,
476 (Ast0.default_info
(),Ast0.context_befaft
())))
478 let doloop d s w lp e rp pv
=
479 Ast0.wrap
(Ast0.Do
(clt2mcode "do" d
,s
,clt2mcode "while" w
,
480 clt2mcode "(" lp
,e
,clt2mcode ")" rp
,
483 let iterator i lp e rp s
=
484 Ast0.wrap
(Ast0.Iterator
(i,clt2mcode "(" lp
,e
,clt2mcode ")" rp
,s
,
485 (Ast0.default_info
(),Ast0.context_befaft
())))
487 let switch s lp e rp lb d c rb
=
491 Ast0.wrap
(Ast0.Decl
((Ast0.default_info
(),Ast0.context_befaft
()),d)))
493 Ast0.wrap
(Ast0.Switch
(clt2mcode "switch" s
,clt2mcode "(" lp
,e
,
494 clt2mcode ")" rp
,clt2mcode "{" lb
,
495 Ast0.wrap
(Ast0.DOTS
(d)),
496 Ast0.wrap
(Ast0.DOTS
(c
)),clt2mcode "}" rb
))
499 Ast0.wrap
(Ast0.ReturnExpr
(clt2mcode "return" r
,e
,clt2mcode ";" pv
))
502 Ast0.wrap
(Ast0.Return
(clt2mcode "return" r
,clt2mcode ";" pv
))
505 Ast0.wrap
(Ast0.Break
(clt2mcode "break" b
,clt2mcode ";" pv
))
508 Ast0.wrap
(Ast0.Continue
(clt2mcode "continue" c
,clt2mcode ";" pv
))
511 Ast0.wrap
(Ast0.Label
(i,clt2mcode ":" dd
))
514 Ast0.wrap
(Ast0.Goto
(clt2mcode "goto" g
,i,clt2mcode ";" pv
))
517 Ast0.wrap
(Ast0.Seq
(clt2mcode "{" lb
,s
,clt2mcode "}" rb
))
519 (* ---------------------------------------------------------------------- *)
521 let make_iso_rule_name_result n
=
522 (try let _ = Hashtbl.find
Data.all_metadecls n
in
523 raise
(Semantic_cocci.Semantic
("repeated rule name"))
524 with Not_found
-> ());
525 Ast.CocciRulename
(Some n
,Ast.NoDep
,[],[],Ast.Undetermined
,false (*discarded*))
527 let make_cocci_rule_name_result nm
d i a e ee
=
530 let n = id2name nm
in
531 (try let _ = Hashtbl.find
Data.all_metadecls
n in
532 raise
(Semantic_cocci.Semantic
("repeated rule name"))
533 with Not_found
-> ());
534 Ast.CocciRulename
(Some
n,d,i,a
,e
,ee
)
535 | None
-> Ast.CocciRulename
(None
,d,i,a
,e
,ee
)
537 let make_generated_rule_name_result nm
d i a e ee
=
540 let n = id2name nm
in
541 (try let _ = Hashtbl.find
Data.all_metadecls
n in
542 raise
(Semantic_cocci.Semantic
("repeated rule name"))
543 with Not_found
-> ());
544 Ast.GeneratedRulename
(Some
n,d,i,a
,e
,ee
)
545 | None
-> Ast.GeneratedRulename
(None
,d,i,a
,e
,ee
)
547 let make_script_rule_name_result lang deps
=
548 let l = id2name lang
in
549 Ast.ScriptRulename
(l,deps
)
551 let make_initial_script_rule_name_result lang deps
=
552 let l = id2name lang
in
553 Ast.InitialScriptRulename
(l,deps
)
555 let make_final_script_rule_name_result lang deps
=
556 let l = id2name lang
in
557 Ast.FinalScriptRulename
(l,deps
)
559 (* Allows type alone only when it is void and only when there is only one
560 parameter. This avoids ambiguity problems in the parser. *)
561 let verify_parameter_declarations = function
564 (match Ast0.unwrap x
with
565 Ast0.Param
(t
, None
) ->
566 (match Ast0.unwrap t
with
567 Ast0.BaseType
(Ast.VoidType
,_) -> ()
571 "%d: only void can be a parameter without an identifier"
577 match Ast0.unwrap x
with
578 Ast0.Param
(t
, None
) ->
581 "%d: only void alone can be a parameter without an identifier"