Release coccinelle-0.2.4
[bpt/coccinelle.git] / parsing_cocci / unify_ast.ml
CommitLineData
9bc82bae
C
1(*
2 * Copyright 2010, INRIA, University of Copenhagen
3 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
4 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
5 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
6 * This file is part of Coccinelle.
7 *
8 * Coccinelle is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, according to version 2 of the License.
11 *
12 * Coccinelle is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * The authors reserve the right to distribute this or future versions of
21 * Coccinelle under other licenses.
22 *)
23
24
c491d8ee
C
25(*
26 * Copyright 2010, INRIA, University of Copenhagen
27 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
28 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
29 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
30 * This file is part of Coccinelle.
31 *
32 * Coccinelle is free software: you can redistribute it and/or modify
33 * it under the terms of the GNU General Public License as published by
34 * the Free Software Foundation, according to version 2 of the License.
35 *
36 * Coccinelle is distributed in the hope that it will be useful,
37 * but WITHOUT ANY WARRANTY; without even the implied warranty of
38 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39 * GNU General Public License for more details.
40 *
41 * You should have received a copy of the GNU General Public License
42 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
43 *
44 * The authors reserve the right to distribute this or future versions of
45 * Coccinelle under other licenses.
46 *)
47
48
34e49164
C
49(* --------------------------------------------------------------------- *)
50(* Given two patterns, A and B, determine whether B can match any matched
51subterms of A. For simplicity, this doesn't maintain an environment; it
52just assume metavariables match. Thus the result is either NO or MAYBE. *)
53
54module Ast = Ast_cocci
55module V = Visitor_ast
56
57(* --------------------------------------------------------------------- *)
58
59type res = NO | MAYBE
60
61let return b = if b then MAYBE else NO
62
63let unify_mcode (x,_,_,_) (y,_,_,_) = x = y
64
faf9a90c
C
65let ret_unify_mcode a b = return (unify_mcode a b)
66
34e49164
C
67let unify_option f t1 t2 =
68 match (t1,t2) with
69 (Some t1, Some t2) -> f t1 t2
70 | (None, None) -> return true
71 | _ -> return false
72
73let unify_true_option f t1 t2 =
74 match (t1,t2) with
75 (Some t1, Some t2) -> f t1 t2
76 | (None, None) -> return true
77 | _ -> return true
78
79let bool_unify_option f t1 t2 =
80 match (t1,t2) with
81 (Some t1, Some t2) -> f t1 t2
82 | (None, None) -> true
83 | _ -> false
84
85let conjunct_bindings b1 b2 =
86 match b1 with NO -> b1 | MAYBE -> b2
87
88let disjunct_bindings b1 b2 =
89 match b1 with MAYBE -> b1 | NO -> b2
90
faf9a90c 91let disjunct_all_bindings = List.fold_left disjunct_bindings NO
34e49164
C
92
93(* --------------------------------------------------------------------- *)
94
95(* compute the common prefix. if in at least one case, this ends with the
96end of the pattern or a ..., then return true. *)
97
98let unify_lists fn dfn la lb =
99 let rec loop = function
100 ([],_) | (_,[]) -> return true
101 | (cura::resta,curb::restb) ->
102 (match fn cura curb with
103 MAYBE -> loop (resta,restb)
104 | NO -> if dfn cura or dfn curb then MAYBE else NO) in
105 loop (la,lb)
106
107let unify_dots fn dfn d1 d2 =
108 match (Ast.unwrap d1,Ast.unwrap d2) with
109 (Ast.DOTS(l1),Ast.DOTS(l2))
110 | (Ast.CIRCLES(l1),Ast.CIRCLES(l2))
111 | (Ast.STARS(l1),Ast.STARS(l2)) -> unify_lists fn dfn l1 l2
112 | _ -> return false
113
114let edots e =
115 match Ast.unwrap e with
116 Ast.Edots(_,_) | Ast.Ecircles(_,_) | Ast.Estars(_,_) -> true
117 | _ -> false
118
119let ddots e =
120 match Ast.unwrap e with
121 Ast.Ddots(_,_) -> true
122 | _ -> false
123
124let pdots p =
125 match Ast.unwrap p with
126 Ast.Pdots(_) | Ast.Pcircles(_) -> true
127 | _ -> false
128
129let dpdots e =
130 match Ast.unwrap e with
131 Ast.DPdots(_) | Ast.DPcircles(_) -> true
132 | _ -> false
133
134let sdots s =
135 match Ast.unwrap s with
136 Ast.Dots(_,_,_,_) | Ast.Circles(_,_,_,_) | Ast.Stars(_,_,_,_) -> true
137 | _ -> false
138
c491d8ee
C
139let idots e =
140 match Ast.unwrap e with
141 Ast.Idots(_,_) -> true
142 | _ -> false
143
34e49164
C
144(* --------------------------------------------------------------------- *)
145(* Identifier *)
146
147and unify_ident i1 i2 =
148 match (Ast.unwrap i1,Ast.unwrap i2) with
149 (Ast.Id(i1),Ast.Id(i2)) -> return (unify_mcode i1 i2)
150
151 | (Ast.MetaId(_,_,_,_),_)
152 | (Ast.MetaFunc(_,_,_,_),_)
153 | (Ast.MetaLocalFunc(_,_,_,_),_)
154 | (_,Ast.MetaId(_,_,_,_))
155 | (_,Ast.MetaFunc(_,_,_,_))
156 | (_,Ast.MetaLocalFunc(_,_,_,_)) -> return true
157
158 | (Ast.OptIdent(_),_)
159 | (Ast.UniqueIdent(_),_)
160 | (_,Ast.OptIdent(_))
161 | (_,Ast.UniqueIdent(_)) -> failwith "unsupported ident"
162
163(* --------------------------------------------------------------------- *)
164(* Expression *)
165
166let rec unify_expression e1 e2 =
167 match (Ast.unwrap e1,Ast.unwrap e2) with
168 (Ast.Ident(i1),Ast.Ident(i2)) -> unify_ident i1 i2
169 | (Ast.Constant(c1),Ast.Constant(c2))-> return (unify_mcode c1 c2)
170 | (Ast.FunCall(f1,lp1,args1,rp1),Ast.FunCall(f2,lp2,args2,rp2)) ->
171 conjunct_bindings
172 (unify_expression f1 f2)
173 (unify_dots unify_expression edots args1 args2)
174 | (Ast.Assignment(l1,op1,r1,_),Ast.Assignment(l2,op2,r2,_)) ->
175 if unify_mcode op1 op2
176 then conjunct_bindings (unify_expression l1 l2) (unify_expression r1 r2)
177 else return false
178 | (Ast.CondExpr(tst1,q1,thn1,c1,els1),Ast.CondExpr(tst2,q2,thn2,c2,els2)) ->
179 conjunct_bindings (unify_expression tst1 tst2)
180 (conjunct_bindings (unify_option unify_expression thn1 thn2)
181 (unify_expression els1 els2))
182 | (Ast.Postfix(e1,op1),Ast.Postfix(e2,op2)) ->
183 if unify_mcode op1 op2 then unify_expression e1 e2 else return false
184 | (Ast.Infix(e1,op1),Ast.Infix(e2,op2)) ->
185 if unify_mcode op1 op2 then unify_expression e1 e2 else return false
186 | (Ast.Unary(e1,op1),Ast.Unary(e2,op2)) ->
187 if unify_mcode op1 op2 then unify_expression e1 e2 else return false
188 | (Ast.Binary(l1,op1,r1),Ast.Binary(l2,op2,r2)) ->
189 if unify_mcode op1 op2
190 then conjunct_bindings (unify_expression l1 l2) (unify_expression r1 r2)
191 else return false
192 | (Ast.ArrayAccess(ar1,lb1,e1,rb1),Ast.ArrayAccess(ar2,lb2,e2,rb2)) ->
193 conjunct_bindings (unify_expression ar1 ar2) (unify_expression e1 e2)
194 | (Ast.RecordAccess(e1,d1,fld1),Ast.RecordAccess(e2,d2,fld2)) ->
195 conjunct_bindings (unify_expression e1 e2) (unify_ident fld1 fld2)
196 | (Ast.RecordPtAccess(e1,pt1,fld1),Ast.RecordPtAccess(e2,pt2,fld2)) ->
197 conjunct_bindings (unify_expression e1 e2) (unify_ident fld1 fld2)
198 | (Ast.Cast(lp1,ty1,rp1,e1),Ast.Cast(lp2,ty2,rp2,e2)) ->
199 conjunct_bindings (unify_fullType ty1 ty2) (unify_expression e1 e2)
200 | (Ast.SizeOfExpr(szf1,e1),Ast.SizeOfExpr(szf2,e2)) ->
201 unify_expression e1 e2
202 | (Ast.SizeOfType(szf1,lp1,ty1,rp1),Ast.SizeOfType(szf2,lp2,ty2,rp2)) ->
203 unify_fullType ty1 ty2
204 | (Ast.TypeExp(ty1),Ast.TypeExp(ty2)) -> unify_fullType ty1 ty2
205 | (Ast.Paren(lp1,e1,rp1),Ast.Paren(lp2,e2,rp2)) ->
206 unify_expression e1 e2
207
208 | (Ast.MetaErr(_,_,_,_),_)
209 | (Ast.MetaExpr(_,_,_,_,_,_),_)
210 | (Ast.MetaExprList(_,_,_,_),_)
211 | (_,Ast.MetaErr(_,_,_,_))
212 | (_,Ast.MetaExpr(_,_,_,_,_,_))
213 | (_,Ast.MetaExprList(_,_,_,_)) -> return true
214
215 | (Ast.EComma(cm1),Ast.EComma(cm2)) -> return true
216
217 | (Ast.DisjExpr(e1),_) ->
218 disjunct_all_bindings (List.map (function x -> unify_expression x e2) e1)
219 | (_,Ast.DisjExpr(e2)) ->
220 disjunct_all_bindings (List.map (function x -> unify_expression e1 x) e2)
5636bb2c 221 | (Ast.NestExpr(_,e1,_,_,_),Ast.NestExpr(_,e2,_,_,_)) ->
34e49164
C
222 unify_dots unify_expression edots e1 e2
223
224 (* dots can match against anything. return true to be safe. *)
225 | (Ast.Edots(_,_),_) | (_,Ast.Edots(_,_))
226 | (Ast.Ecircles(_,_),_) | (_,Ast.Ecircles(_,_))
227 | (Ast.Estars(_,_),_) | (_,Ast.Estars(_,_)) -> return true
228
229 | (Ast.OptExp(_),_)
230 | (Ast.UniqueExp(_),_)
231 | (_,Ast.OptExp(_))
232 | (_,Ast.UniqueExp(_)) -> failwith "unsupported expression"
233 | _ -> return false
234
235(* --------------------------------------------------------------------- *)
236(* Types *)
237
238and unify_fullType ft1 ft2 =
239 match (Ast.unwrap ft1,Ast.unwrap ft2) with
240 (Ast.Type(cv1,ty1),Ast.Type(cv2,ty2)) ->
241 if bool_unify_option unify_mcode cv1 cv2
242 then unify_typeC ty1 ty2
243 else return false
244 | (Ast.DisjType(ft1),_) ->
245 disjunct_all_bindings (List.map (function x -> unify_fullType x ft2) ft1)
246 | (_,Ast.DisjType(ft2)) ->
247 disjunct_all_bindings (List.map (function x -> unify_fullType ft1 x) ft2)
248
249 | (Ast.OptType(_),_)
250 | (Ast.UniqueType(_),_)
251 | (_,Ast.OptType(_))
252 | (_,Ast.UniqueType(_)) -> failwith "unsupported type"
253
254and unify_typeC t1 t2 =
255 match (Ast.unwrap t1,Ast.unwrap t2) with
faf9a90c
C
256 (Ast.BaseType(ty1,stringsa),Ast.BaseType(ty2,stringsb)) ->
257 if ty1 = ty2
258 then
259 unify_lists ret_unify_mcode (function _ -> false (* not dots*))
260 stringsa stringsb
261 else return false
262 | (Ast.SignedT(sgn1,ty1),Ast.SignedT(sgn2,ty2)) ->
263 if unify_mcode sgn1 sgn2
264 then unify_option unify_typeC ty1 ty2
265 else return false
34e49164
C
266 | (Ast.Pointer(ty1,s1),Ast.Pointer(ty2,s2)) -> unify_fullType ty1 ty2
267 | (Ast.FunctionPointer(tya,lp1a,stara,rp1a,lp2a,paramsa,rp2a),
268 Ast.FunctionPointer(tyb,lp1b,starb,rp1b,lp2b,paramsb,rp2b)) ->
269 if List.for_all2 unify_mcode
270 [lp1a;stara;rp1a;lp2a;rp2a] [lp1b;starb;rp1b;lp2b;rp2b]
271 then
272 conjunct_bindings (unify_fullType tya tyb)
273 (unify_dots unify_parameterTypeDef pdots paramsa paramsb)
274 else return false
275 | (Ast.FunctionType(_,tya,lp1a,paramsa,rp1a),
276 Ast.FunctionType(_,tyb,lp1b,paramsb,rp1b)) ->
277 if List.for_all2 unify_mcode [lp1a;rp1a] [lp1b;rp1b]
278 then
279 conjunct_bindings (unify_option unify_fullType tya tyb)
280 (unify_dots unify_parameterTypeDef pdots paramsa paramsb)
281 else return false
282 | (Ast.FunctionType _ , _) -> failwith "not supported"
283 | (Ast.Array(ty1,lb1,e1,rb1),Ast.Array(ty2,lb2,e2,rb2)) ->
284 conjunct_bindings
285 (unify_fullType ty1 ty2) (unify_option unify_expression e1 e2)
c491d8ee 286 | (Ast.EnumName(s1,Some ts1),Ast.EnumName(s2,Some ts2)) ->
faf9a90c 287 if unify_mcode s1 s2 then unify_ident ts1 ts2 else return false
c491d8ee
C
288 | (Ast.EnumName(s1,None),Ast.EnumName(s2,None)) ->
289 return true
290 | (Ast.EnumDef(ty1,lb1,ids1,rb1),Ast.EnumDef(ty2,lb2,ids2,rb2)) ->
291 conjunct_bindings (unify_fullType ty1 ty2)
292 (unify_dots unify_expression edots ids1 ids2)
34e49164
C
293 | (Ast.StructUnionName(s1,Some ts1),Ast.StructUnionName(s2,Some ts2)) ->
294 if unify_mcode s1 s2 then unify_ident ts1 ts2 else return false
295 | (Ast.StructUnionName(s1,None),Ast.StructUnionName(s2,None)) ->
c491d8ee 296 return (unify_mcode s1 s2)
34e49164
C
297 | (Ast.StructUnionDef(ty1,lb1,decls1,rb1),
298 Ast.StructUnionDef(ty2,lb2,decls2,rb2)) ->
299 conjunct_bindings (unify_fullType ty1 ty2)
300 (unify_dots unify_declaration ddots decls1 decls2)
301 | (Ast.TypeName(t1),Ast.TypeName(t2)) -> return (unify_mcode t1 t2)
302
303 | (Ast.MetaType(_,_,_),_)
304 | (_,Ast.MetaType(_,_,_)) -> return true
305 | _ -> return false
306
307(* --------------------------------------------------------------------- *)
308(* Variable declaration *)
309(* Even if the Cocci program specifies a list of declarations, they are
310 split out into multiple declarations of a single variable each. *)
311
312and unify_declaration d1 d2 =
313 match (Ast.unwrap d1,Ast.unwrap d2) with
413ffc02
C
314 (Ast.MetaDecl(_,_,_),_) | (_,Ast.MetaDecl(_,_,_)) -> return true
315 | (Ast.MetaField(_,_,_),_) | (_,Ast.MetaField(_,_,_)) -> return true
316 | (Ast.Init(stg1,ft1,id1,eq1,i1,s1),Ast.Init(stg2,ft2,id2,eq2,i2,s2)) ->
34e49164
C
317 if bool_unify_option unify_mcode stg1 stg2
318 then
319 conjunct_bindings (unify_fullType ft1 ft2)
320 (conjunct_bindings (unify_ident id1 id2) (unify_initialiser i1 i2))
321 else return false
322 | (Ast.UnInit(stg1,ft1,id1,s1),Ast.UnInit(stg2,ft2,id2,s2)) ->
323 if bool_unify_option unify_mcode stg1 stg2
324 then conjunct_bindings (unify_fullType ft1 ft2) (unify_ident id1 id2)
325 else return false
326 | (Ast.MacroDecl(n1,lp1,args1,rp1,sem1),
327 Ast.MacroDecl(n2,lp2,args2,rp2,sem2)) ->
328 conjunct_bindings (unify_ident n1 n2)
329 (unify_dots unify_expression edots args1 args2)
330 | (Ast.TyDecl(ft1,s1),Ast.TyDecl(ft2,s2)) -> unify_fullType ft1 ft2
331 | (Ast.Typedef(stg1,ft1,id1,s1),Ast.Typedef(stg2,ft2,id2,s2)) ->
332 conjunct_bindings (unify_fullType ft1 ft2) (unify_typeC id1 id2)
333 | (Ast.DisjDecl(d1),_) ->
334 disjunct_all_bindings
335 (List.map (function x -> unify_declaration x d2) d1)
336 | (_,Ast.DisjDecl(d2)) ->
337 disjunct_all_bindings
338 (List.map (function x -> unify_declaration d1 x) d2)
339 (* dots can match against anything. return true to be safe. *)
340 | (Ast.Ddots(_,_),_) | (_,Ast.Ddots(_,_)) -> return true
341
342 | (Ast.OptDecl(_),_)
343 | (Ast.UniqueDecl(_),_)
344 | (_,Ast.OptDecl(_))
345 | (_,Ast.UniqueDecl(_)) -> failwith "unsupported decl"
346 | _ -> return false
347
348(* --------------------------------------------------------------------- *)
349(* Initializer *)
350
351and unify_initialiser i1 i2 =
352 match (Ast.unwrap i1,Ast.unwrap i2) with
113803cf
C
353 (Ast.MetaInit(_,_,_),_) | (_,Ast.MetaInit(_,_,_)) -> return true
354 | (Ast.InitExpr(expa),Ast.InitExpr(expb)) ->
34e49164 355 unify_expression expa expb
c491d8ee
C
356 | (Ast.ArInitList(_,initlista,_),
357 Ast.ArInitList(_,initlistb,_)) ->
358 (* ignore whencode - returns true safely *)
359 unify_dots unify_initialiser idots initlista initlistb
360 | (Ast.StrInitList(_,_,initlista,_,whena),
361 Ast.StrInitList(_,_,initlistb,_,whenb)) ->
34e49164
C
362 (* ignore whencode - returns true safely *)
363 unify_lists unify_initialiser (function _ -> false) initlista initlistb
113803cf
C
364 | (Ast.InitGccExt(designatorsa,_,inia),
365 Ast.InitGccExt(designatorsb,_,inib)) ->
34e49164 366 conjunct_bindings
113803cf
C
367 (unify_lists unify_designator (function _ -> false)
368 designatorsa designatorsb)
369 (unify_initialiser inia inib)
34e49164
C
370 | (Ast.InitGccName(namea,_,inia),Ast.InitGccName(nameb,_,inib)) ->
371 conjunct_bindings (unify_ident namea nameb) (unify_initialiser inia inib)
faf9a90c 372
34e49164
C
373 | (Ast.OptIni(_),_)
374 | (Ast.UniqueIni(_),_)
375 | (_,Ast.OptIni(_))
376 | (_,Ast.UniqueIni(_)) -> failwith "unsupported decl"
377 | _ -> return false
378
113803cf
C
379and unify_designator d1 d2 =
380 match (d1,d2) with
381 (Ast.DesignatorField(_,idb),Ast.DesignatorField(_,ida)) ->
382 unify_ident ida idb
383 | (Ast.DesignatorIndex(_,expa,_),Ast.DesignatorIndex(_,expb,_)) ->
384 unify_expression expa expb
385 | (Ast.DesignatorRange(_,mina,_,maxa,_),
386 Ast.DesignatorRange(_,minb,_,maxb,_)) ->
387 conjunct_bindings (unify_expression mina minb)
388 (unify_expression maxa maxb)
389 | _ -> return false
390
34e49164
C
391(* --------------------------------------------------------------------- *)
392(* Parameter *)
393
394and unify_parameterTypeDef p1 p2 =
395 match (Ast.unwrap p1,Ast.unwrap p2) with
396 (Ast.VoidParam(ft1),Ast.VoidParam(ft2)) -> unify_fullType ft1 ft2
397 | (Ast.Param(ft1,i1),Ast.Param(ft2,i2)) ->
398 conjunct_bindings (unify_fullType ft1 ft2)
399 (unify_option unify_ident i1 i2)
400
401 | (Ast.MetaParam(_,_,_),_)
402 | (Ast.MetaParamList(_,_,_,_),_)
403 | (_,Ast.MetaParam(_,_,_))
404 | (_,Ast.MetaParamList(_,_,_,_)) -> return true
405
406 | (Ast.PComma(_),Ast.PComma(_)) -> return true
407
408 (* dots can match against anything. return true to be safe. *)
409 | (Ast.Pdots(_),_) | (_,Ast.Pdots(_))
410 | (Ast.Pcircles(_),_) | (_,Ast.Pcircles(_)) -> return true
411
412 | (Ast.OptParam(_),_)
413 | (Ast.UniqueParam(_),_)
414 | (_,Ast.OptParam(_))
415 | (_,Ast.UniqueParam(_)) -> failwith "unsupported parameter"
416 | _ -> return false
417
418(* --------------------------------------------------------------------- *)
419(* Define parameter *)
420
421and unify_define_parameters p1 p2 =
422 match (Ast.unwrap p1,Ast.unwrap p2) with
423 (Ast.NoParams,Ast.NoParams) -> return true
424 | (Ast.DParams(lp1,params1,rp1),Ast.DParams(lp2,params2,rp2)) ->
425 unify_dots unify_define_param dpdots params1 params2
426 | _ -> return false
427
428and unify_define_param p1 p2 =
429 match (Ast.unwrap p1,Ast.unwrap p2) with
430 (Ast.DParam(i1),Ast.DParam(i2)) ->
431 (unify_ident i1 i2)
432 | (Ast.DPComma(_),Ast.DPComma(_)) -> return true
433
434 (* dots can match against anything. return true to be safe. *)
435 | (Ast.DPdots(_),_) | (_,Ast.DPdots(_))
436 | (Ast.DPcircles(_),_) | (_,Ast.DPcircles(_)) -> return true
437
438 | (Ast.OptDParam(_),_)
439 | (Ast.UniqueDParam(_),_)
440 | (_,Ast.OptDParam(_))
441 | (_,Ast.UniqueDParam(_)) -> failwith "unsupported parameter"
442 | _ -> return false
443
444(* --------------------------------------------------------------------- *)
445(* Top-level code *)
446
447and unify_rule_elem re1 re2 =
448 match (Ast.unwrap re1,Ast.unwrap re2) with
449 (Ast.FunHeader(_,_,fi1,nm1,lp1,params1,rp1),
450 Ast.FunHeader(_,_,fi2,nm2,lp2,params2,rp2)) ->
451 conjunct_bindings (unify_fninfo fi1 fi2)
452 (conjunct_bindings (unify_ident nm1 nm2)
453 (unify_dots unify_parameterTypeDef pdots params1 params2))
454 | (Ast.Decl(_,_,d1),Ast.Decl(_,_,d2)) -> unify_declaration d1 d2
455
456 | (Ast.SeqStart(lb1),Ast.SeqStart(lb2)) -> return true
457 | (Ast.SeqEnd(rb1),Ast.SeqEnd(rb2)) -> return true
458
459 | (Ast.ExprStatement(e1,s1),Ast.ExprStatement(e2,s2)) ->
460 unify_expression e1 e2
461 | (Ast.IfHeader(if1,lp1,e1,rp1),Ast.IfHeader(if2,lp2,e2,rp2)) ->
462 unify_expression e1 e2
463 | (Ast.Else(e1),Ast.Else(e2)) -> return true
464 | (Ast.WhileHeader(wh1,lp1,e1,rp1),Ast.WhileHeader(wh2,lp2,e2,rp2)) ->
465 unify_expression e1 e2
466 | (Ast.DoHeader(d1),Ast.DoHeader(d2)) -> return true
467 | (Ast.WhileTail(wh1,lp1,e1,rp1,s1),Ast.WhileTail(wh2,lp2,e2,rp2,s2)) ->
468 unify_expression e1 e2
469 | (Ast.ForHeader(fr1,lp1,e11,s11,e21,s21,e31,rp1),
470 Ast.ForHeader(fr2,lp2,e12,s12,e22,s22,e32,rp2)) ->
471 conjunct_bindings
472 (unify_option unify_expression e11 e12)
473 (conjunct_bindings
474 (unify_option unify_expression e21 e22)
475 (unify_option unify_expression e31 e32))
476 | (Ast.IteratorHeader(nm1,lp1,args1,rp1),
477 Ast.IteratorHeader(nm2,lp2,args2,rp2)) ->
478 conjunct_bindings (unify_ident nm1 nm2)
479 (unify_dots unify_expression edots args1 args2)
480 | (Ast.DefineHeader(_,n1,p1),Ast.DefineHeader(_,n2,p2)) ->
481 conjunct_bindings (unify_ident n1 n2)
482 (unify_define_parameters p1 p2)
483 | (Ast.Break(r1,s1),Ast.Break(r2,s2)) -> return true
484 | (Ast.Continue(r1,s1),Ast.Continue(r2,s2)) -> return true
485 | (Ast.Label(l1,dd1),Ast.Label(l2,dd2)) -> unify_ident l1 l2
486 | (Ast.Goto(g1,l1,dd1),Ast.Goto(g2,l2,dd2)) -> unify_ident l1 l2
487 | (Ast.Return(r1,s1),Ast.Return(r2,s2)) -> return true
488 | (Ast.ReturnExpr(r1,e1,s1),Ast.ReturnExpr(r2,e2,s2)) ->
489 unify_expression e1 e2
490
491 | (Ast.DisjRuleElem(res1),_) ->
492 disjunct_all_bindings
493 (List.map (function x -> unify_rule_elem x re2) res1)
494 | (_,Ast.DisjRuleElem(res2)) ->
495 disjunct_all_bindings
496 (List.map (function x -> unify_rule_elem re1 x) res2)
497
498 | (Ast.MetaRuleElem(_,_,_),_)
499 | (Ast.MetaStmt(_,_,_,_),_)
500 | (Ast.MetaStmtList(_,_,_),_)
501 | (_,Ast.MetaRuleElem(_,_,_))
502 | (_,Ast.MetaStmt(_,_,_,_))
503 | (_,Ast.MetaStmtList(_,_,_)) -> return true
504
505 (* can match a rule_elem in different parts *)
506 | (Ast.Exp(e1),Ast.Exp(e2)) -> return true
507 | (Ast.Exp(e1),_) -> subexp (unify_expression e1) re2
508 | (_,Ast.Exp(e2)) -> subexp (unify_expression e2) re1
509
510 | (Ast.TopExp(e1),Ast.TopExp(e2)) -> unify_expression e1 e2
1be43e12 511 | (Ast.TopInit(i1),Ast.TopInit(i2)) -> unify_initialiser i1 i2
34e49164
C
512
513 (* can match a rule_elem in different parts *)
514 | (Ast.Ty(t1),Ast.Ty(t2)) -> return true
515 | (Ast.Ty(t1),_) -> subtype (unify_fullType t1) re2
516 | (_,Ast.Ty(t2)) -> subtype (unify_fullType t2) re1
517 | _ -> return false
518
519and unify_fninfo patterninfo cinfo =
520 let patterninfo = List.sort compare patterninfo in
521 let cinfo = List.sort compare cinfo in
522 let rec loop = function
523 (Ast.FStorage(sta)::resta,Ast.FStorage(stb)::restb) ->
524 if unify_mcode sta stb then loop (resta,restb) else return false
525 | (Ast.FType(tya)::resta,Ast.FType(tyb)::restb) ->
526 conjunct_bindings (unify_fullType tya tyb) (loop (resta,restb))
527 | (Ast.FInline(ia)::resta,Ast.FInline(ib)::restb) ->
528 if unify_mcode ia ib then loop (resta,restb) else return false
529 | (Ast.FAttr(ia)::resta,Ast.FAttr(ib)::restb) ->
530 if unify_mcode ia ib then loop (resta,restb) else return false
531 | (x::resta,((y::_) as restb)) ->
532 (match compare x y with
533 -1 -> return false
534 | 1 -> loop (resta,restb)
535 | _ -> failwith "not possible")
536 | _ -> return false in
537 loop (patterninfo,cinfo)
538
539and subexp f =
540 let bind = conjunct_bindings in
541 let option_default = return false in
542 let mcode r e = option_default in
543 let expr r k e = conjunct_bindings (f e) (k e) in
544 let donothing r k e = k e in
545 let recursor = V.combiner bind option_default
546 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
c491d8ee 547 donothing donothing donothing donothing donothing
34e49164
C
548 donothing expr donothing donothing donothing donothing donothing
549 donothing donothing donothing donothing donothing in
550 recursor.V.combiner_rule_elem
551
552and subtype f =
553 let bind = conjunct_bindings in
554 let option_default = return false in
555 let mcode r e = option_default in
556 let fullType r k e = conjunct_bindings (f e) (k e) in
557 let donothing r k e = k e in
558 let recursor = V.combiner bind option_default
559 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
c491d8ee 560 donothing donothing donothing donothing donothing
34e49164
C
561 donothing donothing fullType donothing donothing donothing donothing
562 donothing donothing donothing donothing donothing in
563 recursor.V.combiner_rule_elem
564
565let rec unify_statement s1 s2 =
566 match (Ast.unwrap s1,Ast.unwrap s2) with
708f4980 567 (Ast.Seq(lb1,s1,rb1),Ast.Seq(lb2,s2,rb2)) ->
34e49164
C
568 conjunct_bindings (unify_rule_elem lb1 lb2)
569 (conjunct_bindings
570 (unify_dots unify_statement sdots s1 s2)
708f4980 571 (unify_rule_elem rb1 rb2))
34e49164
C
572 | (Ast.IfThen(h1,thn1,_),Ast.IfThen(h2,thn2,_)) ->
573 conjunct_bindings (unify_rule_elem h1 h2) (unify_statement thn1 thn2)
574 | (Ast.IfThenElse(h1,thn1,e1,els1,_),Ast.IfThenElse(h2,thn2,e2,els2,_)) ->
575 conjunct_bindings (unify_rule_elem h1 h2)
576 (conjunct_bindings (unify_statement thn1 thn2)
577 (conjunct_bindings (unify_rule_elem e1 e2)
578 (unify_statement els1 els2)))
579 | (Ast.While(h1,s1,_),Ast.While(h2,s2,_)) ->
580 conjunct_bindings (unify_rule_elem h1 h2) (unify_statement s1 s2)
581 | (Ast.Do(h1,s1,t1),Ast.Do(h2,s2,t2)) ->
582 conjunct_bindings (unify_rule_elem h1 h2)
583 (conjunct_bindings (unify_statement s1 s2) (unify_rule_elem t1 t2))
584 | (Ast.For(h1,s1,_),Ast.For(h2,s2,_)) ->
585 conjunct_bindings (unify_rule_elem h1 h2) (unify_statement s1 s2)
586 | (Ast.Atomic(re1),Ast.Atomic(re2)) -> unify_rule_elem re1 re2
587 | (Ast.Disj(s1),_) ->
588 let s2 = Ast.rewrap s2 (Ast.DOTS[s2]) in
589 disjunct_all_bindings
590 (List.map
591 (function x -> unify_dots unify_statement sdots x s2)
592 s1)
593 | (_,Ast.Disj(s2)) ->
594 let s1 = Ast.rewrap s1 (Ast.DOTS[s1]) in
595 disjunct_all_bindings
596 (List.map
597 (function x -> unify_dots unify_statement sdots s1 x)
598 s2)
5636bb2c 599 | (Ast.Nest(_,s1,_,_,_,_,_),Ast.Nest(_,s2,_,_,_,_,_)) ->
34e49164 600 unify_dots unify_statement sdots s1 s2
708f4980 601 | (Ast.FunDecl(h1,lb1,s1,rb1),Ast.FunDecl(h2,lb2,s2,rb2)) ->
34e49164
C
602 conjunct_bindings (unify_rule_elem h1 h2)
603 (conjunct_bindings (unify_rule_elem lb1 lb2)
708f4980
C
604 (conjunct_bindings (unify_dots unify_statement sdots s1 s2)
605 (unify_rule_elem rb1 rb2)))
34e49164
C
606 | (Ast.Define(h1,s1),Ast.Define(h2,s2)) ->
607 conjunct_bindings (unify_rule_elem h1 h2)
608 (unify_dots unify_statement sdots s1 s2)
609 (* dots can match against anything. return true to be safe. *)
610 | (Ast.Dots(_,_,_,_),_) | (_,Ast.Dots(_,_,_,_))
611 | (Ast.Circles(_,_,_,_),_) | (_,Ast.Circles(_,_,_,_))
612 | (Ast.Stars(_,_,_,_),_) | (_,Ast.Stars(_,_,_,_)) -> return true
613 | (Ast.OptStm(_),_)
614 | (Ast.UniqueStm(_),_)
615 | (_,Ast.OptStm(_))
616 | (_,Ast.UniqueStm(_)) -> failwith "unsupported statement"
617 | _ -> return false
618
619let unify_statement_dots = unify_dots unify_statement sdots