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.
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.
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.
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/>.
20 * The authors reserve the right to distribute this or future versions of
21 * Coccinelle under other licenses.
25 (* Arities matter for the minus slice, but not for the plus slice. *)
27 (* + only allowed on code in a nest (in_nest = true). ? only allowed on
28 rule_elems, and on subterms if the context is ? also. *)
30 module Ast0
= Ast0_cocci
31 module Ast
= Ast_cocci
32 module V0
= Visitor_ast0
33 module VT0
= Visitor_ast0_types
34 module V
= Visitor_ast
36 let unitary = Type_cocci.Unitary
44 (* --------------------------------------------------------------------- *)
45 (* Move plus tokens from the MINUS and CONTEXT structured nodes to the
46 corresponding leftmost and rightmost mcodes *)
50 let option_default = () in
52 let do_nothing r k e
=
54 let einfo = Ast0.get_info e
in
55 match (Ast0.get_mcodekind e
) with
56 Ast0.MINUS
(replacements
) ->
57 (match !replacements
with
60 let minus_try = function
64 Ast0.MINUS
(mreplacements
) -> true | _
-> false)
69 Ast0.MINUS
(mreplacements
) ->
70 mreplacements
:= replacements
76 if not
(minus_try(einfo.Ast0.attachable_start
,
77 einfo.Ast0.mcode_start
)
79 minus_try(einfo.Ast0.attachable_end
,
80 einfo.Ast0.mcode_end
))
82 failwith
"minus tree should not have bad code on both sides")
83 | Ast0.CONTEXT
(befaft
)
84 | Ast0.MIXED
(befaft
) ->
85 let concat starter startinfo ender endinfo
=
87 match (starter
,ender
) with
91 if startinfo
.Ast0.tline_end
= endinfo
.Ast0.tline_start
92 then (* put them in the same inner list *)
93 let last = List.hd
(List.rev starter
) in
94 let butlast = List.rev
(List.tl
(List.rev starter
)) in
95 butlast @ (last@(List.hd ender
)) :: (List.tl ender
)
96 else starter
@ ender
in
98 {endinfo
with Ast0.tline_start
= startinfo
.Ast0.tline_start
}) in
99 let attach_bef bef beforeinfo befit
= function
103 Ast0.MINUS
(mreplacements
) ->
104 let (mrepl
,tokeninfo
) = !mreplacements
in
105 mreplacements
:= concat bef beforeinfo mrepl tokeninfo
106 | Ast0.CONTEXT
(mbefaft
) ->
108 (Ast.BEFORE
(mbef
,it
),mbeforeinfo
,a
) ->
109 let (newbef
,newinfo
) =
110 concat bef beforeinfo mbef mbeforeinfo
in
111 let it = Ast.lub_count befit
it in
112 mbefaft
:= (Ast.BEFORE
(newbef
,it),newinfo
,a
)
113 | (Ast.AFTER
(maft
,it),_
,a
) ->
114 let it = Ast.lub_count befit
it in
116 (Ast.BEFOREAFTER
(bef
,maft
,it),beforeinfo
,a
)
117 | (Ast.BEFOREAFTER
(mbef
,maft
,it),mbeforeinfo
,a
) ->
118 let (newbef
,newinfo
) =
119 concat bef beforeinfo mbef mbeforeinfo
in
120 let it = Ast.lub_count befit
it in
122 (Ast.BEFOREAFTER
(newbef
,maft
,it),newinfo
,a
)
123 | (Ast.NOTHING
,_
,a
) ->
125 (Ast.BEFORE
(bef
,befit
),beforeinfo
,a
))
126 | _
-> failwith
"unexpected annotation")
129 Printf.printf
"before %s\n" (Dumper.dump bef
);
131 "context tree should not have bad code before" in
132 let attach_aft aft afterinfo aftit
= function
136 Ast0.MINUS
(mreplacements
) ->
137 let (mrepl
,tokeninfo
) = !mreplacements
in
138 mreplacements
:= concat mrepl tokeninfo aft afterinfo
139 | Ast0.CONTEXT
(mbefaft
) ->
141 (Ast.BEFORE
(mbef
,it),b
,_
) ->
142 let it = Ast.lub_count aftit
it in
144 (Ast.BEFOREAFTER
(mbef
,aft
,it),b
,afterinfo
)
145 | (Ast.AFTER
(maft
,it),b
,mafterinfo
) ->
146 let (newaft
,newinfo
) =
147 concat maft mafterinfo aft afterinfo
in
148 let it = Ast.lub_count aftit
it in
149 mbefaft
:= (Ast.AFTER
(newaft
,it),b
,newinfo
)
150 | (Ast.BEFOREAFTER
(mbef
,maft
,it),b
,mafterinfo
) ->
151 let (newaft
,newinfo
) =
152 concat maft mafterinfo aft afterinfo
in
153 let it = Ast.lub_count aftit
it in
155 (Ast.BEFOREAFTER
(mbef
,newaft
,it),b
,newinfo
)
156 | (Ast.NOTHING
,b
,_
) ->
157 mbefaft
:= (Ast.AFTER
(aft
,aftit
),b
,afterinfo
))
158 | _
-> failwith
"unexpected annotation")
162 "context tree should not have bad code after" in
164 (Ast.BEFORE
(bef
,it),beforeinfo
,_
) ->
165 attach_bef bef beforeinfo
it
166 (einfo.Ast0.attachable_start
,einfo.Ast0.mcode_start
)
167 | (Ast.AFTER
(aft
,it),_
,afterinfo
) ->
168 attach_aft aft afterinfo
it
169 (einfo.Ast0.attachable_end
,einfo.Ast0.mcode_end
)
170 | (Ast.BEFOREAFTER
(bef
,aft
,it),beforeinfo
,afterinfo
) ->
171 attach_bef bef beforeinfo
it
172 (einfo.Ast0.attachable_start
,einfo.Ast0.mcode_start
);
173 attach_aft aft afterinfo
it
174 (einfo.Ast0.attachable_end
,einfo.Ast0.mcode_end
)
175 | (Ast.NOTHING
,_
,_
) -> ())
176 | Ast0.PLUS _
-> () in
177 V0.flat_combiner
bind option_default
178 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
180 do_nothing do_nothing do_nothing do_nothing do_nothing do_nothing
181 do_nothing do_nothing do_nothing do_nothing do_nothing do_nothing
182 do_nothing do_nothing do_nothing
184 (* --------------------------------------------------------------------- *)
185 (* For function declarations. Can't use the mcode at the root, because that
186 might be mixed when the function contains ()s, where agglomeration of -s is
190 let donothing r k e
= k e
in
191 let bind x y
= x
&& y
in
192 let option_default = true in
193 let mcode (_
,_
,_
,mc
,_
,_
) =
195 Ast0.MINUS
(r
) -> let (plusses
,_
) = !r
in plusses
= []
198 (* special case for disj *)
199 let expression r k e
=
200 match Ast0.unwrap e
with
201 Ast0.DisjExpr
(starter
,expr_list
,mids
,ender
) ->
202 List.for_all r
.VT0.combiner_rec_expression expr_list
205 let declaration r k e
=
206 match Ast0.unwrap e
with
207 Ast0.DisjDecl
(starter
,decls
,mids
,ender
) ->
208 List.for_all r
.VT0.combiner_rec_declaration decls
212 match Ast0.unwrap e
with
213 Ast0.DisjType
(starter
,decls
,mids
,ender
) ->
214 List.for_all r
.VT0.combiner_rec_typeC decls
217 let statement r k e
=
218 match Ast0.unwrap e
with
219 Ast0.Disj
(starter
,statement_dots_list
,mids
,ender
) ->
220 List.for_all r
.VT0.combiner_rec_statement_dots statement_dots_list
223 let case_line r k e
=
224 match Ast0.unwrap e
with
225 Ast0.DisjCase
(starter
,case_lines
,mids
,ender
) ->
226 List.for_all r
.VT0.combiner_rec_case_line case_lines
229 V0.flat_combiner
bind option_default
230 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
232 donothing donothing donothing donothing donothing donothing
233 donothing expression typeC donothing donothing declaration
234 statement case_line donothing
236 (* --------------------------------------------------------------------- *)
237 (* --------------------------------------------------------------------- *)
239 let get_option fn
= function
241 | Some x
-> Some
(fn x
)
243 (* --------------------------------------------------------------------- *)
244 (* --------------------------------------------------------------------- *)
247 let convert_info info
=
250 (function (s
,info
) -> (s
,info
.Ast0.line_start
,info
.Ast0.column
))
252 { Ast.line
= info
.Ast0.pos_info
.Ast0.line_start
;
253 Ast.column
= info
.Ast0.pos_info
.Ast0.column
;
254 Ast.strbef
= strings_to_s info
.Ast0.strings_before
;
255 Ast.straft
= strings_to_s info
.Ast0.strings_after
;}
257 let convert_mcodekind adj
= function
258 Ast0.MINUS
(replacements
) ->
259 let (replacements
,_
) = !replacements
in
260 Ast.MINUS
(Ast.NoPos
,[],adj
,replacements
)
261 | Ast0.PLUS count
-> Ast.PLUS count
262 | Ast0.CONTEXT
(befaft
) ->
263 let (befaft
,_
,_
) = !befaft
in Ast.CONTEXT
(Ast.NoPos
,befaft
)
264 | Ast0.MIXED
(_
) -> failwith
"not possible for mcode"
266 let pos_mcode(term
,_
,info
,mcodekind
,pos
,adj
) =
267 (* avoids a recursion problem *)
268 (term
,convert_info info
,convert_mcodekind adj mcodekind
,Ast.NoMetaPos
)
270 let mcode (term
,_
,info
,mcodekind
,pos
,adj
) =
273 Ast0.MetaPos
(pos,constraints
,per
) ->
274 Ast.MetaPos
(pos_mcode pos,constraints
,per
,unitary,false)
275 | _
-> Ast.NoMetaPos
in
276 (term
,convert_info info
,convert_mcodekind adj mcodekind
,pos)
278 (* --------------------------------------------------------------------- *)
280 let wrap ast line isos
=
281 {(Ast.make_term ast
) with Ast.node_line
= line
;
284 let rewrap ast0 isos ast
=
285 wrap ast
((Ast0.get_info ast0
).Ast0.pos_info
.Ast0.line_start
) isos
289 (* no isos on tokens *)
290 let tokenwrap (_
,info
,_
,_
) s ast
= wrap ast info
.Ast.line
no_isos
291 let iso_tokenwrap (_
,info
,_
,_
) s ast iso
= wrap ast info
.Ast.line iso
295 (match Ast0.unwrap d
with
296 Ast0.DOTS
(x
) -> Ast.DOTS
(List.map fn x
)
297 | Ast0.CIRCLES
(x
) -> Ast.CIRCLES
(List.map fn x
)
298 | Ast0.STARS
(x
) -> Ast.STARS
(List.map fn x
))
300 (* --------------------------------------------------------------------- *)
303 let rec do_isos l
= List.map
(function (nm
,x
) -> (nm
,anything x
)) l
306 rewrap i
(do_isos (Ast0.get_iso i
))
307 (match Ast0.unwrap i
with
308 Ast0.Id
(name
) -> Ast.Id
(mcode name
)
309 | Ast0.MetaId
(name
,constraints
,_
) ->
310 Ast.MetaId
(mcode name
,constraints
,unitary,false)
311 | Ast0.MetaFunc
(name
,constraints
,_
) ->
312 Ast.MetaFunc
(mcode name
,constraints
,unitary,false)
313 | Ast0.MetaLocalFunc
(name
,constraints
,_
) ->
314 Ast.MetaLocalFunc
(mcode name
,constraints
,unitary,false)
315 | Ast0.OptIdent
(id
) -> Ast.OptIdent
(ident id
)
316 | Ast0.UniqueIdent
(id
) -> Ast.UniqueIdent
(ident id
))
318 (* --------------------------------------------------------------------- *)
323 rewrap e
(do_isos (Ast0.get_iso e
))
324 (match Ast0.unwrap e
with
325 Ast0.Ident
(id
) -> Ast.Ident
(ident id
)
326 | Ast0.Constant
(const
) ->
327 Ast.Constant
(mcode const
)
328 | Ast0.FunCall
(fn
,lp
,args
,rp
) ->
329 let fn = expression fn in
331 let args = dots expression args in
333 Ast.FunCall
(fn,lp,args,rp)
334 | Ast0.Assignment
(left
,op
,right
,simple
) ->
335 Ast.Assignment
(expression left
,mcode op
,expression right
,simple
)
336 | Ast0.CondExpr
(exp1
,why
,exp2
,colon
,exp3
) ->
337 let exp1 = expression exp1 in
338 let why = mcode why in
339 let exp2 = get_option expression exp2 in
340 let colon = mcode colon in
341 let exp3 = expression exp3 in
342 Ast.CondExpr
(exp1,why,exp2,colon,exp3)
343 | Ast0.Postfix
(exp
,op
) ->
344 Ast.Postfix
(expression exp
,mcode op
)
345 | Ast0.Infix
(exp
,op
) ->
346 Ast.Infix
(expression exp
,mcode op
)
347 | Ast0.Unary
(exp
,op
) ->
348 Ast.Unary
(expression exp
,mcode op
)
349 | Ast0.Binary
(left
,op
,right
) ->
350 Ast.Binary
(expression left
,mcode op
,expression right
)
351 | Ast0.Nested
(left
,op
,right
) ->
352 Ast.Nested
(expression left
,mcode op
,expression right
)
353 | Ast0.Paren
(lp,exp
,rp) ->
354 Ast.Paren
(mcode lp,expression exp
,mcode rp)
355 | Ast0.ArrayAccess
(exp1,lb
,exp2,rb
) ->
356 Ast.ArrayAccess
(expression exp1,mcode lb
,expression exp2,mcode rb
)
357 | Ast0.RecordAccess
(exp
,pt
,field
) ->
358 Ast.RecordAccess
(expression exp
,mcode pt
,ident field
)
359 | Ast0.RecordPtAccess
(exp
,ar
,field
) ->
360 Ast.RecordPtAccess
(expression exp
,mcode ar
,ident field
)
361 | Ast0.Cast
(lp,ty
,rp,exp
) ->
362 Ast.Cast
(mcode lp,typeC ty
,mcode rp,expression exp
)
363 | Ast0.SizeOfExpr
(szf
,exp
) ->
364 Ast.SizeOfExpr
(mcode szf
,expression exp
)
365 | Ast0.SizeOfType
(szf
,lp,ty
,rp) ->
366 Ast.SizeOfType
(mcode szf
, mcode lp,typeC ty
,mcode rp)
367 | Ast0.TypeExp
(ty
) -> Ast.TypeExp
(typeC ty
)
368 | Ast0.MetaErr
(name
,cstrts
,_
) ->
369 Ast.MetaErr
(mcode name
,constraints cstrts
,unitary,false)
370 | Ast0.MetaExpr
(name
,cstrts
,ty
,form
,_
) ->
371 Ast.MetaExpr
(mcode name
,constraints cstrts
,unitary,ty
,form
,false)
372 | Ast0.MetaExprList
(name
,Some lenname
,_
) ->
373 Ast.MetaExprList
(mcode name
,Some
(mcode lenname
,unitary,false),
375 | Ast0.MetaExprList
(name
,None
,_
) ->
376 Ast.MetaExprList
(mcode name
,None
,unitary,false)
377 | Ast0.EComma
(cm
) -> Ast.EComma
(mcode cm
)
378 | Ast0.DisjExpr
(_
,exps
,_
,_
) ->
379 Ast.DisjExpr
(List.map
expression exps
)
380 | Ast0.NestExpr
(starter
,exp_dots
,ender
,whencode
,multi
) ->
381 let starter = mcode starter in
382 let whencode = get_option expression whencode in
383 let ender = mcode ender in
384 Ast.NestExpr
(starter,dots expression exp_dots
,ender,whencode,multi
)
385 | Ast0.Edots
(dots,whencode) ->
386 let dots = mcode dots in
387 let whencode = get_option expression whencode in
388 Ast.Edots
(dots,whencode)
389 | Ast0.Ecircles
(dots,whencode) ->
390 let dots = mcode dots in
391 let whencode = get_option expression whencode in
392 Ast.Ecircles
(dots,whencode)
393 | Ast0.Estars
(dots,whencode) ->
394 let dots = mcode dots in
395 let whencode = get_option expression whencode in
396 Ast.Estars
(dots,whencode)
397 | Ast0.OptExp
(exp
) -> Ast.OptExp
(expression exp
)
398 | Ast0.UniqueExp
(exp
) -> Ast.UniqueExp
(expression exp
)) in
399 if Ast0.get_test_exp e
then Ast.set_test_exp
e1 else e1
401 and expression_dots ed
= dots expression ed
405 Ast0.NoConstraint
-> Ast.NoConstraint
406 | Ast0.NotIdCstrt idctrt
-> Ast.NotIdCstrt idctrt
407 | Ast0.NotExpCstrt exps
-> Ast.NotExpCstrt
(List.map
expression exps
)
408 | Ast0.SubExpCstrt ids
-> Ast.SubExpCstrt ids
410 (* --------------------------------------------------------------------- *)
413 and rewrap_iso t t1
= rewrap t
(do_isos (Ast0.get_iso t
)) t1
416 rewrap t
(do_isos (Ast0.get_iso t
))
417 (match Ast0.unwrap t
with
418 Ast0.ConstVol
(cv
,ty
) ->
419 let rec collect_disjs t
=
420 match Ast0.unwrap t
with
421 Ast0.DisjType
(_
,types
,_
,_
) ->
422 if Ast0.get_iso t
= []
423 then List.concat (List.map
collect_disjs types
)
424 else failwith
"unexpected iso on a disjtype"
430 (Some
(mcode cv
),rewrap_iso ty
(base_typeC ty
)))
431 (collect_disjs ty
) in
432 (* one could worry that isos are lost because we flatten the
433 disjunctions. but there should not be isos on the disjunctions
437 | types
-> Ast.DisjType
(List.map
(rewrap t
no_isos) types
))
438 | Ast0.BaseType
(_
) | Ast0.Signed
(_
,_
) | Ast0.Pointer
(_
,_
)
439 | Ast0.FunctionPointer
(_
,_
,_
,_
,_
,_
,_
) | Ast0.FunctionType
(_
,_
,_
,_
)
440 | Ast0.Array
(_
,_
,_
,_
) | Ast0.EnumName
(_
,_
) | Ast0.StructUnionName
(_
,_
)
441 | Ast0.StructUnionDef
(_
,_
,_
,_
) | Ast0.TypeName
(_
) | Ast0.MetaType
(_
,_
) ->
442 Ast.Type
(None
,rewrap t
no_isos (base_typeC t
))
443 | Ast0.DisjType
(_
,types
,_
,_
) -> Ast.DisjType
(List.map
typeC types
)
444 | Ast0.OptType
(ty
) -> Ast.OptType
(typeC ty
)
445 | Ast0.UniqueType
(ty
) -> Ast.UniqueType
(typeC ty
))
448 match Ast0.unwrap t
with
449 Ast0.BaseType
(ty
,strings
) -> Ast.BaseType
(ty
,List.map
mcode strings
)
450 | Ast0.Signed
(sgn
,ty
) ->
451 Ast.SignedT
(mcode sgn
,
452 get_option (function x
-> rewrap_iso x
(base_typeC x
)) ty
)
453 | Ast0.Pointer
(ty
,star
) -> Ast.Pointer
(typeC ty
,mcode star
)
454 | Ast0.FunctionPointer
(ty
,lp1
,star
,rp1
,lp2
,params
,rp2
) ->
456 (typeC ty
,mcode lp1
,mcode star
,mcode rp1
,
457 mcode lp2
,parameter_list params
,mcode rp2
)
458 | Ast0.FunctionType
(ret
,lp,params
,rp) ->
459 let allminus = check_allminus.VT0.combiner_rec_typeC t
in
461 (allminus,get_option typeC ret
,mcode lp,
462 parameter_list params
,mcode rp)
463 | Ast0.Array
(ty
,lb
,size
,rb
) ->
464 Ast.Array
(typeC ty
,mcode lb
,get_option expression size
,mcode rb
)
465 | Ast0.EnumName
(kind
,name
) ->
466 Ast.EnumName
(mcode kind
,ident name
)
467 | Ast0.StructUnionName
(kind
,name
) ->
468 Ast.StructUnionName
(mcode kind
,get_option ident name
)
469 | Ast0.StructUnionDef
(ty
,lb
,decls
,rb
) ->
470 Ast.StructUnionDef
(typeC ty
,mcode lb
,
471 dots declaration decls
,
473 | Ast0.TypeName
(name
) -> Ast.TypeName
(mcode name
)
474 | Ast0.MetaType
(name
,_
) ->
475 Ast.MetaType
(mcode name
,unitary,false)
476 | _
-> failwith
"ast0toast: unexpected type"
478 (* --------------------------------------------------------------------- *)
479 (* Variable declaration *)
480 (* Even if the Cocci program specifies a list of declarations, they are
481 split out into multiple declarations of a single variable each. *)
484 rewrap d
(do_isos (Ast0.get_iso d
))
485 (match Ast0.unwrap d
with
486 Ast0.Init
(stg
,ty
,id
,eq
,ini
,sem
) ->
487 let stg = get_option mcode stg in
491 let ini = initialiser
ini in
492 let sem = mcode sem in
493 Ast.Init
(stg,ty,id,eq,ini,sem)
494 | Ast0.UnInit
(stg,ty,id,sem) ->
495 (match Ast0.unwrap
ty with
496 Ast0.FunctionType
(tyx
,lp1
,params
,rp1
) ->
497 let allminus = check_allminus.VT0.combiner_rec_declaration d
in
498 Ast.UnInit
(get_option mcode stg,
499 rewrap ty (do_isos (Ast0.get_iso
ty))
504 (allminus,get_option typeC tyx
,mcode lp1
,
505 parameter_list params
,mcode rp1
)))),
507 | _
-> Ast.UnInit
(get_option mcode stg,typeC ty,ident
id,mcode sem))
508 | Ast0.MacroDecl
(name
,lp,args,rp,sem) ->
509 let name = ident
name in
511 let args = dots expression args in
513 let sem = mcode sem in
514 Ast.MacroDecl
(name,lp,args,rp,sem)
515 | Ast0.TyDecl
(ty,sem) -> Ast.TyDecl
(typeC ty,mcode sem)
516 | Ast0.Typedef
(stg,ty,id,sem) ->
518 (match Ast.unwrap
id with
519 Ast.Type
(None
,id) -> (* only MetaType or Id *)
520 Ast.Typedef
(mcode stg,typeC ty,id,mcode sem)
521 | _
-> failwith
"bad typedef")
522 | Ast0.DisjDecl
(_
,decls
,_
,_
) -> Ast.DisjDecl
(List.map
declaration decls
)
523 | Ast0.Ddots
(dots,whencode) ->
524 let dots = mcode dots in
525 let whencode = get_option declaration whencode in
526 Ast.Ddots
(dots,whencode)
527 | Ast0.OptDecl
(decl
) -> Ast.OptDecl
(declaration decl
)
528 | Ast0.UniqueDecl
(decl
) -> Ast.UniqueDecl
(declaration decl
))
530 and declaration_dots l
= dots declaration l
532 (* --------------------------------------------------------------------- *)
535 and strip_idots initlist
=
537 match Ast0.get_mcode_mcodekind mc
with
540 match Ast0.unwrap initlist
with
542 let (whencode,init
,dotinfo
) =
544 (function (prevwhen
,previnit
,dotinfo
) ->
546 match Ast0.unwrap cur
with
547 Ast0.Idots
(dots,Some
whencode) ->
548 (whencode :: prevwhen
, previnit
,
549 (isminus dots)::dotinfo
)
550 | Ast0.Idots
(dots,None
) ->
551 (prevwhen
, previnit
, (isminus dots)::dotinfo
)
552 | _
-> (prevwhen
, cur
:: previnit
, dotinfo
))
555 if List.for_all
(function x
-> not x
) dotinfo
556 then false (* false if no dots *)
558 if List.for_all
(function x
-> x
) dotinfo
560 else failwith
"inconsistent annotations on initialiser list dots" in
561 (List.rev
whencode, List.rev init
, allminus)
562 | Ast0.CIRCLES
(x
) | Ast0.STARS
(x
) -> failwith
"not possible for an initlist"
566 (match Ast0.unwrap i
with
567 Ast0.MetaInit
(name,_
) -> Ast.MetaInit
(mcode name,unitary,false)
568 | Ast0.InitExpr
(exp
) -> Ast.InitExpr
(expression exp
)
569 | Ast0.InitList
(lb
,initlist
,rb
) ->
570 let (whencode,initlist
,allminus) = strip_idots initlist
in
571 Ast.InitList
(allminus,mcode lb
,List.map initialiser initlist
,mcode rb
,
572 List.map initialiser
whencode)
573 | Ast0.InitGccExt
(designators
,eq,ini) ->
574 Ast.InitGccExt
(List.map designator designators
,mcode eq,
576 | Ast0.InitGccName
(name,eq,ini) ->
577 Ast.InitGccName
(ident
name,mcode eq,initialiser
ini)
578 | Ast0.IComma
(comma
) -> Ast.IComma
(mcode comma
)
579 | Ast0.Idots
(_
,_
) -> failwith
"Idots should have been removed"
580 | Ast0.OptIni
(ini) -> Ast.OptIni
(initialiser
ini)
581 | Ast0.UniqueIni
(ini) -> Ast.UniqueIni
(initialiser
ini))
583 and designator
= function
584 Ast0.DesignatorField
(dot
,id) -> Ast.DesignatorField
(mcode dot
,ident
id)
585 | Ast0.DesignatorIndex
(lb
,exp
,rb
) ->
586 Ast.DesignatorIndex
(mcode lb
, expression exp
, mcode rb
)
587 | Ast0.DesignatorRange
(lb
,min
,dots,max
,rb
) ->
588 Ast.DesignatorRange
(mcode lb
,expression min
,mcode dots,expression max
,
591 (* --------------------------------------------------------------------- *)
594 and parameterTypeDef p
=
596 (match Ast0.unwrap p
with
597 Ast0.VoidParam
(ty) -> Ast.VoidParam
(typeC ty)
598 | Ast0.Param
(ty,id) -> Ast.Param
(typeC ty,get_option ident
id)
599 | Ast0.MetaParam
(name,_
) ->
600 Ast.MetaParam
(mcode name,unitary,false)
601 | Ast0.MetaParamList
(name,Some lenname
,_
) ->
602 Ast.MetaParamList
(mcode name,Some
(mcode lenname
,unitary,false),
604 | Ast0.MetaParamList
(name,None
,_
) ->
605 Ast.MetaParamList
(mcode name,None
,unitary,false)
606 | Ast0.PComma
(cm
) -> Ast.PComma
(mcode cm
)
607 | Ast0.Pdots
(dots) -> Ast.Pdots
(mcode dots)
608 | Ast0.Pcircles
(dots) -> Ast.Pcircles
(mcode dots)
609 | Ast0.OptParam
(param
) -> Ast.OptParam
(parameterTypeDef param
)
610 | Ast0.UniqueParam
(param
) -> Ast.UniqueParam
(parameterTypeDef param
))
612 and parameter_list l
= dots parameterTypeDef l
614 (* --------------------------------------------------------------------- *)
618 let rec statement seqible s
=
619 let rewrap_stmt ast0 ast
=
621 match Ast0.get_dots_bef_aft s
with
622 Ast0.NoDots
-> Ast.NoDots
623 | Ast0.DroppingBetweenDots s
->
624 Ast.DroppingBetweenDots
(statement seqible s
,get_ctr())
625 | Ast0.AddingBetweenDots s
->
626 Ast.AddingBetweenDots
(statement seqible s
,get_ctr()) in
627 Ast.set_dots_bef_aft
befaft (rewrap ast0
no_isos ast
) in
628 let rewrap_rule_elem ast0 ast
=
629 rewrap ast0
(do_isos (Ast0.get_iso ast0
)) ast
in
631 (match Ast0.unwrap s
with
632 Ast0.Decl
((_
,bef
),decl
) ->
633 Ast.Atomic
(rewrap_rule_elem s
634 (Ast.Decl
(convert_mcodekind (-1) bef
,
635 check_allminus.VT0.combiner_rec_statement s
,
637 | Ast0.Seq
(lbrace
,body
,rbrace
) ->
638 let lbrace = mcode lbrace in
639 let body = dots (statement seqible
) body in
640 let rbrace = mcode rbrace in
641 Ast.Seq
(iso_tokenwrap lbrace s
(Ast.SeqStart
(lbrace))
642 (do_isos (Ast0.get_iso s
)),
644 tokenwrap rbrace s
(Ast.SeqEnd
(rbrace)))
645 | Ast0.ExprStatement
(exp
,sem) ->
646 Ast.Atomic
(rewrap_rule_elem s
647 (Ast.ExprStatement
(expression exp
,mcode sem)))
648 | Ast0.IfThen
(iff
,lp,exp
,rp,branch
,(_
,aft
)) ->
651 (Ast.IfHeader
(mcode iff
,mcode lp,expression exp
,mcode rp)),
652 statement Ast.NotSequencible branch
,
653 ([],[],[],convert_mcodekind (-1) aft
))
654 | Ast0.IfThenElse
(iff
,lp,exp
,rp,branch1
,els
,branch2
,(_
,aft
)) ->
655 let els = mcode els in
658 (Ast.IfHeader
(mcode iff
,mcode lp,expression exp
,mcode rp)),
659 statement Ast.NotSequencible branch1
,
660 tokenwrap els s
(Ast.Else
(els)),
661 statement Ast.NotSequencible branch2
,
662 ([],[],[],convert_mcodekind (-1) aft
))
663 | Ast0.While
(wh
,lp,exp
,rp,body,(_
,aft
)) ->
664 Ast.While
(rewrap_rule_elem s
666 (mcode wh
,mcode lp,expression exp
,mcode rp)),
667 statement Ast.NotSequencible
body,
668 ([],[],[],convert_mcodekind (-1) aft
))
669 | Ast0.Do
(d
,body,wh
,lp,exp
,rp,sem) ->
671 Ast.Do
(rewrap_rule_elem s
(Ast.DoHeader
(mcode d
)),
672 statement Ast.NotSequencible
body,
674 (Ast.WhileTail
(wh,mcode lp,expression exp
,mcode rp,
676 | Ast0.For
(fr
,lp,exp1,sem1
,exp2,sem2
,exp3,rp,body,(_
,aft
)) ->
679 let exp1 = get_option expression exp1 in
680 let sem1 = mcode sem1 in
681 let exp2 = get_option expression exp2 in
682 let sem2= mcode sem2 in
683 let exp3 = get_option expression exp3 in
685 let body = statement Ast.NotSequencible
body in
686 Ast.For
(rewrap_rule_elem s
687 (Ast.ForHeader
(fr,lp,exp1,sem1,exp2,sem2,exp3,rp)),
688 body,([],[],[],convert_mcodekind (-1) aft
))
689 | Ast0.Iterator
(nm
,lp,args,rp,body,(_
,aft
)) ->
690 Ast.Iterator
(rewrap_rule_elem s
693 dots expression args,
695 statement Ast.NotSequencible
body,
696 ([],[],[],convert_mcodekind (-1) aft
))
697 | Ast0.Switch
(switch
,lp,exp
,rp,lb
,decls
,cases
,rb
) ->
698 let switch = mcode switch in
700 let exp = expression exp in
703 let decls = dots (statement seqible
) decls in
704 let cases = List.map
case_line (Ast0.undots
cases) in
706 Ast.Switch
(rewrap_rule_elem s
(Ast.SwitchHeader
(switch,lp,exp,rp)),
707 tokenwrap lb s
(Ast.SeqStart
(lb)),
709 tokenwrap rb s
(Ast.SeqEnd
(rb)))
710 | Ast0.Break
(br
,sem) ->
711 Ast.Atomic
(rewrap_rule_elem s
(Ast.Break
(mcode br
,mcode sem)))
712 | Ast0.Continue
(cont
,sem) ->
713 Ast.Atomic
(rewrap_rule_elem s
(Ast.Continue
(mcode cont
,mcode sem)))
714 | Ast0.Label
(l
,dd
) ->
715 Ast.Atomic
(rewrap_rule_elem s
(Ast.Label
(ident l
,mcode dd
)))
716 | Ast0.Goto
(goto
,l
,sem) ->
718 (rewrap_rule_elem s
(Ast.Goto
(mcode goto
,ident l
,mcode sem)))
719 | Ast0.Return
(ret
,sem) ->
720 Ast.Atomic
(rewrap_rule_elem s
(Ast.Return
(mcode ret
,mcode sem)))
721 | Ast0.ReturnExpr
(ret
,exp,sem) ->
724 (Ast.ReturnExpr
(mcode ret
,expression exp,mcode sem)))
725 | Ast0.MetaStmt
(name,_
) ->
726 Ast.Atomic
(rewrap_rule_elem s
727 (Ast.MetaStmt
(mcode name,unitary,seqible
,false)))
728 | Ast0.MetaStmtList
(name,_
) ->
729 Ast.Atomic
(rewrap_rule_elem s
730 (Ast.MetaStmtList
(mcode name,unitary,false)))
731 | Ast0.TopExp
(exp) ->
732 Ast.Atomic
(rewrap_rule_elem s
(Ast.TopExp
(expression exp)))
734 Ast.Atomic
(rewrap_rule_elem s
(Ast.Exp
(expression exp)))
735 | Ast0.TopInit
(init
) ->
736 Ast.Atomic
(rewrap_rule_elem s
(Ast.TopInit
(initialiser init
)))
738 Ast.Atomic
(rewrap_rule_elem s
(Ast.Ty
(typeC ty)))
739 | Ast0.Disj
(_
,rule_elem_dots_list
,_
,_
) ->
740 Ast.Disj
(List.map
(function x
-> statement_dots seqible x
)
742 | Ast0.Nest
(starter,rule_elem_dots
,ender,whn
,multi
) ->
744 (mcode starter,statement_dots
Ast.Sequencible rule_elem_dots
,
747 (whencode (statement_dots
Ast.Sequencible
)
748 (statement Ast.NotSequencible
))
751 | Ast0.Dots
(d
,whn
) ->
755 (whencode (statement_dots
Ast.Sequencible
)
756 (statement Ast.NotSequencible
))
758 Ast.Dots
(d,whn,[],[])
759 | Ast0.Circles
(d,whn) ->
763 (whencode (statement_dots
Ast.Sequencible
)
764 (statement Ast.NotSequencible
))
766 Ast.Circles
(d,whn,[],[])
767 | Ast0.Stars
(d,whn) ->
771 (whencode (statement_dots
Ast.Sequencible
)
772 (statement Ast.NotSequencible
))
774 Ast.Stars
(d,whn,[],[])
775 | Ast0.FunDecl
((_
,bef
),fi
,name,lp,params
,rp,lbrace,body,rbrace) ->
776 let fi = List.map fninfo
fi in
777 let name = ident
name in
779 let params = parameter_list
params in
781 let lbrace = mcode lbrace in
782 let body = dots (statement seqible
) body in
783 let rbrace = mcode rbrace in
784 let allminus = check_allminus.VT0.combiner_rec_statement s
in
785 Ast.FunDecl
(rewrap_rule_elem s
786 (Ast.FunHeader
(convert_mcodekind (-1) bef
,
787 allminus,fi,name,lp,params,rp)),
788 tokenwrap lbrace s
(Ast.SeqStart
(lbrace)),
790 tokenwrap rbrace s
(Ast.SeqEnd
(rbrace)))
791 | Ast0.Include
(inc
,str
) ->
792 Ast.Atomic
(rewrap_rule_elem s
(Ast.Include
(mcode inc
,mcode str
)))
793 | Ast0.Define
(def
,id,params,body) ->
797 (mcode def
,ident
id, define_parameters
params)),
798 statement_dots
Ast.NotSequencible
(*not sure*) body)
799 | Ast0.OptStm
(stm
) -> Ast.OptStm
(statement seqible stm
)
800 | Ast0.UniqueStm
(stm
) -> Ast.UniqueStm
(statement seqible stm
))
802 and define_parameters p
=
804 (match Ast0.unwrap p
with
805 Ast0.NoParams
-> Ast.NoParams
806 | Ast0.DParams
(lp,params,rp) ->
807 Ast.DParams
(mcode lp,
808 dots define_param
params,
813 (match Ast0.unwrap p
with
814 Ast0.DParam
(id) -> Ast.DParam
(ident
id)
815 | Ast0.DPComma
(comma
) -> Ast.DPComma
(mcode comma
)
816 | Ast0.DPdots
(d) -> Ast.DPdots
(mcode d)
817 | Ast0.DPcircles
(c) -> Ast.DPcircles
(mcode c)
818 | Ast0.OptDParam
(dp
) -> Ast.OptDParam
(define_param dp
)
819 | Ast0.UniqueDParam
(dp
) -> Ast.UniqueDParam
(define_param dp
))
821 and whencode notfn alwaysfn
= function
822 Ast0.WhenNot a
-> Ast.WhenNot
(notfn a
)
823 | Ast0.WhenAlways a
-> Ast.WhenAlways
(alwaysfn a
)
824 | Ast0.WhenModifier
(x
) -> Ast.WhenModifier
(x
)
826 let rewrap_rule_elem ast0 ast
=
827 rewrap ast0
(do_isos (Ast0.get_iso ast0
)) ast
in
829 Ast0.WhenNotTrue
(e
) ->
830 Ast.WhenNotTrue
(rewrap_rule_elem e
(Ast.Exp
(expression e
)))
831 | Ast0.WhenNotFalse
(e
) ->
832 Ast.WhenNotFalse
(rewrap_rule_elem e
(Ast.Exp
(expression e
)))
833 | _
-> failwith
"not possible"
835 and process_list seqible isos
= function
838 let first = statement seqible x
in
840 if !Flag.track_iso_usage
841 then Ast.set_isos
first (isos
@(Ast.get_isos
first))
843 (match Ast0.unwrap x
with
844 Ast0.Dots
(_
,_
) | Ast0.Nest
(_
) ->
845 first::(process_list
(Ast.SequencibleAfterDots
[]) no_isos rest
)
847 first::(process_list
Ast.Sequencible
no_isos rest
))
849 and statement_dots seqible
d =
850 let isos = do_isos (Ast0.get_iso
d) in
852 (match Ast0.unwrap
d with
853 Ast0.DOTS
(x
) -> Ast.DOTS
(process_list seqible
isos x
)
854 | Ast0.CIRCLES
(x
) -> Ast.CIRCLES
(process_list seqible
isos x
)
855 | Ast0.STARS
(x
) -> Ast.STARS
(process_list seqible
isos x
))
857 (* the following is no longer used.
858 the goal was to let one put a statement at the very beginning of a function
859 pattern and have it skip over the declarations in the C code.
860 that feature was removed a long time ago, however, in favor of
861 ... when != S, which also causes whatever comes after it to match the
862 first real statement.
863 the separation of declarations from the rest of the body means that the
864 quantifier of any variable shared between them comes out too high, posing
865 problems when there is ... decl ... stmt, as the quantifier of any shared
866 variable will be around the whole thing, making variables not free enough
867 in the first ..., and thus not implementing the expected shortest path
868 condition. example: f() { ... int A; ... foo(A); }.
869 the quantifier for A should start just before int A, not at the top of the
871 and separate_decls seqible d =
872 let rec collect_decls = function
875 (match Ast0.unwrap x with
877 let (decls,other) = collect_decls xs in
879 | Ast0.Dots(_,_) | Ast0.Nest(_,_,_,_,_) ->
880 let (decls,other) = collect_decls xs in
883 | _ -> (x :: decls,other))
884 | Ast0.Disj(starter,stmt_dots_list,mids,ender) ->
885 let disjs = List.map collect_dot_decls stmt_dots_list in
886 let all_decls = List.for_all (function (_,s) -> s=[]) disjs in
889 let (decls,other) = collect_decls xs in
894 and collect_dot_decls d =
895 match Ast0.unwrap d with
896 Ast0.DOTS(x) -> collect_decls x
897 | Ast0.CIRCLES(x) -> collect_decls x
898 | Ast0.STARS(x) -> collect_decls x in
901 let (decls,other) = collect_decls l in
902 (rewrap d no_isos (fn (List.map (statement seqible) decls)),
904 (fn (process_list seqible (do_isos (Ast0.get_iso d)) other))) in
905 match Ast0.unwrap d with
906 Ast0.DOTS(x) -> process x d (function x -> Ast.DOTS x)
907 | Ast0.CIRCLES(x) -> process x d (function x -> Ast.CIRCLES x)
908 | Ast0.STARS(x) -> process x d (function x -> Ast.STARS x) *) in
910 statement Ast.Sequencible s
912 and fninfo
= function
913 Ast0.FStorage
(stg) -> Ast.FStorage
(mcode stg)
914 | Ast0.FType
(ty) -> Ast.FType
(typeC ty)
915 | Ast0.FInline
(inline
) -> Ast.FInline
(mcode inline
)
916 | Ast0.FAttr
(attr
) -> Ast.FAttr
(mcode attr
)
918 and option_to_list
= function
924 (match Ast0.unwrap
c with
925 Ast0.Default
(def
,colon,code
) ->
926 let def = mcode def in
927 let colon = mcode colon in
928 let code = dots statement code in
929 Ast.CaseLine
(rewrap c no_isos (Ast.Default
(def,colon)),code)
930 | Ast0.Case
(case
,exp,colon,code) ->
931 let case = mcode case in
932 let exp = expression exp in
933 let colon = mcode colon in
934 let code = dots statement code in
935 Ast.CaseLine
(rewrap c no_isos (Ast.Case
(case,exp,colon)),code)
936 | Ast0.DisjCase
(_
,case_lines
,_
,_
) ->
937 failwith
"not supported"
938 (*Ast.CaseLine(Ast.DisjRuleElem(List.map case_line case_lines))*)
940 | Ast0.OptCase
(case) -> Ast.OptCase
(case_line case))
942 and statement_dots l
= dots statement l
944 (* --------------------------------------------------------------------- *)
946 (* what is possible is only what is at the top level in an iso *)
947 and anything
= function
948 Ast0.DotsExprTag
(d) -> Ast.ExprDotsTag
(expression_dots
d)
949 | Ast0.DotsParamTag
(d) -> Ast.ParamDotsTag
(parameter_list
d)
950 | Ast0.DotsInitTag
(d) -> failwith
"not possible"
951 | Ast0.DotsStmtTag
(d) -> Ast.StmtDotsTag
(statement_dots
d)
952 | Ast0.DotsDeclTag
(d) -> Ast.DeclDotsTag
(declaration_dots
d)
953 | Ast0.DotsCaseTag
(d) -> failwith
"not possible"
954 | Ast0.IdentTag
(d) -> Ast.IdentTag
(ident
d)
955 | Ast0.ExprTag
(d) -> Ast.ExpressionTag
(expression d)
956 | Ast0.ArgExprTag
(d) | Ast0.TestExprTag
(d) ->
957 failwith
"only in isos, not converted to ast"
958 | Ast0.TypeCTag
(d) -> Ast.FullTypeTag
(typeC d)
959 | Ast0.ParamTag
(d) -> Ast.ParamTag
(parameterTypeDef
d)
960 | Ast0.InitTag
(d) -> Ast.InitTag
(initialiser
d)
961 | Ast0.DeclTag
(d) -> Ast.DeclarationTag
(declaration d)
962 | Ast0.StmtTag
(d) -> Ast.StatementTag
(statement d)
963 | Ast0.CaseLineTag
(d) -> Ast.CaseLineTag
(case_line d)
964 | Ast0.TopTag
(d) -> Ast.Code
(top_level
d)
965 | Ast0.IsoWhenTag
(_
) -> failwith
"not possible"
966 | Ast0.IsoWhenTTag
(_
) -> failwith
"not possible"
967 | Ast0.IsoWhenFTag
(_
) -> failwith
"not possible"
968 | Ast0.MetaPosTag _
-> failwith
"not possible"
970 (* --------------------------------------------------------------------- *)
971 (* Function declaration *)
972 (* top level isos are probably lost to tracking *)
976 (match Ast0.unwrap t
with
977 Ast0.FILEINFO
(old_file
,new_file
) ->
978 Ast.FILEINFO
(mcode old_file
,mcode new_file
)
979 | Ast0.DECL
(stmt
) -> Ast.DECL
(statement stmt
)
980 | Ast0.CODE
(rule_elem_dots
) ->
981 Ast.CODE
(statement_dots rule_elem_dots
)
982 | Ast0.ERRORWORDS
(exps
) -> Ast.ERRORWORDS
(List.map
expression exps
)
983 | Ast0.OTHER
(_
) -> failwith
"eliminated by top_level")
985 (* --------------------------------------------------------------------- *)
986 (* Entry point for minus code *)
988 (* Inline_mcodes is very important - sends + code attached to the - code
989 down to the mcodes. The functions above can only be used when there is no
990 attached + code, eg in + code itself. *)
991 let ast0toast_toplevel x
=
992 inline_mcodes.VT0.combiner_rec_top_level x
;
995 let ast0toast name deps dropped exists x is_exp ruletype
=
996 List.iter
inline_mcodes.VT0.combiner_rec_top_level x
;
998 (name,(deps
,dropped
,exists
),List.map top_level x
,is_exp
,ruletype
)