Skip to content

Commit 15a17a3

Browse files
committed
Working version, but positivity check is not on
1 parent 03ed347 commit 15a17a3

7 files changed

+653
-284
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ VERSION = devel
44
# Compile with "make Q=" to display the commands that are run.
55
Q = @
66

7-
PKG = -package dedukti -package xml-light
7+
PKG = -package dedukti -package xml-light -package str
88

99
.PHONY: all
1010
all: sct

src/callgraph.ml

+111-27
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ let pp_index fmt x =
1717
Format.pp_print_int fmt (int_of_index x)
1818

1919
(** The local result express the result of the termination checker for this symbol *)
20-
type local_result = SelfLooping of (index list)
20+
type local_result = SelfLooping of string list
2121

2222
(** The pretty printer for the type [local_result] *)
2323
let pp_local_result : local_result printer =
@@ -46,57 +46,100 @@ module IMap =
4646
end)
4747
end
4848

49-
50-
(** A call [{callee; caller; matrix; is_rec}] represents a call to the function symbol with key [callee] by the function symbole with the key [caller].
51-
The [matrix] gives the relation between the parameters of the caller and the callee.
52-
The coefficient [matrix.(a).(b)] give the relation between the [a]-th parameter of the caller and the [b]-th argument of the callee.
53-
[rules] is the list of indexes of rules which lead to this call-matrix in the graph. *)
54-
type call =
55-
{ callee : index ; (** Key of the function symbol being called. *)
56-
caller : index ; (** Key of the calling function symbol. *)
57-
matrix : matrix ; (** Size change matrix of the call. *)
58-
}
49+
module EdgeLabel = struct
50+
type t = (string list * Cmp_matrix.t) list
51+
52+
let pp : t printer =
53+
fun fmt l ->
54+
Format.fprintf fmt "[%a]"
55+
(pp_list ",@." (fun fmt (a,b) -> Cmp_matrix.pp fmt b)) l
56+
57+
let add_neutral : t = []
58+
59+
let plus : t -> t -> t =
60+
let compare_cmp_matrix (m1 : Cmp_matrix.t) (m2 : Cmp_matrix.t) =
61+
assert (m1.h = m2.h);
62+
assert (m1.w = m2.w);
63+
let res = ref 0 in
64+
for i = 0 to m1.h -1 do
65+
for j = 0 to m1.w -1 do
66+
if !res = 0
67+
then
68+
res := Cmp.(match (m1.tab.(i).(j),m2.tab.(i).(j)) with
69+
| Infi, Infi -> 0
70+
| Infi, _ -> 1
71+
| _ , Infi -> -1
72+
| Zero, Zero -> 0
73+
| Zero, Min1 -> 1
74+
| Min1, Zero -> -1
75+
| Min1, Min1 -> 0)
76+
done
77+
done; !res in
78+
fun l1 l2 ->
79+
List.sort_uniq
80+
(fun (_,a) (_,b) -> compare_cmp_matrix a b) (List.append l1 l2)
81+
82+
let mult : t -> t -> t =
83+
fun l1 l2 ->
84+
List.flatten (
85+
List.map (
86+
fun (r1,x) ->
87+
List.map (fun (r2,y) -> (r1@r2,Cmp_matrix.prod x y)) l2
88+
) l1
89+
)
90+
end
91+
92+
module CallGraphAdjMat = Matrix(EdgeLabel)
5993

6094
(** Internal state of the SCT, including the representation of symbols and the call graph. *)
6195
type call_graph =
6296
{
6397
next_index : index ref ; (** The index of the next function symbol to be added *)
6498
symbols : symbol IMap.t ref ; (** A map containing every symbols studied *)
65-
calls : call list ref ; (** The list of every call *)
99+
calls : CallGraphAdjMat.t ref; (** The adjacence matrix of the call graph *)
66100
}
67101

68102
(** Create a new graph *)
69103
let new_graph : unit -> call_graph =
70104
fun () ->
71105
let syms = IMap.empty in
72-
{ next_index = ref 0; symbols = ref syms ; calls = ref [] }
106+
{
107+
next_index = ref 0;
108+
symbols = ref syms;
109+
calls = ref (CallGraphAdjMat.new_mat 0)
110+
}
73111

74112
let find_name : call_graph -> index -> string =
75113
fun gr i ->
76114
(IMap.find i !(gr.symbols)).name
77115

116+
type call = {caller : index;
117+
callee : index;
118+
matrix : Cmp_matrix.t;
119+
rule_name : string}
120+
78121
(** The pretty printer for the type [call]. *)
79122
let pp_call : call_graph -> call printer=
80-
fun gr fmt c ->
123+
fun gr fmt cc ->
81124
let res=ref "" in
82-
for i=0 to c.matrix.h -1 do
125+
for i=0 to cc.matrix.h -1 do
83126
res:=!res^"x"^(string_of_int i)^" "
84127
done;
85128
Format.fprintf fmt "%s(%s%!) <- %s%!("
86-
(find_name gr c.caller)
87-
!res (find_name gr c.callee);
88-
let jj=Array.length c.matrix.tab in
129+
(find_name gr cc.caller)
130+
!res (find_name gr cc.callee);
131+
let jj=cc.matrix.h in
89132
if jj>0 then
90-
let ii=Array.length c.matrix.tab.(0) in
133+
let ii=cc.matrix.w in
91134
for i = 0 to ii - 1 do
92135
if i > 0 then Format.fprintf fmt ",";
93136
let some = ref false in
94137
for j = 0 to jj - 1 do
95-
let c = c.matrix.tab.(j).(i) in
96-
if c <> Infi then
138+
let c = cc.matrix.tab.(j).(i) in
139+
if c <> Cmp.Infi then
97140
begin
98141
let sep = if !some then " " else "" in
99-
Format.fprintf fmt "%s%s" sep (cmp_to_string c);
142+
Format.fprintf fmt "%s%s" sep (Cmp.cmp_to_string c);
100143
some := true
101144
end
102145
done
@@ -110,23 +153,64 @@ let update_result : call_graph -> index -> local_result -> unit =
110153
let sy = (IMap.find i tbl) in
111154
sy.result <- res::sy.result
112155

113-
(** Add a new call to the call graph. *)
156+
(** Compute the transitive closure of a call_graph *)
157+
let rec trans_clos : call_graph -> unit =
158+
fun gr ->
159+
let m = !(gr.calls) in
160+
let mm = CallGraphAdjMat.sum m (CallGraphAdjMat.prod m m) in
161+
if m = mm
162+
then ()
163+
else (
164+
gr.calls := mm;
165+
trans_clos gr)
166+
167+
(** Add a new call to the call graph.
168+
We maintain the transitive closure computed at each step. *)
114169
let add_call : call_graph -> call -> unit =
115170
fun gr cc ->
116171
Debug.debug D_graph "New call: %a" (pp_call gr) cc;
117-
gr.calls := cc :: !(gr.calls)
172+
!(gr.calls).tab.(cc.caller).(cc.callee) <-
173+
([cc.rule_name],cc.matrix) :: !(gr.calls).tab.(cc.caller).(cc.callee);
174+
trans_clos gr
118175

119176
(** Add a new symb to the call graph *)
120177
let add_symb : call_graph -> symbol -> unit =
121178
fun gr sy ->
122179
gr.symbols := IMap.add !(gr.next_index) sy !(gr.symbols);
123-
incr gr.next_index
180+
incr gr.next_index;
181+
let tab =
182+
Array.init !(gr.next_index)
183+
(fun i ->
184+
Array.init !(gr.next_index)
185+
(fun j ->
186+
try !(gr.calls).tab.(i).(j)
187+
with _ -> []
188+
)
189+
) in
190+
gr.calls := {h = !(gr.calls).h +1; w = !(gr.calls).w +1; tab}
124191

125192
let graph : call_graph ref = ref (new_graph ())
126193

194+
let initialize : unit -> unit =
195+
fun () -> graph := new_graph ()
196+
197+
exception Success_index of index
198+
199+
(** [find_rule_key r] will return the key [k] which is mapped to the rule [r] *)
200+
let find_symbol_key : call_graph -> string -> index
201+
= fun gr s ->
202+
try
203+
IMap.iter
204+
(
205+
fun k x -> if x.name = s then raise (Success_index k)
206+
) !(gr.symbols);
207+
raise Not_found
208+
with Success_index k -> k
209+
127210
let index_and_arity_of : call_graph -> string -> index*int =
128211
fun gr s ->
129212
let symb = !(gr.symbols) in
130-
let k,sym = IMap.find_first (fun k -> (IMap.find k symb).name = s) symb in
213+
let k = find_symbol_key gr s in
214+
let sym = IMap.find k symb in
131215
k, sym.arity
132-
216+

src/input.ml

+123-14
Original file line numberDiff line numberDiff line change
@@ -6,40 +6,149 @@ module type Input = sig
66
type term
77
type pattern
88
type typ
9+
type rule_name
910

1011
val dig_in_rhs : term -> (string * term array) list
1112
val destruct_lhs : pattern -> (string * pattern array)
1213
val get_arity : typ -> int
13-
val compare : pattern -> term -> cmp
14+
val compare : pattern -> term -> Cmp.t
15+
val rn_to_string : rule_name -> string
1416
end
1517

1618
module StudyRules = functor (In : Input ) -> struct
1719

1820
(** Declare a symbol to be added in the call graph *)
19-
let declare : string -> In.typ -> unit =
20-
fun s t ->
21+
let declare : call_graph -> string -> In.typ -> unit =
22+
fun gr s t ->
2123
let sym = { name = s; arity = In.get_arity t; result = []} in
22-
add_symb !graph sym
24+
add_symb gr sym
2325

2426
(** Add the calls associated to a rule in the call graph *)
25-
let add_rule : In.pattern -> In.term -> unit =
26-
fun p t ->
27+
let add_rule : call_graph -> In.rule_name -> In.pattern -> In.term -> unit =
28+
fun gr rn p t ->
2729
let lhs = In.destruct_lhs p in
2830
let list_rhs = In.dig_in_rhs t in
2931
let study_call (fun_l, arg_l) (fun_r, arg_r) =
30-
let ind_l, ari_l = index_and_arity_of !graph fun_l in
31-
let ind_r, ari_r = index_and_arity_of !graph fun_r in
32-
let mat = Array.make_matrix ari_l ari_r Infi in
33-
for i=0 to min ari_l (Array.length arg_l)
32+
let ind_l, h = index_and_arity_of gr fun_l in
33+
let ind_r, w = index_and_arity_of gr fun_r in
34+
let matrix : Cmp_matrix.t =
35+
{h; w; tab = Array.make_matrix h w Cmp.Infi} in
36+
for i=0 to (min h (Array.length arg_l)) -1
3437
do
35-
for j=0 to min ari_r (Array.length arg_r)
38+
for j=0 to (min w (Array.length arg_r)) -1
3639
do
37-
mat.(i).(j) <- In.compare arg_l.(i) arg_r.(j)
40+
matrix.tab.(i).(j) <- In.compare arg_l.(i) arg_r.(j)
3841
done
3942
done;
40-
let matrix = {w = ari_l; h = ari_r; tab=mat} in
41-
add_call !graph {caller = ind_l; callee = ind_r; matrix}
43+
add_call gr {caller = ind_l; callee = ind_r; matrix;
44+
rule_name = In.rn_to_string rn }
4245
in
4346
List.iter (fun c -> study_call lhs c) list_rhs
4447

4548
end
49+
50+
module Dk = struct
51+
type term = Term.term
52+
type pattern = Rule.pattern
53+
type typ = Term.term
54+
type rule_name = Rule.rule_name
55+
56+
let string_of_name n =
57+
(Basic.string_of_mident (Basic.md n))^"."^
58+
(Basic.string_of_ident (Basic.id n))
59+
60+
let rec dig_in_rhs : term -> (string * term array) list =
61+
function
62+
| Kind
63+
| Type _
64+
| DB (_, _, _) -> []
65+
| Const (_, f) -> [string_of_name f, [||]]
66+
| App (Const(_, f), t1, l) -> (string_of_name f, Array.of_list (t1 :: l)) :: List.concat (List.map dig_in_rhs (t1::l))
67+
| App (t0, t1, l) -> List.concat (List.map dig_in_rhs (t0::t1::l))
68+
| Lam (_, _, None, t) -> dig_in_rhs t
69+
| Lam (_, _, Some ty, t) -> (dig_in_rhs ty) @ (dig_in_rhs t)
70+
| Pi (_, _, t1, t2) -> (dig_in_rhs t1) @ (dig_in_rhs t2)
71+
72+
let destruct_lhs : pattern -> (string * pattern array) =
73+
function
74+
| Pattern (_,f,l) -> (string_of_name f, Array.of_list l)
75+
| _ -> failwith "This is not a valid lhs of rule"
76+
77+
let rec get_arity : typ -> int =
78+
function
79+
| Pi (_, _, _, t) -> 1 + (get_arity t)
80+
| _ -> 0
81+
82+
let compare : pattern -> term -> Cmp.t =
83+
(** Compare a term and a pattern, using an int indicating under how many lambdas the comparison occurs *)
84+
let rec comparison : int -> term -> pattern -> Cmp.t =
85+
fun nb t p ->
86+
let rec comp_list : Cmp.t -> pattern list -> term list -> Cmp.t =
87+
fun cur lp lt ->
88+
match lp,lt with
89+
| [], _ | _, [] -> cur
90+
| a::l1, b::l2 ->
91+
begin
92+
match (comparison nb b a), cur with
93+
| _ , Infi -> assert false
94+
(* We are sure, that the current state [cur] cannot contain a Infi, else the Infi would be the result of the function and no recursive call would be needed *)
95+
| Infi, _ -> Infi
96+
| Min1, _ -> comp_list Min1 l1 l2
97+
| _ , Min1 -> comp_list Min1 l1 l2
98+
| Zero, Zero -> comp_list Zero l1 l2
99+
end
100+
in
101+
match p,t with
102+
| Var (_,_,n,_), DB (_,_,m) -> if n+nb=m then Zero else Infi (* Two distinct variables are uncomparable *)
103+
| Var (_,_,n,_), App(DB(_,_,m),_,_) -> if n+nb=m then Zero else Infi (* A variable when applied has the same size as if it was not applied *)
104+
| Lambda(_,_,Var(_,_,n,_)), DB(_,_,m) -> if n+nb=m+1 then Zero else Infi
105+
| Lambda(_,_,Var(_,_,n,_)), App(DB(_,_,m),_,_) -> if n+nb=m+1 then Zero else Infi
106+
| Pattern (_,f,lp), App(Const(_,g),t1,lt) when (name_eq f g) ->
107+
begin
108+
comp_list Zero lp (t1::lt)
109+
end
110+
| Pattern (_,_,l),t -> Cmp.minus1 (Cmp.mini (List.map (comparison nb t) l))
111+
| Lambda(_,_,pp),Lam(_,_,_,tt) -> comparison nb tt pp
112+
| _ -> Infi
113+
in fun p t -> comparison 0 t p
114+
115+
116+
let rn_to_string : rule_name -> string =
117+
function
118+
| Beta -> failwith "Beta should not occur in a rule declaration"
119+
| Delta n -> string_of_name n
120+
| Gamma(_, n) -> string_of_name n
121+
end
122+
123+
module DkRules = struct
124+
include StudyRules(Dk)
125+
126+
let rec import : loc -> mident -> unit =
127+
fun lc m ->
128+
begin
129+
let (deps,ctx,ext) = Signature.read_dko lc (string_of_mident m) in
130+
let symb (id,_,ty,_) =
131+
let cst = (string_of_mident m)^"."^(string_of_ident id) in
132+
declare !graph cst ty;
133+
in
134+
let rule (id,_,ty,rul) =
135+
List.iter
136+
(fun (r : Rule.rule_infos) ->
137+
add_rule !graph r.name (Pattern(dloc,r.cst,r.args)) r.rhs
138+
) rul
139+
in
140+
List.iter symb ctx;
141+
List.iter rule ctx
142+
end
143+
144+
and load_terms : Term.term -> unit =
145+
function
146+
| Term.Kind
147+
| Term.Type _
148+
| Term.DB (_, _, _) -> ()
149+
| Term.Const (lc, n) -> import lc (md n)
150+
| Term.App (t, u, l) -> List.iter load_terms (t::u::l)
151+
| Term.Lam (_, _, Some ty, te) -> load_terms ty; load_terms te
152+
| Term.Lam (_, _, None, te) -> load_terms te
153+
| Term.Pi (_, _, t1, t2) -> load_terms t1; load_terms t2
154+
end

0 commit comments

Comments
 (0)