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