2 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
3 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
4 * This file is part of Coccinelle.
6 * Coccinelle is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, according to version 2 of the License.
10 * Coccinelle is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
18 * The authors reserve the right to distribute this or future versions of
19 * Coccinelle under other licenses.
23 (* --------------------------------------------------------------------- *)
24 (* Given two patterns, A and B, determine whether B can match any matched
25 subterms of A. For simplicity, this doesn't maintain an environment; it
26 just assume metavariables match. Thus the result is either NO or MAYBE. *)
28 module Ast
= Ast_cocci
29 module V
= Visitor_ast
31 (* --------------------------------------------------------------------- *)
35 let return b
= if b
then MAYBE
else NO
37 let unify_mcode (x
,_
,_
,_
) (y
,_
,_
,_
) = x
= y
39 let ret_unify_mcode a b
= return (unify_mcode a b
)
41 let unify_option f t1 t2
=
43 (Some t1
, Some t2
) -> f t1 t2
44 | (None
, None
) -> return true
47 let unify_true_option f t1 t2
=
49 (Some t1
, Some t2
) -> f t1 t2
50 | (None
, None
) -> return true
53 let bool_unify_option f t1 t2
=
55 (Some t1
, Some t2
) -> f t1 t2
56 | (None
, None
) -> true
59 let conjunct_bindings b1 b2
=
60 match b1
with NO
-> b1
| MAYBE
-> b2
62 let disjunct_bindings b1 b2
=
63 match b1
with MAYBE
-> b1
| NO
-> b2
65 let disjunct_all_bindings = List.fold_left
disjunct_bindings NO
67 (* --------------------------------------------------------------------- *)
69 (* compute the common prefix. if in at least one case, this ends with the
70 end of the pattern or a ..., then return true. *)
72 let unify_lists fn dfn la lb
=
73 let rec loop = function
74 ([],_
) | (_
,[]) -> return true
75 | (cura
::resta
,curb
::restb
) ->
76 (match fn cura curb
with
77 MAYBE
-> loop (resta
,restb
)
78 | NO
-> if dfn cura
or dfn curb
then MAYBE
else NO
) in
81 let unify_dots fn dfn d1 d2
=
82 match (Ast.unwrap d1
,Ast.unwrap d2
) with
83 (Ast.DOTS
(l1
),Ast.DOTS
(l2
))
84 | (Ast.CIRCLES
(l1
),Ast.CIRCLES
(l2
))
85 | (Ast.STARS
(l1
),Ast.STARS
(l2
)) -> unify_lists fn dfn l1 l2
89 match Ast.unwrap e
with
90 Ast.Edots
(_
,_
) | Ast.Ecircles
(_
,_
) | Ast.Estars
(_
,_
) -> true
94 match Ast.unwrap e
with
95 Ast.Ddots
(_
,_
) -> true
99 match Ast.unwrap p
with
100 Ast.Pdots
(_
) | Ast.Pcircles
(_
) -> true
104 match Ast.unwrap e
with
105 Ast.DPdots
(_
) | Ast.DPcircles
(_
) -> true
109 match Ast.unwrap s
with
110 Ast.Dots
(_
,_
,_
,_
) | Ast.Circles
(_
,_
,_
,_
) | Ast.Stars
(_
,_
,_
,_
) -> true
113 (* --------------------------------------------------------------------- *)
116 and unify_ident i1 i2
=
117 match (Ast.unwrap i1
,Ast.unwrap i2
) with
118 (Ast.Id
(i1
),Ast.Id
(i2
)) -> return (unify_mcode i1 i2
)
120 | (Ast.MetaId
(_
,_
,_
,_
),_
)
121 | (Ast.MetaFunc
(_
,_
,_
,_
),_
)
122 | (Ast.MetaLocalFunc
(_
,_
,_
,_
),_
)
123 | (_
,Ast.MetaId
(_
,_
,_
,_
))
124 | (_
,Ast.MetaFunc
(_
,_
,_
,_
))
125 | (_
,Ast.MetaLocalFunc
(_
,_
,_
,_
)) -> return true
127 | (Ast.OptIdent
(_
),_
)
128 | (Ast.UniqueIdent
(_
),_
)
129 | (_
,Ast.OptIdent
(_
))
130 | (_
,Ast.UniqueIdent
(_
)) -> failwith
"unsupported ident"
132 (* --------------------------------------------------------------------- *)
135 let rec unify_expression e1 e2
=
136 match (Ast.unwrap e1
,Ast.unwrap e2
) with
137 (Ast.Ident
(i1
),Ast.Ident
(i2
)) -> unify_ident i1 i2
138 | (Ast.Constant
(c1
),Ast.Constant
(c2
))-> return (unify_mcode c1 c2
)
139 | (Ast.FunCall
(f1
,lp1
,args1
,rp1
),Ast.FunCall
(f2
,lp2
,args2
,rp2
)) ->
141 (unify_expression f1 f2
)
142 (unify_dots unify_expression edots args1 args2
)
143 | (Ast.Assignment
(l1
,op1
,r1
,_
),Ast.Assignment
(l2
,op2
,r2
,_
)) ->
144 if unify_mcode op1 op2
145 then conjunct_bindings (unify_expression l1 l2
) (unify_expression r1 r2
)
147 | (Ast.CondExpr
(tst1
,q1
,thn1
,c1
,els1
),Ast.CondExpr
(tst2
,q2
,thn2
,c2
,els2
)) ->
148 conjunct_bindings (unify_expression tst1 tst2
)
149 (conjunct_bindings (unify_option unify_expression thn1 thn2
)
150 (unify_expression els1 els2
))
151 | (Ast.Postfix
(e1
,op1
),Ast.Postfix
(e2
,op2
)) ->
152 if unify_mcode op1 op2
then unify_expression e1 e2
else return false
153 | (Ast.Infix
(e1
,op1
),Ast.Infix
(e2
,op2
)) ->
154 if unify_mcode op1 op2
then unify_expression e1 e2
else return false
155 | (Ast.Unary
(e1
,op1
),Ast.Unary
(e2
,op2
)) ->
156 if unify_mcode op1 op2
then unify_expression e1 e2
else return false
157 | (Ast.Binary
(l1
,op1
,r1
),Ast.Binary
(l2
,op2
,r2
)) ->
158 if unify_mcode op1 op2
159 then conjunct_bindings (unify_expression l1 l2
) (unify_expression r1 r2
)
161 | (Ast.ArrayAccess
(ar1
,lb1
,e1
,rb1
),Ast.ArrayAccess
(ar2
,lb2
,e2
,rb2
)) ->
162 conjunct_bindings (unify_expression ar1 ar2
) (unify_expression e1 e2
)
163 | (Ast.RecordAccess
(e1
,d1
,fld1
),Ast.RecordAccess
(e2
,d2
,fld2
)) ->
164 conjunct_bindings (unify_expression e1 e2
) (unify_ident fld1 fld2
)
165 | (Ast.RecordPtAccess
(e1
,pt1
,fld1
),Ast.RecordPtAccess
(e2
,pt2
,fld2
)) ->
166 conjunct_bindings (unify_expression e1 e2
) (unify_ident fld1 fld2
)
167 | (Ast.Cast
(lp1
,ty1
,rp1
,e1
),Ast.Cast
(lp2
,ty2
,rp2
,e2
)) ->
168 conjunct_bindings (unify_fullType ty1 ty2
) (unify_expression e1 e2
)
169 | (Ast.SizeOfExpr
(szf1
,e1
),Ast.SizeOfExpr
(szf2
,e2
)) ->
170 unify_expression e1 e2
171 | (Ast.SizeOfType
(szf1
,lp1
,ty1
,rp1
),Ast.SizeOfType
(szf2
,lp2
,ty2
,rp2
)) ->
172 unify_fullType ty1 ty2
173 | (Ast.TypeExp
(ty1
),Ast.TypeExp
(ty2
)) -> unify_fullType ty1 ty2
174 | (Ast.Paren
(lp1
,e1
,rp1
),Ast.Paren
(lp2
,e2
,rp2
)) ->
175 unify_expression e1 e2
177 | (Ast.MetaErr
(_
,_
,_
,_
),_
)
178 | (Ast.MetaExpr
(_
,_
,_
,_
,_
,_
),_
)
179 | (Ast.MetaExprList
(_
,_
,_
,_
),_
)
180 | (_
,Ast.MetaErr
(_
,_
,_
,_
))
181 | (_
,Ast.MetaExpr
(_
,_
,_
,_
,_
,_
))
182 | (_
,Ast.MetaExprList
(_
,_
,_
,_
)) -> return true
184 | (Ast.EComma
(cm1
),Ast.EComma
(cm2
)) -> return true
186 | (Ast.DisjExpr
(e1
),_
) ->
187 disjunct_all_bindings (List.map
(function x
-> unify_expression x e2
) e1
)
188 | (_
,Ast.DisjExpr
(e2
)) ->
189 disjunct_all_bindings (List.map
(function x
-> unify_expression e1 x
) e2
)
190 | (Ast.NestExpr
(e1
,_
,_
),Ast.NestExpr
(e2
,_
,_
)) ->
191 unify_dots unify_expression edots e1 e2
193 (* dots can match against anything. return true to be safe. *)
194 | (Ast.Edots
(_
,_
),_
) | (_
,Ast.Edots
(_
,_
))
195 | (Ast.Ecircles
(_
,_
),_
) | (_
,Ast.Ecircles
(_
,_
))
196 | (Ast.Estars
(_
,_
),_
) | (_
,Ast.Estars
(_
,_
)) -> return true
199 | (Ast.UniqueExp
(_
),_
)
201 | (_
,Ast.UniqueExp
(_
)) -> failwith
"unsupported expression"
204 (* --------------------------------------------------------------------- *)
207 and unify_fullType ft1 ft2
=
208 match (Ast.unwrap ft1
,Ast.unwrap ft2
) with
209 (Ast.Type
(cv1
,ty1
),Ast.Type
(cv2
,ty2
)) ->
210 if bool_unify_option unify_mcode cv1 cv2
211 then unify_typeC ty1 ty2
213 | (Ast.DisjType
(ft1
),_
) ->
214 disjunct_all_bindings (List.map
(function x
-> unify_fullType x ft2
) ft1
)
215 | (_
,Ast.DisjType
(ft2
)) ->
216 disjunct_all_bindings (List.map
(function x
-> unify_fullType ft1 x
) ft2
)
219 | (Ast.UniqueType
(_
),_
)
221 | (_
,Ast.UniqueType
(_
)) -> failwith
"unsupported type"
223 and unify_typeC t1 t2
=
224 match (Ast.unwrap t1
,Ast.unwrap t2
) with
225 (Ast.BaseType
(ty1
,stringsa
),Ast.BaseType
(ty2
,stringsb
)) ->
228 unify_lists ret_unify_mcode (function _
-> false (* not dots*))
231 | (Ast.SignedT
(sgn1
,ty1
),Ast.SignedT
(sgn2
,ty2
)) ->
232 if unify_mcode sgn1 sgn2
233 then unify_option unify_typeC ty1 ty2
235 | (Ast.Pointer
(ty1
,s1
),Ast.Pointer
(ty2
,s2
)) -> unify_fullType ty1 ty2
236 | (Ast.FunctionPointer
(tya
,lp1a
,stara
,rp1a
,lp2a
,paramsa
,rp2a
),
237 Ast.FunctionPointer
(tyb
,lp1b
,starb
,rp1b
,lp2b
,paramsb
,rp2b
)) ->
238 if List.for_all2
unify_mcode
239 [lp1a
;stara
;rp1a
;lp2a
;rp2a
] [lp1b
;starb
;rp1b
;lp2b
;rp2b
]
241 conjunct_bindings (unify_fullType tya tyb
)
242 (unify_dots unify_parameterTypeDef
pdots paramsa paramsb
)
244 | (Ast.FunctionType
(_
,tya
,lp1a
,paramsa
,rp1a
),
245 Ast.FunctionType
(_
,tyb
,lp1b
,paramsb
,rp1b
)) ->
246 if List.for_all2
unify_mcode [lp1a
;rp1a
] [lp1b
;rp1b
]
248 conjunct_bindings (unify_option unify_fullType tya tyb
)
249 (unify_dots unify_parameterTypeDef
pdots paramsa paramsb
)
251 | (Ast.FunctionType _
, _
) -> failwith
"not supported"
252 | (Ast.Array
(ty1
,lb1
,e1
,rb1
),Ast.Array
(ty2
,lb2
,e2
,rb2
)) ->
254 (unify_fullType ty1 ty2
) (unify_option unify_expression e1 e2
)
255 | (Ast.EnumName
(s1
,ts1
),Ast.EnumName
(s2
,ts2
)) ->
256 if unify_mcode s1 s2
then unify_ident ts1 ts2
else return false
257 | (Ast.StructUnionName
(s1
,Some ts1
),Ast.StructUnionName
(s2
,Some ts2
)) ->
258 if unify_mcode s1 s2
then unify_ident ts1 ts2
else return false
259 | (Ast.StructUnionName
(s1
,None
),Ast.StructUnionName
(s2
,None
)) ->
261 | (Ast.StructUnionDef
(ty1
,lb1
,decls1
,rb1
),
262 Ast.StructUnionDef
(ty2
,lb2
,decls2
,rb2
)) ->
263 conjunct_bindings (unify_fullType ty1 ty2
)
264 (unify_dots unify_declaration
ddots decls1 decls2
)
265 | (Ast.TypeName
(t1
),Ast.TypeName
(t2
)) -> return (unify_mcode t1 t2
)
267 | (Ast.MetaType
(_
,_
,_
),_
)
268 | (_
,Ast.MetaType
(_
,_
,_
)) -> return true
271 (* --------------------------------------------------------------------- *)
272 (* Variable declaration *)
273 (* Even if the Cocci program specifies a list of declarations, they are
274 split out into multiple declarations of a single variable each. *)
276 and unify_declaration d1 d2
=
277 match (Ast.unwrap d1
,Ast.unwrap d2
) with
278 (Ast.Init
(stg1
,ft1
,id1
,eq1
,i1
,s1
),Ast.Init
(stg2
,ft2
,id2
,eq2
,i2
,s2
)) ->
279 if bool_unify_option unify_mcode stg1 stg2
281 conjunct_bindings (unify_fullType ft1 ft2
)
282 (conjunct_bindings (unify_ident id1 id2
) (unify_initialiser i1 i2
))
284 | (Ast.UnInit
(stg1
,ft1
,id1
,s1
),Ast.UnInit
(stg2
,ft2
,id2
,s2
)) ->
285 if bool_unify_option unify_mcode stg1 stg2
286 then conjunct_bindings (unify_fullType ft1 ft2
) (unify_ident id1 id2
)
288 | (Ast.MacroDecl
(n1
,lp1
,args1
,rp1
,sem1
),
289 Ast.MacroDecl
(n2
,lp2
,args2
,rp2
,sem2
)) ->
290 conjunct_bindings (unify_ident n1 n2
)
291 (unify_dots unify_expression edots args1 args2
)
292 | (Ast.TyDecl
(ft1
,s1
),Ast.TyDecl
(ft2
,s2
)) -> unify_fullType ft1 ft2
293 | (Ast.Typedef
(stg1
,ft1
,id1
,s1
),Ast.Typedef
(stg2
,ft2
,id2
,s2
)) ->
294 conjunct_bindings (unify_fullType ft1 ft2
) (unify_typeC id1 id2
)
295 | (Ast.DisjDecl
(d1
),_
) ->
296 disjunct_all_bindings
297 (List.map
(function x
-> unify_declaration x d2
) d1
)
298 | (_
,Ast.DisjDecl
(d2
)) ->
299 disjunct_all_bindings
300 (List.map
(function x
-> unify_declaration d1 x
) d2
)
301 (* dots can match against anything. return true to be safe. *)
302 | (Ast.Ddots
(_
,_
),_
) | (_
,Ast.Ddots
(_
,_
)) -> return true
305 | (Ast.UniqueDecl
(_
),_
)
307 | (_
,Ast.UniqueDecl
(_
)) -> failwith
"unsupported decl"
310 (* --------------------------------------------------------------------- *)
313 and unify_initialiser i1 i2
=
314 match (Ast.unwrap i1
,Ast.unwrap i2
) with
315 (Ast.MetaInit
(_
,_
,_
),_
) | (_
,Ast.MetaInit
(_
,_
,_
)) -> return true
316 | (Ast.InitExpr
(expa
),Ast.InitExpr
(expb
)) ->
317 unify_expression expa expb
318 | (Ast.InitList
(_
,initlista
,_
,whena
),
319 Ast.InitList
(_
,initlistb
,_
,whenb
)) ->
320 (* ignore whencode - returns true safely *)
321 unify_lists unify_initialiser
(function _
-> false) initlista initlistb
322 | (Ast.InitGccExt
(designatorsa
,_
,inia
),
323 Ast.InitGccExt
(designatorsb
,_
,inib
)) ->
325 (unify_lists unify_designator
(function _
-> false)
326 designatorsa designatorsb
)
327 (unify_initialiser inia inib
)
328 | (Ast.InitGccName
(namea
,_
,inia
),Ast.InitGccName
(nameb
,_
,inib
)) ->
329 conjunct_bindings (unify_ident namea nameb
) (unify_initialiser inia inib
)
332 | (Ast.UniqueIni
(_
),_
)
334 | (_
,Ast.UniqueIni
(_
)) -> failwith
"unsupported decl"
337 and unify_designator d1 d2
=
339 (Ast.DesignatorField
(_
,idb
),Ast.DesignatorField
(_
,ida
)) ->
341 | (Ast.DesignatorIndex
(_
,expa
,_
),Ast.DesignatorIndex
(_
,expb
,_
)) ->
342 unify_expression expa expb
343 | (Ast.DesignatorRange
(_
,mina
,_
,maxa
,_
),
344 Ast.DesignatorRange
(_
,minb
,_
,maxb
,_
)) ->
345 conjunct_bindings (unify_expression mina minb
)
346 (unify_expression maxa maxb
)
349 (* --------------------------------------------------------------------- *)
352 and unify_parameterTypeDef p1 p2
=
353 match (Ast.unwrap p1
,Ast.unwrap p2
) with
354 (Ast.VoidParam
(ft1
),Ast.VoidParam
(ft2
)) -> unify_fullType ft1 ft2
355 | (Ast.Param
(ft1
,i1
),Ast.Param
(ft2
,i2
)) ->
356 conjunct_bindings (unify_fullType ft1 ft2
)
357 (unify_option unify_ident i1 i2
)
359 | (Ast.MetaParam
(_
,_
,_
),_
)
360 | (Ast.MetaParamList
(_
,_
,_
,_
),_
)
361 | (_
,Ast.MetaParam
(_
,_
,_
))
362 | (_
,Ast.MetaParamList
(_
,_
,_
,_
)) -> return true
364 | (Ast.PComma
(_
),Ast.PComma
(_
)) -> return true
366 (* dots can match against anything. return true to be safe. *)
367 | (Ast.Pdots
(_
),_
) | (_
,Ast.Pdots
(_
))
368 | (Ast.Pcircles
(_
),_
) | (_
,Ast.Pcircles
(_
)) -> return true
370 | (Ast.OptParam
(_
),_
)
371 | (Ast.UniqueParam
(_
),_
)
372 | (_
,Ast.OptParam
(_
))
373 | (_
,Ast.UniqueParam
(_
)) -> failwith
"unsupported parameter"
376 (* --------------------------------------------------------------------- *)
377 (* Define parameter *)
379 and unify_define_parameters p1 p2
=
380 match (Ast.unwrap p1
,Ast.unwrap p2
) with
381 (Ast.NoParams
,Ast.NoParams
) -> return true
382 | (Ast.DParams
(lp1
,params1
,rp1
),Ast.DParams
(lp2
,params2
,rp2
)) ->
383 unify_dots unify_define_param
dpdots params1 params2
386 and unify_define_param p1 p2
=
387 match (Ast.unwrap p1
,Ast.unwrap p2
) with
388 (Ast.DParam
(i1
),Ast.DParam
(i2
)) ->
390 | (Ast.DPComma
(_
),Ast.DPComma
(_
)) -> return true
392 (* dots can match against anything. return true to be safe. *)
393 | (Ast.DPdots
(_
),_
) | (_
,Ast.DPdots
(_
))
394 | (Ast.DPcircles
(_
),_
) | (_
,Ast.DPcircles
(_
)) -> return true
396 | (Ast.OptDParam
(_
),_
)
397 | (Ast.UniqueDParam
(_
),_
)
398 | (_
,Ast.OptDParam
(_
))
399 | (_
,Ast.UniqueDParam
(_
)) -> failwith
"unsupported parameter"
402 (* --------------------------------------------------------------------- *)
405 and unify_rule_elem re1 re2
=
406 match (Ast.unwrap re1
,Ast.unwrap re2
) with
407 (Ast.FunHeader
(_
,_
,fi1
,nm1
,lp1
,params1
,rp1
),
408 Ast.FunHeader
(_
,_
,fi2
,nm2
,lp2
,params2
,rp2
)) ->
409 conjunct_bindings (unify_fninfo fi1 fi2
)
410 (conjunct_bindings (unify_ident nm1 nm2
)
411 (unify_dots unify_parameterTypeDef
pdots params1 params2
))
412 | (Ast.Decl
(_
,_
,d1
),Ast.Decl
(_
,_
,d2
)) -> unify_declaration d1 d2
414 | (Ast.SeqStart
(lb1
),Ast.SeqStart
(lb2
)) -> return true
415 | (Ast.SeqEnd
(rb1
),Ast.SeqEnd
(rb2
)) -> return true
417 | (Ast.ExprStatement
(e1
,s1
),Ast.ExprStatement
(e2
,s2
)) ->
418 unify_expression e1 e2
419 | (Ast.IfHeader
(if1
,lp1
,e1
,rp1
),Ast.IfHeader
(if2
,lp2
,e2
,rp2
)) ->
420 unify_expression e1 e2
421 | (Ast.Else
(e1
),Ast.Else
(e2
)) -> return true
422 | (Ast.WhileHeader
(wh1
,lp1
,e1
,rp1
),Ast.WhileHeader
(wh2
,lp2
,e2
,rp2
)) ->
423 unify_expression e1 e2
424 | (Ast.DoHeader
(d1
),Ast.DoHeader
(d2
)) -> return true
425 | (Ast.WhileTail
(wh1
,lp1
,e1
,rp1
,s1
),Ast.WhileTail
(wh2
,lp2
,e2
,rp2
,s2
)) ->
426 unify_expression e1 e2
427 | (Ast.ForHeader
(fr1
,lp1
,e11
,s11
,e21
,s21
,e31
,rp1
),
428 Ast.ForHeader
(fr2
,lp2
,e12
,s12
,e22
,s22
,e32
,rp2
)) ->
430 (unify_option unify_expression e11 e12
)
432 (unify_option unify_expression e21 e22
)
433 (unify_option unify_expression e31 e32
))
434 | (Ast.IteratorHeader
(nm1
,lp1
,args1
,rp1
),
435 Ast.IteratorHeader
(nm2
,lp2
,args2
,rp2
)) ->
436 conjunct_bindings (unify_ident nm1 nm2
)
437 (unify_dots unify_expression edots args1 args2
)
438 | (Ast.DefineHeader
(_
,n1
,p1
),Ast.DefineHeader
(_
,n2
,p2
)) ->
439 conjunct_bindings (unify_ident n1 n2
)
440 (unify_define_parameters p1 p2
)
441 | (Ast.Break
(r1
,s1
),Ast.Break
(r2
,s2
)) -> return true
442 | (Ast.Continue
(r1
,s1
),Ast.Continue
(r2
,s2
)) -> return true
443 | (Ast.Label
(l1
,dd1
),Ast.Label
(l2
,dd2
)) -> unify_ident l1 l2
444 | (Ast.Goto
(g1
,l1
,dd1
),Ast.Goto
(g2
,l2
,dd2
)) -> unify_ident l1 l2
445 | (Ast.Return
(r1
,s1
),Ast.Return
(r2
,s2
)) -> return true
446 | (Ast.ReturnExpr
(r1
,e1
,s1
),Ast.ReturnExpr
(r2
,e2
,s2
)) ->
447 unify_expression e1 e2
449 | (Ast.DisjRuleElem
(res1
),_
) ->
450 disjunct_all_bindings
451 (List.map
(function x
-> unify_rule_elem x re2
) res1
)
452 | (_
,Ast.DisjRuleElem
(res2
)) ->
453 disjunct_all_bindings
454 (List.map
(function x
-> unify_rule_elem re1 x
) res2
)
456 | (Ast.MetaRuleElem
(_
,_
,_
),_
)
457 | (Ast.MetaStmt
(_
,_
,_
,_
),_
)
458 | (Ast.MetaStmtList
(_
,_
,_
),_
)
459 | (_
,Ast.MetaRuleElem
(_
,_
,_
))
460 | (_
,Ast.MetaStmt
(_
,_
,_
,_
))
461 | (_
,Ast.MetaStmtList
(_
,_
,_
)) -> return true
463 (* can match a rule_elem in different parts *)
464 | (Ast.Exp
(e1
),Ast.Exp
(e2
)) -> return true
465 | (Ast.Exp
(e1
),_
) -> subexp
(unify_expression e1
) re2
466 | (_
,Ast.Exp
(e2
)) -> subexp
(unify_expression e2
) re1
468 | (Ast.TopExp
(e1
),Ast.TopExp
(e2
)) -> unify_expression e1 e2
469 | (Ast.TopInit
(i1
),Ast.TopInit
(i2
)) -> unify_initialiser i1 i2
471 (* can match a rule_elem in different parts *)
472 | (Ast.Ty
(t1
),Ast.Ty
(t2
)) -> return true
473 | (Ast.Ty
(t1
),_
) -> subtype
(unify_fullType t1
) re2
474 | (_
,Ast.Ty
(t2
)) -> subtype
(unify_fullType t2
) re1
477 and unify_fninfo patterninfo cinfo
=
478 let patterninfo = List.sort compare
patterninfo in
479 let cinfo = List.sort compare
cinfo in
480 let rec loop = function
481 (Ast.FStorage
(sta
)::resta
,Ast.FStorage
(stb
)::restb
) ->
482 if unify_mcode sta stb
then loop (resta
,restb
) else return false
483 | (Ast.FType
(tya
)::resta
,Ast.FType
(tyb
)::restb
) ->
484 conjunct_bindings (unify_fullType tya tyb
) (loop (resta
,restb
))
485 | (Ast.FInline
(ia
)::resta
,Ast.FInline
(ib
)::restb
) ->
486 if unify_mcode ia ib
then loop (resta
,restb
) else return false
487 | (Ast.FAttr
(ia
)::resta
,Ast.FAttr
(ib
)::restb
) ->
488 if unify_mcode ia ib
then loop (resta
,restb
) else return false
489 | (x
::resta
,((y
::_
) as restb
)) ->
490 (match compare x y
with
492 | 1 -> loop (resta
,restb
)
493 | _
-> failwith
"not possible")
494 | _
-> return false in
495 loop (patterninfo,cinfo)
498 let bind = conjunct_bindings in
499 let option_default = return false in
500 let mcode r e
= option_default in
501 let expr r k e
= conjunct_bindings (f e
) (k e
) in
502 let donothing r k e
= k e
in
503 let recursor = V.combiner
bind option_default
504 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
505 donothing donothing donothing donothing
506 donothing expr donothing donothing donothing donothing donothing
507 donothing donothing donothing donothing donothing in
508 recursor.V.combiner_rule_elem
511 let bind = conjunct_bindings in
512 let option_default = return false in
513 let mcode r e
= option_default in
514 let fullType r k e
= conjunct_bindings (f e
) (k e
) in
515 let donothing r k e
= k e
in
516 let recursor = V.combiner
bind option_default
517 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
518 donothing donothing donothing donothing
519 donothing donothing fullType donothing donothing donothing donothing
520 donothing donothing donothing donothing donothing in
521 recursor.V.combiner_rule_elem
523 let rec unify_statement s1 s2
=
524 match (Ast.unwrap s1
,Ast.unwrap s2
) with
525 (Ast.Seq
(lb1
,s1
,rb1
),Ast.Seq
(lb2
,s2
,rb2
)) ->
526 conjunct_bindings (unify_rule_elem lb1 lb2
)
528 (unify_dots unify_statement sdots s1 s2
)
529 (unify_rule_elem rb1 rb2
))
530 | (Ast.IfThen
(h1
,thn1
,_
),Ast.IfThen
(h2
,thn2
,_
)) ->
531 conjunct_bindings (unify_rule_elem h1 h2
) (unify_statement thn1 thn2
)
532 | (Ast.IfThenElse
(h1
,thn1
,e1
,els1
,_
),Ast.IfThenElse
(h2
,thn2
,e2
,els2
,_
)) ->
533 conjunct_bindings (unify_rule_elem h1 h2
)
534 (conjunct_bindings (unify_statement thn1 thn2
)
535 (conjunct_bindings (unify_rule_elem e1 e2
)
536 (unify_statement els1 els2
)))
537 | (Ast.While
(h1
,s1
,_
),Ast.While
(h2
,s2
,_
)) ->
538 conjunct_bindings (unify_rule_elem h1 h2
) (unify_statement s1 s2
)
539 | (Ast.Do
(h1
,s1
,t1
),Ast.Do
(h2
,s2
,t2
)) ->
540 conjunct_bindings (unify_rule_elem h1 h2
)
541 (conjunct_bindings (unify_statement s1 s2
) (unify_rule_elem t1 t2
))
542 | (Ast.For
(h1
,s1
,_
),Ast.For
(h2
,s2
,_
)) ->
543 conjunct_bindings (unify_rule_elem h1 h2
) (unify_statement s1 s2
)
544 | (Ast.Atomic
(re1
),Ast.Atomic
(re2
)) -> unify_rule_elem re1 re2
545 | (Ast.Disj
(s1
),_
) ->
546 let s2 = Ast.rewrap
s2 (Ast.DOTS
[s2]) in
547 disjunct_all_bindings
549 (function x
-> unify_dots unify_statement sdots x
s2)
551 | (_
,Ast.Disj
(s2)) ->
552 let s1 = Ast.rewrap
s1 (Ast.DOTS
[s1]) in
553 disjunct_all_bindings
555 (function x
-> unify_dots unify_statement sdots s1 x
)
557 | (Ast.Nest
(s1,_
,_
,_
,_
),Ast.Nest
(s2,_
,_
,_
,_
)) ->
558 unify_dots unify_statement sdots s1 s2
559 | (Ast.FunDecl
(h1
,lb1
,s1,rb1
),Ast.FunDecl
(h2
,lb2
,s2,rb2
)) ->
560 conjunct_bindings (unify_rule_elem h1 h2
)
561 (conjunct_bindings (unify_rule_elem lb1 lb2
)
562 (conjunct_bindings (unify_dots unify_statement sdots s1 s2)
563 (unify_rule_elem rb1 rb2
)))
564 | (Ast.Define
(h1
,s1),Ast.Define
(h2
,s2)) ->
565 conjunct_bindings (unify_rule_elem h1 h2
)
566 (unify_dots unify_statement sdots s1 s2)
567 (* dots can match against anything. return true to be safe. *)
568 | (Ast.Dots
(_
,_
,_
,_
),_
) | (_
,Ast.Dots
(_
,_
,_
,_
))
569 | (Ast.Circles
(_
,_
,_
,_
),_
) | (_
,Ast.Circles
(_
,_
,_
,_
))
570 | (Ast.Stars
(_
,_
,_
,_
),_
) | (_
,Ast.Stars
(_
,_
,_
,_
)) -> return true
572 | (Ast.UniqueStm
(_
),_
)
574 | (_
,Ast.UniqueStm
(_
)) -> failwith
"unsupported statement"
577 let unify_statement_dots = unify_dots unify_statement sdots