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