Release coccinelle-0.2.0
[bpt/coccinelle.git] / parsing_cocci / insert_plus.ml
CommitLineData
9f8e26f4
C
1(*
2 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
3 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
4 * This file is part of Coccinelle.
5 *
6 * Coccinelle is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, according to version 2 of the License.
9 *
10 * Coccinelle is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * The authors reserve the right to distribute this or future versions of
19 * Coccinelle under other licenses.
20 *)
21
22
34e49164
C
23(* The error message "no available token to attach to" often comes in an
24argument list of unbounded length. In this case, one should move a comma so
25that there is a comma after the + code. *)
26
27(* Start at all of the corresponding BindContext nodes in the minus and
28plus trees, and traverse their children. We take the same strategy as
29before: collect the list of minus/context nodes/tokens and the list of plus
30tokens, and then merge them. *)
31
32module Ast = Ast_cocci
33module Ast0 = Ast0_cocci
34module V0 = Visitor_ast0
b1b2de81 35module VT0 = Visitor_ast0_types
34e49164
C
36module CN = Context_neg
37
faf9a90c
C
38let empty_isos = ref false
39
34e49164
C
40let get_option f = function
41 None -> []
42 | Some x -> f x
43
44(* --------------------------------------------------------------------- *)
45(* Collect root and all context nodes in a tree *)
46
47let collect_context e =
48 let bind x y = x @ y in
49 let option_default = [] in
50
51 let mcode _ = [] in
52
53 let donothing builder r k e =
54 match Ast0.get_mcodekind e with
55 Ast0.CONTEXT(_) -> (builder e) :: (k e)
56 | _ -> k e in
57
58(* special case for everything that contains whencode, so that we skip over
59it *)
60 let expression r k e =
61 donothing Ast0.expr r k
62 (Ast0.rewrap e
63 (match Ast0.unwrap e with
64 Ast0.NestExpr(starter,exp,ender,whencode,multi) ->
65 Ast0.NestExpr(starter,exp,ender,None,multi)
66 | Ast0.Edots(dots,whencode) -> Ast0.Edots(dots,None)
67 | Ast0.Ecircles(dots,whencode) -> Ast0.Ecircles(dots,None)
68 | Ast0.Estars(dots,whencode) -> Ast0.Estars(dots,None)
69 | e -> e)) in
70
71 let initialiser r k i =
72 donothing Ast0.ini r k
73 (Ast0.rewrap i
74 (match Ast0.unwrap i with
75 Ast0.Idots(dots,whencode) -> Ast0.Idots(dots,None)
76 | i -> i)) in
77
78 let statement r k s =
79 donothing Ast0.stmt r k
80 (Ast0.rewrap s
81 (match Ast0.unwrap s with
82 Ast0.Nest(started,stm_dots,ender,whencode,multi) ->
83 Ast0.Nest(started,stm_dots,ender,[],multi)
84 | Ast0.Dots(dots,whencode) -> Ast0.Dots(dots,[])
85 | Ast0.Circles(dots,whencode) -> Ast0.Circles(dots,[])
86 | Ast0.Stars(dots,whencode) -> Ast0.Stars(dots,[])
87 | s -> s)) in
88
89 let topfn r k e = Ast0.TopTag(e) :: (k e) in
90
91 let res =
b1b2de81 92 V0.flat_combiner bind option_default
34e49164 93 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
34e49164
C
94 (donothing Ast0.dotsExpr) (donothing Ast0.dotsInit)
95 (donothing Ast0.dotsParam) (donothing Ast0.dotsStmt)
96 (donothing Ast0.dotsDecl) (donothing Ast0.dotsCase)
97 (donothing Ast0.ident) expression (donothing Ast0.typeC) initialiser
98 (donothing Ast0.param) (donothing Ast0.decl) statement
99 (donothing Ast0.case_line) topfn in
b1b2de81 100 res.VT0.combiner_rec_top_level e
34e49164
C
101
102(* --------------------------------------------------------------------- *)
103(* --------------------------------------------------------------------- *)
104(* collect the possible join points, in order, among the children of a
105BindContext. Dots are not allowed. Nests and disjunctions are no problem,
106because their delimiters take up a line by themselves *)
107
108(* An Unfavored token is one that is in a BindContext node; using this causes
109 the node to become Neither, meaning that isomorphisms can't be applied *)
110(* Toplevel is for the bef token of a function declaration and is for
111attaching top-level definitions that should come before the complete
112declaration *)
113type minus_join_point = Favored | Unfavored | Toplevel | Decl
114
115(* Maps the index of a node to the indices of the mcodes it contains *)
116let root_token_table = (Hashtbl.create(50) : (int, int list) Hashtbl.t)
117
118let create_root_token_table minus =
119 Hashtbl.iter
120 (function tokens ->
121 function (node,_) ->
122 let key =
123 match node with
124 Ast0.DotsExprTag(d) -> Ast0.get_index d
125 | Ast0.DotsInitTag(d) -> Ast0.get_index d
126 | Ast0.DotsParamTag(d) -> Ast0.get_index d
127 | Ast0.DotsStmtTag(d) -> Ast0.get_index d
128 | Ast0.DotsDeclTag(d) -> Ast0.get_index d
129 | Ast0.DotsCaseTag(d) -> Ast0.get_index d
130 | Ast0.IdentTag(d) -> Ast0.get_index d
131 | Ast0.ExprTag(d) -> Ast0.get_index d
132 | Ast0.ArgExprTag(d) | Ast0.TestExprTag(d) ->
133 failwith "not possible - iso only"
134 | Ast0.TypeCTag(d) -> Ast0.get_index d
135 | Ast0.ParamTag(d) -> Ast0.get_index d
136 | Ast0.InitTag(d) -> Ast0.get_index d
137 | Ast0.DeclTag(d) -> Ast0.get_index d
138 | Ast0.StmtTag(d) -> Ast0.get_index d
139 | Ast0.CaseLineTag(d) -> Ast0.get_index d
140 | Ast0.TopTag(d) -> Ast0.get_index d
141 | Ast0.IsoWhenTag(_) -> failwith "only within iso phase"
1be43e12
C
142 | Ast0.IsoWhenTTag(_) -> failwith "only within iso phase"
143 | Ast0.IsoWhenFTag(_) -> failwith "only within iso phase"
34e49164
C
144 | Ast0.MetaPosTag(p) -> failwith "metapostag only within iso phase"
145 in
146 Hashtbl.add root_token_table key tokens)
147 CN.minus_table;
148 List.iter
149 (function r ->
150 let index = Ast0.get_index r in
151 try let _ = Hashtbl.find root_token_table index in ()
152 with Not_found -> Hashtbl.add root_token_table index [])
153 minus
154
155let collect_minus_join_points root =
156 let root_index = Ast0.get_index root in
157 let unfavored_tokens = Hashtbl.find root_token_table root_index in
158 let bind x y = x @ y in
159 let option_default = [] in
160
7f004419 161 let mcode (x,_,info,mcodekind,_,_) =
0708f913 162 if List.mem (info.Ast0.pos_info.Ast0.offset) unfavored_tokens
34e49164
C
163 then [(Unfavored,info,mcodekind)]
164 else [(Favored,info,mcodekind)] in
165
166 let do_nothing r k e =
167 let info = Ast0.get_info e in
168 let index = Ast0.get_index e in
169 match Ast0.get_mcodekind e with
170 (Ast0.MINUS(_)) as mc -> [(Favored,info,mc)]
171 | (Ast0.CONTEXT(_)) as mc when not(index = root_index) ->
172 (* This was unfavored at one point, but I don't remember why *)
173 [(Favored,info,mc)]
174 | _ -> k e in
175
176(* don't want to attach to the outside of DOTS, because metavariables can't
177bind to that; not good for isomorphisms *)
178
179 let dots f k d =
180 let multibind l =
181 let rec loop = function
182 [] -> option_default
183 | [x] -> x
184 | x::xs -> bind x (loop xs) in
185 loop l in
186
187 match Ast0.unwrap d with
188 Ast0.DOTS(l) -> multibind (List.map f l)
189 | Ast0.CIRCLES(l) -> multibind (List.map f l)
190 | Ast0.STARS(l) -> multibind (List.map f l) in
191
b1b2de81
C
192 let edots r k d = dots r.VT0.combiner_rec_expression k d in
193 let idots r k d = dots r.VT0.combiner_rec_initialiser k d in
194 let pdots r k d = dots r.VT0.combiner_rec_parameter k d in
195 let sdots r k d = dots r.VT0.combiner_rec_statement k d in
196 let ddots r k d = dots r.VT0.combiner_rec_declaration k d in
197 let cdots r k d = dots r.VT0.combiner_rec_case_line k d in
34e49164
C
198
199 (* a case for everything that has a Opt *)
200
201 let statement r k s =
202 (*
203 let redo_branched res (ifinfo,aftmc) =
204 let redo fv info mc rest =
205 let new_info = {info with Ast0.attachable_end = false} in
206 List.rev ((Favored,ifinfo,aftmc)::(fv,new_info,mc)::rest) in
207 match List.rev res with
208 [(fv,info,mc)] ->
209 (match mc with
210 Ast0.MINUS(_) | Ast0.CONTEXT(_) ->
211 (* even for -, better for isos not to integrate code after an
212 if into the if body.
213 but the problem is that this can extend the region in
214 which a variable is bound, because a variable bound in the
215 aft node would seem to have to be live in the whole if,
216 whereas we might like it to be live in only one branch.
217 ie ideally, if we can keep the minus code in the right
218 order, we would like to drop it as close to the bindings
219 of its free variables. This could be anywhere in the minus
220 code. Perhaps we would like to do this after the
221 application of isomorphisms, though.
222 *)
223 redo fv info mc []
224 | _ -> res)
225 | (fv,info,mc)::rest ->
226 (match mc with
227 Ast0.CONTEXT(_) -> redo fv info mc rest
228 | _ -> res)
229 | _ -> failwith "unexpected empty code" in *)
230 match Ast0.unwrap s with
231 (* Ast0.IfThen(_,_,_,_,_,aft)
232 | Ast0.IfThenElse(_,_,_,_,_,_,_,aft)
233 | Ast0.While(_,_,_,_,_,aft)
234 | Ast0.For(_,_,_,_,_,_,_,_,_,aft)
235 | Ast0.Iterator(_,_,_,_,_,aft) ->
236 redo_branched (do_nothing r k s) aft*)
237 | Ast0.FunDecl((info,bef),fninfo,name,lp,params,rp,lbrace,body,rbrace) ->
238 (Toplevel,info,bef)::(k s)
239 | Ast0.Decl((info,bef),decl) -> (Decl,info,bef)::(k s)
240 | Ast0.Nest(starter,stmt_dots,ender,whencode,multi) ->
b1b2de81
C
241 mcode starter @ r.VT0.combiner_rec_statement_dots stmt_dots @
242 mcode ender
34e49164
C
243 | Ast0.Dots(d,whencode) | Ast0.Circles(d,whencode)
244 | Ast0.Stars(d,whencode) -> mcode d (* ignore whencode *)
245 | Ast0.OptStm s | Ast0.UniqueStm s ->
246 (* put the + code on the thing, not on the opt *)
b1b2de81 247 r.VT0.combiner_rec_statement s
34e49164
C
248 | _ -> do_nothing r k s in
249
250 let expression r k e =
251 match Ast0.unwrap e with
252 Ast0.NestExpr(starter,expr_dots,ender,whencode,multi) ->
253 mcode starter @
b1b2de81 254 r.VT0.combiner_rec_expression_dots expr_dots @ mcode ender
34e49164
C
255 | Ast0.Edots(d,whencode) | Ast0.Ecircles(d,whencode)
256 | Ast0.Estars(d,whencode) -> mcode d (* ignore whencode *)
257 | Ast0.OptExp e | Ast0.UniqueExp e ->
258 (* put the + code on the thing, not on the opt *)
b1b2de81 259 r.VT0.combiner_rec_expression e
34e49164
C
260 | _ -> do_nothing r k e in
261
262 let ident r k e =
263 match Ast0.unwrap e with
264 Ast0.OptIdent i | Ast0.UniqueIdent i ->
265 (* put the + code on the thing, not on the opt *)
b1b2de81 266 r.VT0.combiner_rec_ident i
34e49164
C
267 | _ -> do_nothing r k e in
268
269 let typeC r k e =
270 match Ast0.unwrap e with
271 Ast0.OptType t | Ast0.UniqueType t ->
272 (* put the + code on the thing, not on the opt *)
b1b2de81 273 r.VT0.combiner_rec_typeC t
34e49164
C
274 | _ -> do_nothing r k e in
275
276 let decl r k e =
277 match Ast0.unwrap e with
278 Ast0.OptDecl d | Ast0.UniqueDecl d ->
279 (* put the + code on the thing, not on the opt *)
b1b2de81 280 r.VT0.combiner_rec_declaration d
34e49164
C
281 | _ -> do_nothing r k e in
282
283 let initialiser r k e =
284 match Ast0.unwrap e with
285 Ast0.Idots(d,whencode) -> mcode d (* ignore whencode *)
286 | Ast0.OptIni i | Ast0.UniqueIni i ->
287 (* put the + code on the thing, not on the opt *)
b1b2de81 288 r.VT0.combiner_rec_initialiser i
34e49164
C
289 | _ -> do_nothing r k e in
290
291 let param r k e =
292 match Ast0.unwrap e with
293 Ast0.OptParam p | Ast0.UniqueParam p ->
294 (* put the + code on the thing, not on the opt *)
b1b2de81 295 r.VT0.combiner_rec_parameter p
34e49164
C
296 | _ -> do_nothing r k e in
297
298 let case_line r k e =
299 match Ast0.unwrap e with
300 Ast0.OptCase c ->
301 (* put the + code on the thing, not on the opt *)
b1b2de81 302 r.VT0.combiner_rec_case_line c
34e49164
C
303 | _ -> do_nothing r k e in
304
305 let do_top r k (e: Ast0.top_level) = k e in
306
b1b2de81 307 V0.flat_combiner bind option_default
34e49164 308 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
34e49164
C
309 edots idots pdots sdots ddots cdots
310 ident expression typeC initialiser param decl statement case_line do_top
311
312
313let call_collect_minus context_nodes :
314 (int * (minus_join_point * Ast0.info * Ast0.mcodekind) list) list =
315 List.map
316 (function e ->
317 match e with
318 Ast0.DotsExprTag(e) ->
319 (Ast0.get_index e,
b1b2de81 320 (collect_minus_join_points e).VT0.combiner_rec_expression_dots e)
34e49164
C
321 | Ast0.DotsInitTag(e) ->
322 (Ast0.get_index e,
b1b2de81 323 (collect_minus_join_points e).VT0.combiner_rec_initialiser_list e)
34e49164
C
324 | Ast0.DotsParamTag(e) ->
325 (Ast0.get_index e,
b1b2de81 326 (collect_minus_join_points e).VT0.combiner_rec_parameter_list e)
34e49164
C
327 | Ast0.DotsStmtTag(e) ->
328 (Ast0.get_index e,
b1b2de81 329 (collect_minus_join_points e).VT0.combiner_rec_statement_dots e)
34e49164
C
330 | Ast0.DotsDeclTag(e) ->
331 (Ast0.get_index e,
b1b2de81 332 (collect_minus_join_points e).VT0.combiner_rec_declaration_dots e)
34e49164
C
333 | Ast0.DotsCaseTag(e) ->
334 (Ast0.get_index e,
b1b2de81 335 (collect_minus_join_points e).VT0.combiner_rec_case_line_dots e)
34e49164
C
336 | Ast0.IdentTag(e) ->
337 (Ast0.get_index e,
b1b2de81 338 (collect_minus_join_points e).VT0.combiner_rec_ident e)
34e49164
C
339 | Ast0.ExprTag(e) ->
340 (Ast0.get_index e,
b1b2de81 341 (collect_minus_join_points e).VT0.combiner_rec_expression e)
34e49164
C
342 | Ast0.ArgExprTag(e) | Ast0.TestExprTag(e) ->
343 failwith "not possible - iso only"
344 | Ast0.TypeCTag(e) ->
345 (Ast0.get_index e,
b1b2de81 346 (collect_minus_join_points e).VT0.combiner_rec_typeC e)
34e49164
C
347 | Ast0.ParamTag(e) ->
348 (Ast0.get_index e,
b1b2de81 349 (collect_minus_join_points e).VT0.combiner_rec_parameter e)
34e49164
C
350 | Ast0.InitTag(e) ->
351 (Ast0.get_index e,
b1b2de81 352 (collect_minus_join_points e).VT0.combiner_rec_initialiser e)
34e49164
C
353 | Ast0.DeclTag(e) ->
354 (Ast0.get_index e,
b1b2de81 355 (collect_minus_join_points e).VT0.combiner_rec_declaration e)
34e49164
C
356 | Ast0.StmtTag(e) ->
357 (Ast0.get_index e,
b1b2de81 358 (collect_minus_join_points e).VT0.combiner_rec_statement e)
34e49164
C
359 | Ast0.CaseLineTag(e) ->
360 (Ast0.get_index e,
b1b2de81 361 (collect_minus_join_points e).VT0.combiner_rec_case_line e)
34e49164
C
362 | Ast0.TopTag(e) ->
363 (Ast0.get_index e,
b1b2de81 364 (collect_minus_join_points e).VT0.combiner_rec_top_level e)
34e49164 365 | Ast0.IsoWhenTag(_) -> failwith "only within iso phase"
1be43e12
C
366 | Ast0.IsoWhenTTag(_) -> failwith "only within iso phase"
367 | Ast0.IsoWhenFTag(_) -> failwith "only within iso phase"
34e49164
C
368 | Ast0.MetaPosTag(p) -> failwith "metapostag only within iso phase")
369 context_nodes
370
371(* result of collecting the join points should be sorted in nondecreasing
372 order by line *)
373let verify l =
374 let get_info = function
375 (Favored,info,_) | (Unfavored,info,_) | (Toplevel,info,_)
376 | (Decl,info,_) -> info in
0708f913
C
377 let token_start_line x = (get_info x).Ast0.pos_info.Ast0.logical_start in
378 let token_end_line x = (get_info x).Ast0.pos_info.Ast0.logical_end in
379 let token_real_start_line x = (get_info x).Ast0.pos_info.Ast0.line_start in
380 let token_real_end_line x = (get_info x).Ast0.pos_info.Ast0.line_end in
34e49164
C
381 List.iter
382 (function
383 (index,((_::_) as l1)) ->
384 let _ =
385 List.fold_left
386 (function (prev,real_prev) ->
387 function cur ->
388 let ln = token_start_line cur in
389 if ln < prev
390 then
391 failwith
392 (Printf.sprintf
7f004419 393 "error in collection of - tokens: line %d less than line %d"
34e49164
C
394 (token_real_start_line cur) real_prev);
395 (token_end_line cur,token_real_end_line cur))
396 (token_end_line (List.hd l1), token_real_end_line (List.hd l1))
397 (List.tl l1) in
398 ()
399 | _ -> ()) (* dots, in eg f() has no join points *)
400 l
401
402let process_minus minus =
403 create_root_token_table minus;
404 List.concat
405 (List.map
406 (function x ->
407 let res = call_collect_minus (collect_context x) in
408 verify res;
409 res)
410 minus)
411
412(* --------------------------------------------------------------------- *)
413(* --------------------------------------------------------------------- *)
414(* collect the plus tokens *)
415
34e49164
C
416let mk_structUnion x = Ast.StructUnionTag x
417let mk_sign x = Ast.SignTag x
418let mk_ident x = Ast.IdentTag (Ast0toast.ident x)
419let mk_expression x = Ast.ExpressionTag (Ast0toast.expression x)
420let mk_constant x = Ast.ConstantTag x
421let mk_unaryOp x = Ast.UnaryOpTag x
422let mk_assignOp x = Ast.AssignOpTag x
423let mk_fixOp x = Ast.FixOpTag x
424let mk_binaryOp x = Ast.BinaryOpTag x
425let mk_arithOp x = Ast.ArithOpTag x
426let mk_logicalOp x = Ast.LogicalOpTag x
427let mk_declaration x = Ast.DeclarationTag (Ast0toast.declaration x)
428let mk_topdeclaration x = Ast.DeclarationTag (Ast0toast.declaration x)
429let mk_storage x = Ast.StorageTag x
430let mk_inc_file x = Ast.IncFileTag x
431let mk_statement x = Ast.StatementTag (Ast0toast.statement x)
432let mk_case_line x = Ast.CaseLineTag (Ast0toast.case_line x)
433let mk_const_vol x = Ast.ConstVolTag x
434let mk_token x info = Ast.Token (x,Some info)
435let mk_meta (_,x) info = Ast.Token (x,Some info)
436let mk_code x = Ast.Code (Ast0toast.top_level x)
437
438let mk_exprdots x = Ast.ExprDotsTag (Ast0toast.expression_dots x)
439let mk_paramdots x = Ast.ParamDotsTag (Ast0toast.parameter_list x)
440let mk_stmtdots x = Ast.StmtDotsTag (Ast0toast.statement_dots x)
441let mk_decldots x = Ast.DeclDotsTag (Ast0toast.declaration_dots x)
442let mk_casedots x = failwith "+ case lines not supported"
443let mk_typeC x = Ast.FullTypeTag (Ast0toast.typeC x)
444let mk_init x = Ast.InitTag (Ast0toast.initialiser x)
445let mk_param x = Ast.ParamTag (Ast0toast.parameterTypeDef x)
446
447let collect_plus_nodes root =
448 let root_index = Ast0.get_index root in
449
450 let bind x y = x @ y in
451 let option_default = [] in
452
0708f913
C
453 let extract_strings info =
454 let adjust_info =
455 {info with Ast0.strings_before = []; Ast0.strings_after = []} in
456 let extract = function
457 [] -> []
458 | strings_before ->
459 let (_,first) = List.hd strings_before in
460 let (_,last) = List.hd (List.rev strings_before) in
461 let new_pos_info =
462 {Ast0.line_start = first.Ast0.line_start;
463 Ast0.line_end = last.Ast0.line_start;
464 Ast0.logical_start = first.Ast0.logical_start;
465 Ast0.logical_end = last.Ast0.logical_start;
466 Ast0.column = first.Ast0.column;
467 Ast0.offset = first.Ast0.offset} in
468 let new_info = {adjust_info with Ast0.pos_info = new_pos_info} in
469 let string = List.map (function (s,_) -> s) strings_before in
951c7801 470 [(new_info,Ast.ONE(*?*),Ast.Pragma (string))] in
0708f913
C
471 let bef = extract info.Ast0.strings_before in
472 let aft = extract info.Ast0.strings_after in
473 (bef,aft) in
474
708f4980 475 let mcode fn (term,_,info,mcodekind,_,_) =
0708f913 476 match mcodekind with
951c7801 477 Ast0.PLUS c -> [(info,c,fn term)]
0708f913
C
478 | Ast0.CONTEXT _ -> let (bef,aft) = extract_strings info in bef@aft
479 | _ -> [] in
34e49164 480
708f4980 481 let imcode fn (term,_,info,mcodekind,_,_) =
34e49164 482 match mcodekind with
951c7801 483 Ast0.PLUS c -> [(info,c,fn term (Ast0toast.convert_info info))]
0708f913 484 | Ast0.CONTEXT _ -> let (bef,aft) = extract_strings info in bef@aft
34e49164
C
485 | _ -> [] in
486
0708f913
C
487 let info (i,_) = let (bef,aft) = extract_strings i in bef@aft in
488
34e49164
C
489 let do_nothing fn r k e =
490 match Ast0.get_mcodekind e with
491 (Ast0.CONTEXT(_)) when not(Ast0.get_index e = root_index) -> []
951c7801 492 | Ast0.PLUS c -> [(Ast0.get_info e,c,fn e)]
34e49164
C
493 | _ -> k e in
494
495 (* case for everything that is just a wrapper for a simpler thing *)
0708f913 496 (* case for things with bef aft *)
34e49164
C
497 let stmt r k e =
498 match Ast0.unwrap e with
b1b2de81
C
499 Ast0.Exp(exp) -> r.VT0.combiner_rec_expression exp
500 | Ast0.TopExp(exp) -> r.VT0.combiner_rec_expression exp
501 | Ast0.Ty(ty) -> r.VT0.combiner_rec_typeC ty
502 | Ast0.TopInit(init) -> r.VT0.combiner_rec_initialiser init
0708f913
C
503 | Ast0.Decl(bef,decl) ->
504 (info bef) @ (do_nothing mk_statement r k e)
505 | Ast0.FunDecl(bef,fi,name,lp,params,rp,lbrace,body,rbrace) ->
506 (info bef) @ (do_nothing mk_statement r k e)
507 | Ast0.IfThen(iff,lp,exp,rp,branch1,aft) ->
508 (do_nothing mk_statement r k e) @ (info aft)
509 | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,aft) ->
510 (do_nothing mk_statement r k e) @ (info aft)
511 | Ast0.While(whl,lp,exp,rp,body,aft) ->
512 (do_nothing mk_statement r k e) @ (info aft)
513 | Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,aft) ->
514 (do_nothing mk_statement r k e) @ (info aft)
515 | Ast0.Iterator(nm,lp,args,rp,body,aft) ->
516 (do_nothing mk_statement r k e) @ (info aft)
34e49164
C
517 | _ -> do_nothing mk_statement r k e in
518
519 (* statementTag is preferred, because it indicates that one statement is
520 replaced by one statement, in single_statement *)
521 let stmt_dots r k e =
522 match Ast0.unwrap e with
523 Ast0.DOTS([s]) | Ast0.CIRCLES([s]) | Ast0.STARS([s]) ->
b1b2de81 524 r.VT0.combiner_rec_statement s
34e49164
C
525 | _ -> do_nothing mk_stmtdots r k e in
526
527 let toplevel r k e =
528 match Ast0.unwrap e with
b1b2de81
C
529 Ast0.DECL(s) -> r.VT0.combiner_rec_statement s
530 | Ast0.CODE(sdots) -> r.VT0.combiner_rec_statement_dots sdots
34e49164
C
531 | _ -> do_nothing mk_code r k e in
532
533 let initdots r k e = k e in
534
b1b2de81 535 V0.flat_combiner bind option_default
34e49164
C
536 (imcode mk_meta) (imcode mk_token) (mcode mk_constant) (mcode mk_assignOp)
537 (mcode mk_fixOp)
538 (mcode mk_unaryOp) (mcode mk_binaryOp) (mcode mk_const_vol)
faf9a90c 539 (mcode mk_sign) (mcode mk_structUnion)
34e49164
C
540 (mcode mk_storage) (mcode mk_inc_file)
541 (do_nothing mk_exprdots) initdots
542 (do_nothing mk_paramdots) stmt_dots (do_nothing mk_decldots)
543 (do_nothing mk_casedots)
544 (do_nothing mk_ident) (do_nothing mk_expression)
545 (do_nothing mk_typeC) (do_nothing mk_init) (do_nothing mk_param)
546 (do_nothing mk_declaration)
547 stmt (do_nothing mk_case_line) toplevel
548
549let call_collect_plus context_nodes :
951c7801 550 (int * (Ast0.info * Ast.count * Ast.anything) list) list =
34e49164
C
551 List.map
552 (function e ->
553 match e with
554 Ast0.DotsExprTag(e) ->
555 (Ast0.get_index e,
b1b2de81 556 (collect_plus_nodes e).VT0.combiner_rec_expression_dots e)
34e49164
C
557 | Ast0.DotsInitTag(e) ->
558 (Ast0.get_index e,
b1b2de81 559 (collect_plus_nodes e).VT0.combiner_rec_initialiser_list e)
34e49164
C
560 | Ast0.DotsParamTag(e) ->
561 (Ast0.get_index e,
b1b2de81 562 (collect_plus_nodes e).VT0.combiner_rec_parameter_list e)
34e49164
C
563 | Ast0.DotsStmtTag(e) ->
564 (Ast0.get_index e,
b1b2de81 565 (collect_plus_nodes e).VT0.combiner_rec_statement_dots e)
34e49164
C
566 | Ast0.DotsDeclTag(e) ->
567 (Ast0.get_index e,
b1b2de81 568 (collect_plus_nodes e).VT0.combiner_rec_declaration_dots e)
34e49164
C
569 | Ast0.DotsCaseTag(e) ->
570 (Ast0.get_index e,
b1b2de81 571 (collect_plus_nodes e).VT0.combiner_rec_case_line_dots e)
34e49164
C
572 | Ast0.IdentTag(e) ->
573 (Ast0.get_index e,
b1b2de81 574 (collect_plus_nodes e).VT0.combiner_rec_ident e)
34e49164
C
575 | Ast0.ExprTag(e) ->
576 (Ast0.get_index e,
b1b2de81 577 (collect_plus_nodes e).VT0.combiner_rec_expression e)
34e49164
C
578 | Ast0.ArgExprTag(_) | Ast0.TestExprTag(_) ->
579 failwith "not possible - iso only"
580 | Ast0.TypeCTag(e) ->
581 (Ast0.get_index e,
b1b2de81 582 (collect_plus_nodes e).VT0.combiner_rec_typeC e)
34e49164
C
583 | Ast0.InitTag(e) ->
584 (Ast0.get_index e,
b1b2de81 585 (collect_plus_nodes e).VT0.combiner_rec_initialiser e)
34e49164
C
586 | Ast0.ParamTag(e) ->
587 (Ast0.get_index e,
b1b2de81 588 (collect_plus_nodes e).VT0.combiner_rec_parameter e)
34e49164
C
589 | Ast0.DeclTag(e) ->
590 (Ast0.get_index e,
b1b2de81 591 (collect_plus_nodes e).VT0.combiner_rec_declaration e)
34e49164
C
592 | Ast0.StmtTag(e) ->
593 (Ast0.get_index e,
b1b2de81 594 (collect_plus_nodes e).VT0.combiner_rec_statement e)
34e49164
C
595 | Ast0.CaseLineTag(e) ->
596 (Ast0.get_index e,
b1b2de81 597 (collect_plus_nodes e).VT0.combiner_rec_case_line e)
34e49164
C
598 | Ast0.TopTag(e) ->
599 (Ast0.get_index e,
b1b2de81 600 (collect_plus_nodes e).VT0.combiner_rec_top_level e)
34e49164 601 | Ast0.IsoWhenTag(_) -> failwith "only within iso phase"
1be43e12
C
602 | Ast0.IsoWhenTTag(_) -> failwith "only within iso phase"
603 | Ast0.IsoWhenFTag(_) -> failwith "only within iso phase"
34e49164
C
604 | Ast0.MetaPosTag(p) -> failwith "metapostag only within iso phase")
605 context_nodes
606
607(* The plus fragments are converted to a list of lists of lists.
608Innermost list: Elements have type anything. For any pair of successive
609elements, n and n+1, the ending line of n is the same as the starting line
610of n+1.
611Middle lists: For any pair of successive elements, n and n+1, the ending
612line of n is one less than the starting line of n+1.
613Outer list: For any pair of successive elements, n and n+1, the ending
614line of n is more than one less than the starting line of n+1. *)
615
0708f913
C
616let logstart info = info.Ast0.pos_info.Ast0.logical_start
617let logend info = info.Ast0.pos_info.Ast0.logical_end
34e49164
C
618
619let redo info start finish =
0708f913
C
620 let new_pos_info =
621 {info.Ast0.pos_info with
622 Ast0.logical_start = start;
623 Ast0.logical_end = finish} in
624 {info with Ast0.pos_info = new_pos_info}
34e49164
C
625
626let rec find_neighbors (index,l) :
951c7801 627 int * (Ast0.info * Ast.count * (Ast.anything list list)) list =
34e49164
C
628 let rec loop = function
629 [] -> []
951c7801 630 | (i,c,x)::rest ->
34e49164 631 (match loop rest with
951c7801 632 ((i1,c1,(x1::rest_inner))::rest_middle)::rest_outer ->
34e49164
C
633 let finish1 = logend i in
634 let start2 = logstart i1 in
635 if finish1 = start2
636 then
951c7801
C
637 ((if not (c = c1) then failwith "inconsistent + code");
638 ((redo i (logstart i) (logend i1),c,(x::x1::rest_inner))
34e49164 639 ::rest_middle)
951c7801 640 ::rest_outer)
34e49164 641 else if finish1 + 1 = start2
951c7801
C
642 then ((i,c,[x])::(i1,c1,(x1::rest_inner))::rest_middle)::rest_outer
643 else
644 [(i,c,[x])]::((i1,c1,(x1::rest_inner))::rest_middle)::rest_outer
645 | _ -> [[(i,c,[x])]]) (* rest must be [] *) in
34e49164
C
646 let res =
647 List.map
648 (function l ->
951c7801
C
649 let (start_info,start_count,_) = List.hd l in
650 let (end_info,end_count,_) = List.hd (List.rev l) in
651 (if not (start_count = end_count) then failwith "inconsistent + code");
34e49164 652 (redo start_info (logstart start_info) (logend end_info),
951c7801
C
653 start_count,
654 List.map (function (_,_,x) -> x) l))
34e49164
C
655 (loop l) in
656 (index,res)
657
658let process_plus plus :
951c7801 659 (int * (Ast0.info * Ast.count * Ast.anything list list) list) list =
34e49164
C
660 List.concat
661 (List.map
662 (function x ->
663 List.map find_neighbors (call_collect_plus (collect_context x)))
664 plus)
665
666(* --------------------------------------------------------------------- *)
667(* --------------------------------------------------------------------- *)
668(* merge *)
669(*
670let merge_one = function
671 (m1::m2::minus_info,p::plus_info) ->
672 if p < m1, then
673 attach p to the beginning of m1.bef if m1 is Good, fail if it is bad
674 if p > m1 && p < m2, then consider the following possibilities, in order
675 m1 is Good and favored: attach to the beginning of m1.aft
676 m2 is Good and favored: attach to the beginning of m2.bef; drop m1
677 m1 is Good and unfavored: attach to the beginning of m1.aft
678 m2 is Good and unfavored: attach to the beginning of m2.bef; drop m1
679 also flip m1.bef if the first where > m1
680 if we drop m1, then flip m1.aft first
681 if p > m2
682 m2 is Good and favored: attach to the beginning of m2.aft; drop m1
683*)
684
685(* end of first argument < start/end of second argument *)
686let less_than_start info1 info2 =
0708f913 687 info1.Ast0.pos_info.Ast0.logical_end < info2.Ast0.pos_info.Ast0.logical_start
34e49164 688let less_than_end info1 info2 =
0708f913 689 info1.Ast0.pos_info.Ast0.logical_end < info2.Ast0.pos_info.Ast0.logical_end
34e49164 690let greater_than_end info1 info2 =
0708f913 691 info1.Ast0.pos_info.Ast0.logical_start > info2.Ast0.pos_info.Ast0.logical_end
34e49164
C
692let good_start info = info.Ast0.attachable_start
693let good_end info = info.Ast0.attachable_end
694
695let toplevel = function Toplevel -> true | Favored | Unfavored | Decl -> false
696let decl = function Decl -> true | Favored | Unfavored | Toplevel -> false
697let favored = function Favored -> true | Unfavored | Toplevel | Decl -> false
698
699let top_code =
700 List.for_all (List.for_all (function Ast.Code _ -> true | _ -> false))
701
702(* The following is probably not correct. The idea is to detect what
703should be placed completely before the declaration. So type/storage
704related things do not fall into this category, and complete statements do
705fall into this category. But perhaps other things should be in this
706category as well, such as { or ;? *)
707let predecl_code =
708 let tester = function
709 (* the following should definitely be true *)
710 Ast.DeclarationTag _
711 | Ast.StatementTag _
712 | Ast.Rule_elemTag _
713 | Ast.StmtDotsTag _
0708f913
C
714 | Ast.Code _
715 | Ast.Pragma _ -> true
34e49164
C
716 (* the following should definitely be false *)
717 | Ast.FullTypeTag _ | Ast.BaseTypeTag _ | Ast.StructUnionTag _
718 | Ast.SignTag _
719 | Ast.StorageTag _ | Ast.ConstVolTag _ | Ast.TypeCTag _ -> false
720 (* not sure about the rest *)
721 | _ -> false in
722 List.for_all (List.for_all tester)
723
724let pr = Printf.sprintf
725
726let insert thing thinginfo into intoinfo =
727 let get_last l = let l = List.rev l in (List.rev(List.tl l),List.hd l) in
728 let get_first l = (List.hd l,List.tl l) in
0708f913
C
729 let thing_start = thinginfo.Ast0.pos_info.Ast0.logical_start in
730 let thing_end = thinginfo.Ast0.pos_info.Ast0.logical_end in
731 let thing_offset = thinginfo.Ast0.pos_info.Ast0.offset in
34e49164
C
732 let into_start = intoinfo.Ast0.tline_start in
733 let into_end = intoinfo.Ast0.tline_end in
734 let into_left_offset = intoinfo.Ast0.left_offset in
735 let into_right_offset = intoinfo.Ast0.right_offset in
34e49164
C
736 if thing_end < into_start && thing_start < into_start
737 then (thing@into,
738 {{intoinfo with Ast0.tline_start = thing_start}
739 with Ast0.left_offset = thing_offset})
740 else if thing_end = into_start && thing_offset < into_left_offset
741 then
742 let (prev,last) = get_last thing in
743 let (first,rest) = get_first into in
744 (prev@[last@first]@rest,
745 {{intoinfo with Ast0.tline_start = thing_start}
746 with Ast0.left_offset = thing_offset})
747 else if thing_start > into_end && thing_end > into_end
748 then (into@thing,
749 {{intoinfo with Ast0.tline_end = thing_end}
750 with Ast0.right_offset = thing_offset})
751 else if thing_start = into_end && thing_offset > into_right_offset
752 then
753 let (first,rest) = get_first thing in
754 let (prev,last) = get_last into in
755 (prev@[last@first]@rest,
756 {{intoinfo with Ast0.tline_end = thing_end}
757 with Ast0.right_offset = thing_offset})
758 else
759 begin
760 Printf.printf "thing start %d thing end %d into start %d into end %d\n"
761 thing_start thing_end into_start into_end;
762 Printf.printf "thing offset %d left offset %d right offset %d\n"
763 thing_offset into_left_offset into_right_offset;
764 Pretty_print_cocci.print_anything "" thing;
1be43e12 765 Pretty_print_cocci.print_anything "" into;
34e49164
C
766 failwith "can't figure out where to put the + code"
767 end
768
769let init thing info =
770 (thing,
0708f913
C
771 {Ast0.tline_start = info.Ast0.pos_info.Ast0.logical_start;
772 Ast0.tline_end = info.Ast0.pos_info.Ast0.logical_end;
773 Ast0.left_offset = info.Ast0.pos_info.Ast0.offset;
774 Ast0.right_offset = info.Ast0.pos_info.Ast0.offset})
34e49164 775
951c7801 776let attachbefore (infop,c,p) = function
34e49164 777 Ast0.MINUS(replacements) ->
951c7801
C
778 let (repl,ti) = !replacements in
779 let (bef,ti) =
780 match repl with
781 [] -> init p infop
782 | repl -> insert p infop repl ti in
783 replacements := (bef,ti)
34e49164
C
784 | Ast0.CONTEXT(neighbors) ->
785 let (repl,ti1,ti2) = !neighbors in
786 (match repl with
951c7801 787 Ast.BEFORE(bef,it) ->
34e49164 788 let (bef,ti1) = insert p infop bef ti1 in
951c7801
C
789 let it = Ast.lub_count it c in
790 neighbors := (Ast.BEFORE(bef,it),ti1,ti2)
791 | Ast.AFTER(aft,it) ->
34e49164 792 let (bef,ti1) = init p infop in
951c7801
C
793 let it = Ast.lub_count it c in
794 neighbors := (Ast.BEFOREAFTER(bef,aft,it),ti1,ti2)
795 | Ast.BEFOREAFTER(bef,aft,it) ->
34e49164 796 let (bef,ti1) = insert p infop bef ti1 in
951c7801
C
797 let it = Ast.lub_count it c in
798 neighbors := (Ast.BEFOREAFTER(bef,aft,it),ti1,ti2)
34e49164
C
799 | Ast.NOTHING ->
800 let (bef,ti1) = init p infop in
951c7801 801 neighbors := (Ast.BEFORE(bef,c),ti1,ti2))
34e49164
C
802 | _ -> failwith "not possible for attachbefore"
803
951c7801 804let attachafter (infop,c,p) = function
34e49164 805 Ast0.MINUS(replacements) ->
951c7801
C
806 let (repl,ti) = !replacements in
807 let (aft,ti) =
808 match repl with
809 [] -> init p infop
810 | repl -> insert p infop repl ti in
811 replacements := (aft,ti)
34e49164
C
812 | Ast0.CONTEXT(neighbors) ->
813 let (repl,ti1,ti2) = !neighbors in
814 (match repl with
951c7801 815 Ast.BEFORE(bef,it) ->
34e49164 816 let (aft,ti2) = init p infop in
951c7801
C
817 let it = Ast.lub_count it c in
818 neighbors := (Ast.BEFOREAFTER(bef,aft,it),ti1,ti2)
819 | Ast.AFTER(aft,it) ->
34e49164 820 let (aft,ti2) = insert p infop aft ti2 in
951c7801
C
821 let it = Ast.lub_count it c in
822 neighbors := (Ast.AFTER(aft,it),ti1,ti2)
823 | Ast.BEFOREAFTER(bef,aft,it) ->
34e49164 824 let (aft,ti2) = insert p infop aft ti2 in
951c7801
C
825 let it = Ast.lub_count it c in
826 neighbors := (Ast.BEFOREAFTER(bef,aft,it),ti1,ti2)
34e49164
C
827 | Ast.NOTHING ->
828 let (aft,ti2) = init p infop in
951c7801 829 neighbors := (Ast.AFTER(aft,c),ti1,ti2))
34e49164
C
830 | _ -> failwith "not possible for attachbefore"
831
832let attach_all_before ps m =
833 List.iter (function x -> attachbefore x m) ps
834
835let attach_all_after ps m =
836 List.iter (function x -> attachafter x m) ps
837
838let split_at_end info ps =
0708f913 839 let split_point = info.Ast0.pos_info.Ast0.logical_end in
34e49164 840 List.partition
951c7801 841 (function (info,_,_) -> info.Ast0.pos_info.Ast0.logical_end < split_point)
34e49164
C
842 ps
843
844let allminus = function
845 Ast0.MINUS(_) -> true
846 | _ -> false
847
848let rec before_m1 ((f1,infom1,m1) as x1) ((f2,infom2,m2) as x2) rest = function
849 [] -> ()
951c7801 850 | (((infop,_,_) as p) :: ps) as all ->
34e49164
C
851 if less_than_start infop infom1 or
852 (allminus m1 && less_than_end infop infom1) (* account for trees *)
853 then
854 if good_start infom1
855 then (attachbefore p m1; before_m1 x1 x2 rest ps)
856 else
857 failwith
0708f913
C
858 (pr "%d: no available token to attach to"
859 infop.Ast0.pos_info.Ast0.line_start)
34e49164
C
860 else after_m1 x1 x2 rest all
861
862and after_m1 ((f1,infom1,m1) as x1) ((f2,infom2,m2) as x2) rest = function
863 [] -> ()
951c7801 864 | (((infop,count,pcode) as p) :: ps) as all ->
34e49164
C
865 (* if the following is false, then some + code is stuck in the middle
866 of some context code (m1). could drop down to the token level.
867 this might require adjustments in ast0toast as well, when + code on
868 expressions is dropped down to + code on expressions. it might
869 also break some invariants on which iso depends, particularly on
870 what it can infer from something being CONTEXT with no top-level
871 modifications. for the moment, we thus give an error, asking the
872 user to rewrite the semantic patch. *)
faf9a90c 873 if greater_than_end infop infom1 or is_minus m1 or !empty_isos
34e49164
C
874 then
875 if less_than_start infop infom2
876 then
877 if predecl_code pcode && good_end infom1 && decl f1
878 then (attachafter p m1; after_m1 x1 x2 rest ps)
879 else if predecl_code pcode && good_start infom2 && decl f2
880 then before_m2 x2 rest all
881 else if top_code pcode && good_end infom1 && toplevel f1
882 then (attachafter p m1; after_m1 x1 x2 rest ps)
883 else if top_code pcode && good_start infom2 && toplevel f2
884 then before_m2 x2 rest all
885 else if good_end infom1 && favored f1
886 then (attachafter p m1; after_m1 x1 x2 rest ps)
887 else if good_start infom2 && favored f2
888 then before_m2 x2 rest all
889 else if good_end infom1
890 then (attachafter p m1; after_m1 x1 x2 rest ps)
891 else if good_start infom2
892 then before_m2 x2 rest all
893 else
894 failwith
0708f913
C
895 (pr "%d: no available token to attach to"
896 infop.Ast0.pos_info.Ast0.line_start)
34e49164
C
897 else after_m2 x2 rest all
898 else
899 begin
900 Printf.printf "between: p start %d p end %d m1 start %d m1 end %d m2 start %d m2 end %d\n"
0708f913
C
901 infop.Ast0.pos_info.Ast0.line_start
902 infop.Ast0.pos_info.Ast0.line_end
903 infom1.Ast0.pos_info.Ast0.line_start
904 infom1.Ast0.pos_info.Ast0.line_end
905 infom2.Ast0.pos_info.Ast0.line_start
906 infom2.Ast0.pos_info.Ast0.line_end;
34e49164
C
907 Pretty_print_cocci.print_anything "" pcode;
908 failwith
909 "The semantic patch is structured in a way that may give bad results with isomorphisms. Please try to rewrite it by moving + code out from -/context terms."
910 end
911
faf9a90c
C
912(* not sure this is safe. if have iso problems, consider changing this
913to always return false *)
914and is_minus = function
915 Ast0.MINUS _ -> true
916 | _ -> false
917
34e49164 918and before_m2 ((f2,infom2,m2) as x2) rest
951c7801 919 (p : (Ast0.info * Ast.count * Ast.anything list list) list) =
34e49164
C
920 match (rest,p) with
921 (_,[]) -> ()
951c7801 922 | ([],((infop,_,_)::_)) ->
34e49164
C
923 let (bef_m2,aft_m2) = split_at_end infom2 p in (* bef_m2 isn't empty *)
924 if good_start infom2
925 then (attach_all_before bef_m2 m2; after_m2 x2 rest aft_m2)
926 else
927 failwith
0708f913
C
928 (pr "%d: no available token to attach to"
929 infop.Ast0.pos_info.Ast0.line_start)
34e49164
C
930 | (m::ms,_) -> before_m1 x2 m ms p
931
932and after_m2 ((f2,infom2,m2) as x2) rest
951c7801 933 (p : (Ast0.info * Ast.count * Ast.anything list list) list) =
34e49164
C
934 match (rest,p) with
935 (_,[]) -> ()
951c7801 936 | ([],((infop,_,_)::_)) ->
34e49164
C
937 if good_end infom2
938 then attach_all_after p m2
939 else
940 failwith
0708f913
C
941 (pr "%d: no available token to attach to"
942 infop.Ast0.pos_info.Ast0.line_start)
34e49164
C
943 | (m::ms,_) -> after_m1 x2 m ms p
944
945let merge_one : (minus_join_point * Ast0.info * 'a) list *
951c7801
C
946 (Ast0.info * Ast.count * Ast.anything list list) list -> unit =
947 function (m,p) ->
34e49164
C
948 (*
949 Printf.printf "minus code\n";
950 List.iter
951 (function (_,info,_) ->
952 Printf.printf "start %d end %d real_start %d real_end %d\n"
0708f913
C
953 info.Ast0.pos_info.Ast0.logical_start
954 info.Ast0.pos_info.Ast0.logical_end
955 info.Ast0.pos_info.Ast0.line_start
956 info.Ast0.pos_info.Ast0.line_end)
34e49164
C
957 m;
958 Printf.printf "plus code\n";
959 List.iter
960 (function (info,p) ->
961 Printf.printf "start %d end %d real_start %d real_end %d\n"
0708f913
C
962 info.Ast0.pos_info.Ast0.logical_start
963 info.Ast0.pos_info.Ast0.logical_end
964 info.Ast0.pos_info.Ast0.line_end
965 info.Ast0.pos_info.Ast0.line_end;
34e49164
C
966 Pretty_print_cocci.print_anything "" p;
967 Format.print_newline())
968 p;
969 *)
970 match (m,p) with
971 (_,[]) -> ()
972 | (m1::m2::restm,p) -> before_m1 m1 m2 restm p
973 | ([m],p) -> before_m2 m [] p
974 | ([],_) -> failwith "minus tree ran out before the plus tree"
975
976let merge minus_list plus_list =
977 (*
978 Printf.printf "minus list %s\n"
979 (String.concat " "
980 (List.map (function (x,_) -> string_of_int x) minus_list));
981 Printf.printf "plus list %s\n"
982 (String.concat " "
983 (List.map (function (x,_) -> string_of_int x) plus_list));
984 *)
985 List.iter
986 (function (index,minus_info) ->
987 let plus_info = List.assoc index plus_list in
988 merge_one (minus_info,plus_info))
989 minus_list
990
991(* --------------------------------------------------------------------- *)
992(* --------------------------------------------------------------------- *)
993(* Need to check that CONTEXT nodes have nothing attached to their tokens.
994If they do, they become MIXED *)
995
996let reevaluate_contextness =
997 let bind = (@) in
998 let option_default = [] in
999
708f4980 1000 let mcode (_,_,_,mc,_,_) =
34e49164
C
1001 match mc with
1002 Ast0.CONTEXT(mc) -> let (ba,_,_) = !mc in [ba]
1003 | _ -> [] in
1004
0708f913
C
1005 let info (_,mc) =
1006 match mc with
1007 Ast0.CONTEXT(mc) -> let (ba,_,_) = !mc in [ba]
1008 | _ -> [] in
1009
34e49164
C
1010 let donothing r k e =
1011 match Ast0.get_mcodekind e with
1012 Ast0.CONTEXT(mc) ->
1013 if List.exists (function Ast.NOTHING -> false | _ -> true) (k e)
1014 then Ast0.set_mcodekind e (Ast0.MIXED(mc));
1015 []
1016 | _ -> let _ = k e in [] in
1017
0708f913
C
1018 (* a case for everything with bef or aft *)
1019 let stmt r k e =
1020 match Ast0.unwrap e with
1021 Ast0.Decl(bef,decl) ->
1022 (info bef) @ (donothing r k e)
1023 | Ast0.FunDecl(bef,fi,name,lp,params,rp,lbrace,body,rbrace) ->
1024 (info bef) @ (donothing r k e)
1025 | Ast0.IfThen(iff,lp,exp,rp,branch1,aft) ->
1026 (donothing r k e) @ (info aft)
1027 | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,aft) ->
1028 (donothing r k e) @ (info aft)
1029 | Ast0.While(whl,lp,exp,rp,body,aft) ->
1030 (donothing r k e) @ (info aft)
1031 | Ast0.For(fr,lp,e1,sem1,e2,sem2,e3,rp,body,aft) ->
1032 (donothing r k e) @ (info aft)
1033 | Ast0.Iterator(nm,lp,args,rp,body,aft) ->
1034 (donothing r k e) @ (info aft)
1035 | _ -> donothing r k e in
1036
34e49164 1037 let res =
b1b2de81 1038 V0.flat_combiner bind option_default
34e49164 1039 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
34e49164
C
1040 donothing donothing donothing donothing donothing donothing donothing
1041 donothing
0708f913 1042 donothing donothing donothing donothing stmt donothing donothing in
b1b2de81 1043 res.VT0.combiner_rec_top_level
34e49164
C
1044
1045(* --------------------------------------------------------------------- *)
1046(* --------------------------------------------------------------------- *)
1047
faf9a90c
C
1048let insert_plus minus plus ei =
1049 empty_isos := ei;
34e49164
C
1050 let minus_stream = process_minus minus in
1051 let plus_stream = process_plus plus in
1052 merge minus_stream plus_stream;
1053 List.iter (function x -> let _ = reevaluate_contextness x in ()) minus