File: term.ml

package info (click to toggle)
alt-ergo 0.94-2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 1,148 kB
  • sloc: ml: 15,127; makefile: 261
file content (183 lines) | stat: -rw-r--r-- 5,633 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
(**************************************************************************)
(*                                                                        *)
(*     The Alt-Ergo theorem prover                                        *)
(*     Copyright (C) 2006-2011                                            *)
(*                                                                        *)
(*     Sylvain Conchon                                                    *)
(*     Evelyne Contejean                                                  *)
(*                                                                        *)
(*     Francois Bobot                                                     *)
(*     Mohamed Iguernelala                                                *)
(*     Stephane Lescuyer                                                  *)
(*     Alain Mebsout                                                      *)
(*                                                                        *)
(*     CNRS - INRIA - Universite Paris Sud                                *)
(*                                                                        *)
(*   This file is distributed under the terms of the CeCILL-C licence     *)
(*                                                                        *)
(**************************************************************************)

open Format
open Hashcons

module Sy = Symbols

type view = {f: Sy.t ; xs: t list; ty: Ty.t; tag: int}
and t = view

type subst = t Subst.t * Ty.subst
    
module H = struct
  type t = view
  let equal t1 t2 = try
    Sy.equal t1.f t2.f 
    && List.for_all2 (==) t1.xs t2.xs 
    && Ty.equal t1.ty t2.ty
  with Invalid_argument _ -> false
      
  let hash t =
    abs (List.fold_left 
	   (fun acc x-> acc*19 +x.tag) (Sy.hash t.f + Ty.hash t.ty) 
	   t.xs)
  let tag tag x = {x with tag = tag}
end

module T = Make(H)
  
let view t = t

let rec print fmt t = 
  let {f=x;xs=l;ty=ty} = view t in
  match x, l with
    | Sy.Op Sy.Get, [e1; e2] ->
	fprintf fmt "%a[%a]" print e1 print e2

    | Sy.Op Sy.Set, [e1; e2; e3] ->
	fprintf fmt "%a[%a<-%a]" print e1 print e2 print e3

    | Sy.Op Sy.Concat, [e1; e2] ->
	fprintf fmt "%a@@%a" print e1 print e2

    | Sy.Op Sy.Extract, [e1; e2; e3] ->
	fprintf fmt "%a^{%a,%a}" print e1 print e2 print e3

    | Sy.Op op, [e1; e2] -> 
	fprintf fmt "(%a %a %a)" print e1 Sy.print x print e2

    | _, [] -> 
        if Options.debug then
          fprintf fmt "%a:%a" Sy.print x Ty.print ty
        else
          fprintf fmt "%a" Sy.print x
          
    | _, _ ->
        if Options.debug then 
          fprintf fmt "%a(%a):%a" Sy.print x print_list l Ty.print ty
        else 
          fprintf fmt "%a(%a)" Sy.print x print_list l

and print_list fmt = function
  | [] -> ()
  | [t] -> print fmt t
  | t::l -> Format.fprintf fmt "%a,%a" print t print_list l




(* fresh variables must be smaller than problem's variables.
   thus, Instead of comparinf t1.tag with t2.tag, 
   we compare t2.tag and t1.tag
   But we keep true and false as repr
 *)
let compare t1 t2 =
  let c = Pervasives.compare t2.tag t1.tag in
  if c = 0 then c else
  match (view t1).f, (view t2).f with
    | (Sy.True | Sy.False ), (Sy.True | Sy.False) -> c
    | (Sy.True | Sy.False ), _ -> -1
    | _, (Sy.True | Sy.False ) -> 1
    | _,_ -> c

let sort = List.sort compare

let make s l ty = T.hashcons {f=s;xs=l;ty=ty;tag=0 (* dumb_value *) }

let fresh_name ty = make (Sy.name (Common.fresh_string())) [] ty

let shorten t = 
  let {f=f;xs=xs;ty=ty} = view t in
  make f xs (Ty.shorten ty)

let vrai = make (Sy.True) [] Ty.Tbool
let faux = make (Sy.False) [] Ty.Tbool
let void = make (Sy.Void) [] Ty.Tunit

let int i = make (Sy.int i) [] Ty.Tint
let real r = make (Sy.real r) [] Ty.Treal
let bitv bt ty = make (Sy.Bitv bt) [] ty


let is_int t = (view t).ty= Ty.Tint
let is_real t = (view t).ty= Ty.Treal
      
let equal t1 t2 =  t1 == t2
  
let hash t = t.tag
  
let pred t = make (Sy.Op Sy.Minus) [t;int "1"] Ty.Tint
  
let dummy = make Sy.dummy [] Ty.Tint
  (* verifier que ce type est correct et voir si on ne peut pas
  supprimer ce dummy*)

module Set = 
  Set.Make(struct type t' = t type t=t' let compare=compare end)
    
module Map = 
  Map.Make(struct type t' = t type t=t' let compare=compare end)
  
let vars_of = 
  let rec vars_of s t = 
    match view t with
	{ f=(Sy.Var _ as v);xs=[]} -> Sy.Set.add v s
      | {xs=l} -> List.fold_left vars_of s l
  in fun t -> vars_of Sy.Set.empty t

let vars_of_as_term = 
  let rec vars_of_as_term s t = 
    match view t with
	{ f=(Sy.Var _ );xs=[]} -> Set.add t s
      | {xs=l} -> List.fold_left vars_of_as_term s l
  in fun t -> vars_of_as_term Set.empty t

    
let vty_of t = 
  let rec vty_of s t = 
    let {xs = xs; ty = ty} = view t in 
    List.fold_left vty_of (Ty.Svty.union s (Ty.vty_of ty)) xs
  in
  vty_of Ty.Svty.empty t

let rec apply_subst ((s_t,s_ty) as s) t = 
  let {f=f;xs=xs;ty=ty} = view t in
  try Sy.Map.find f s_t
  with Not_found -> 
    make f (List.map (apply_subst s) xs) (Ty.apply_subst s_ty ty)

let compare_subst (s_t1, s_ty1) (s_t2, s_ty2) = 
  let c = Ty.compare_subst s_ty1 s_ty2 in
  if c<>0 then c else Sy.Map.compare compare s_t1 s_t2

let fold_subst_term f (s,_) acc = Sy.Map.fold f s acc

let union_subst (s_t1, s_ty1) ((s_t2, s_ty2) as subst) = 
  let s_t = 
    Sy.Map.fold 
      (fun k x s2 -> Sy.Map.add k x s2)
      (Sy.Map.map (apply_subst subst) s_t1) s_t2
  in
  let s_ty = Ty.union_subst s_ty1 s_ty2 in
  s_t, s_ty

let rec subterms acc t = 
  let {xs=xs} = view t in List.fold_left subterms (Set.add t acc) xs