From c8a04147a79c98218508e5500ce52c48aa9a216c Mon Sep 17 00:00:00 2001
From: Sylvain Pogodalla <sylvain.pogodalla@inria.fr>
Date: Thu, 2 Jul 2009 15:28:40 +0000
Subject: [PATCH] eta expansion added

---
 src/acg-data/acg_lexicon.ml               |  12 +-
 src/acg-data/signature.ml                 | 158 ++++++++++++----------
 src/grammars/interface.ml                 |   1 +
 src/grammars/interface.mli                |   4 +
 src/grammars/syntactic_data_structures.ml |   2 +
 src/logic/lambda.ml                       |  86 +++++++++++-
 src/logic/lambda.mli                      |   9 ++
 7 files changed, 195 insertions(+), 77 deletions(-)

diff --git a/src/acg-data/acg_lexicon.ml b/src/acg-data/acg_lexicon.ml
index a792bfed..5805cc7b 100644
--- a/src/acg-data/acg_lexicon.ml
+++ b/src/acg-data/acg_lexicon.ml
@@ -39,9 +39,11 @@ struct
     | Constant of (Abstract_syntax.location * Lambda.term )
 
 
-  let interpretation_to_string i sg = match i with
+  let interpretation_to_string abstract_type_or_cst_id fun_type_from_id i sg = match i with
     | Type (_,t) -> Printf.sprintf "\t%s" (Lambda.type_to_string t (Sg.id_to_string sg))
-    | Constant (_,c) -> Printf.sprintf "\t%s" (Lambda.term_to_string c (Sg.id_to_string sg))
+    | Constant (_,c) -> 
+	let eta_long = Sg.eta_long_form c (fun_type_from_id abstract_type_or_cst_id) sg  in
+	  Printf.sprintf "\t%s [eta-long form: %s {%s}]" (Lambda.term_to_string c (Sg.id_to_string sg)) (Lambda.term_to_string eta_long (Sg.id_to_string sg) ) (Lambda.raw_to_string eta_long)
 
   type t = {name:string*Abstract_syntax.location;
 	    dico:interpretation Dico.t;
@@ -103,7 +105,7 @@ struct
     | Abstract_syntax.Type (id,loc,ty) -> {lex with dico=Dico.add id (Type (loc,Sg.convert_type ty lex.object_sig)) d}
     | Abstract_syntax.Constant (id,loc,t) -> {lex with dico=Dico.add id (Constant (loc,Sg.typecheck t (interpret_type (Sg.type_of_constant id lex.abstract_sig) lex) lex.object_sig)) d}
 
-  let to_string {name=n,_;dico=d;abstract_sig=abs_sg;object_sig=obj_sg} =
+  let to_string ({name=n,_;dico=d;abstract_sig=abs_sg;object_sig=obj_sg} as lex) =
     Printf.sprintf
       "lexicon %s(%s): %s =\n%send"
       n
@@ -112,8 +114,8 @@ struct
       (match 
 	 Dico.fold
 	   (fun k i -> function
-	      | None -> Some (Printf.sprintf "\t%s := %s;" k (interpretation_to_string i obj_sg))
-	      | Some a -> Some (Printf.sprintf "%s\n\t%s := %s;" a k (interpretation_to_string i obj_sg)))
+	      | None -> Some (Printf.sprintf "\t%s := %s;" k (interpretation_to_string k (fun id -> interpret_type (Sg.type_of_constant id abs_sg) lex) i obj_sg))
+	      | Some a -> Some (Printf.sprintf "%s\n\t%s := %s;" a k (interpretation_to_string k (fun id -> interpret_type (Sg.type_of_constant id abs_sg) lex) i obj_sg)))
 	   d
 	   None with
 	     | None -> ""
diff --git a/src/acg-data/signature.ml b/src/acg-data/signature.ml
index f63aff8d..f752d7bd 100644
--- a/src/acg-data/signature.ml
+++ b/src/acg-data/signature.ml
@@ -62,6 +62,8 @@ struct
   exception Duplicate_type_definition
   exception Duplicate_term_definition
 
+  exception Not_yet_implemented
+
   type entry = sig_entry
 
   type t = {name:string*Abstract_syntax.location;
@@ -82,6 +84,21 @@ struct
       | Term_definition(s,_,behavior,_,_) -> behavior,s
 
 
+  let type_to_string ty sg = Lambda.type_to_string ty (id_to_string sg)
+    
+  let term_to_string t sg = 
+    Lambda.term_to_string
+      t
+      (id_to_string sg)
+      (* (fun i -> match Id.find i ids with |
+	 Term_declaration(s,_,_) ->
+	 Abstract_syntax.Default,s |
+	 Term_definition(s,_,_,_) ->
+	 Abstract_syntax.Default,s | _ ->
+	 failwith "Call a term on a
+	 type")*)
+
+
   let empty n = {name=n;size=0;terms=Symbols.empty;types=Symbols.empty;ids=Id.empty}
 
   let name {name=n} = n
@@ -90,13 +107,13 @@ struct
     try
       match Symbols.find s syms with
 	| Type_declaration (x,id,_) when x=s -> Lambda.Atom id
-	| Type_declaration _ -> failwith "Bug"
+	| Type_declaration _ -> failwith "Bug in find_atomic_type"
 	| Type_definition (x,id,_,_) when x=s -> Lambda.DAtom id
-	| Type_definition _ -> failwith "Bug"
-	| Term_declaration _ -> failwith "Bug"
-	| Term_definition _ -> failwith "Bug"
+	| Type_definition _ -> failwith "Bug in find_atomic_type"
+	| Term_declaration _ -> failwith "Bug in find_atomic_type"
+	| Term_definition _ -> failwith "Bug in find_atomic_type"
     with
-      | Not_found -> failwith "Bug"
+      | Not_found -> failwith "Bug in find_atomic_type"
 
 
   let rec convert_type ty ({types=syms} as sg) = 
@@ -136,7 +153,7 @@ struct
       | Lambda.DAtom i ->
 	  (match Id.find i ids with
 	     | Type_definition (_,_,_,ty1) -> expand_type ty1 sg
-	     | _ -> failwith "Bug")
+	     | _ -> failwith "Bug in expand type")
       | Lambda.LFun (ty1,ty2) -> Lambda.LFun(expand_type ty1 sg,expand_type ty2 sg)
       | Lambda.Fun (ty1,ty2) -> Lambda.Fun(expand_type ty1 sg,expand_type ty2 sg)
       | _ -> failwith "Not yet implemented"
@@ -144,7 +161,7 @@ struct
   let unfold_type_definition i ({ids=ids} as sg) = 
     match Id.find i ids with
       | Type_definition (_,_,_,ty1) -> expand_type ty1 sg
-      | _ -> failwith "Bug"
+      | _ -> failwith "Bug in unfold_type_definition"
 
 
   let rec expand_term t ({ids=ids} as sg) = 
@@ -153,7 +170,7 @@ struct
       | Lambda.DConst i ->
 	  (match Id.find i ids with
 	     | Term_definition (_,_,_,_,u) -> expand_term u sg
-	     | _ -> failwith "Bug")
+	     | _ -> failwith "Bug in expand term")
       | Lambda.Abs (x,u) -> Lambda.Abs (x,expand_term u sg)
       | Lambda.LAbs (x,u) -> Lambda.LAbs (x,expand_term u sg)
       | Lambda.App (u,v) -> Lambda.App (expand_term u sg,expand_term v sg)
@@ -162,10 +179,19 @@ struct
   let unfold_term_definition i ({ids=ids} as sg) = 
     match Id.find i ids with
       | Term_definition (_,_,_,_,t) -> expand_term t sg
-      | _ -> failwith "Bug"
+      | _ -> failwith "Bug in unfold_term_definition"
 	  
 	  
 
+  let get_type_of_const_id i ({ids=ids} as sg) =
+    try
+      match Id.find i ids with
+	| Term_declaration (_,_,_,ty) -> expand_type ty sg
+	| Term_definition (_,_,_,ty,_) -> expand_type ty sg
+	| _ -> failwith "Should be applied only on constants"
+    with
+      | Id.Not_found -> failwith "Bug in get_type_of_const_id"
+
   let rec decompose_functional_type ty ({ids=ids} as sg) =
     match ty with
       | Lambda.LFun (ty1,ty2) -> ty1,ty2,Abstract_syntax.Linear
@@ -173,7 +199,7 @@ struct
       | Lambda.DAtom i ->
 	  (match Id.find i ids with
 	     | Type_definition (_,_,_,ty1) -> decompose_functional_type ty1 sg
-	     | _ -> failwith "Bug")
+	     | _ -> failwith "Bug in decompose_functional_type")
       | _ -> raise Not_functional_type
 
 
@@ -196,13 +222,13 @@ struct
   (* [get_typing x loc typing_env] returns [l,t,e] where [l] is the
      level of [x] and [t] its type in the typing environment
      [typing_env] when [x] is a variable located at [loc]. [e] is the
-     new environment where [x] as been marcked as used at location
-     [l]. If [x] has been used alread once (this is marked by the [Some
-     l], 3rd projection in the association list), the function raises
-     [Not_linear l] where [l] is the location of the former usage of
-     [x]. If [x] is not in the typing environment [typing_env], it
-     raises Not_found *)
-	  
+     new environment where [x] as been marked as used at location
+     [l]. If [x] has been used alread once (this is marked by the
+     [Some l], 3rd projection in the association list), the function
+     raises [Not_linear l] where [l] is the location of the former
+     usage of [x]. If [x] is not in the typing environment
+     [typing_env], it raises Not_found *)
+	    
   let get_typing x loc lst =
     let rec get_typing_aux lst k =
       match lst with
@@ -232,7 +258,7 @@ struct
     let () = Printf.printf "Linear environment:\n%s\n" (Utils.string_of_list "\n" (fun (x,(l,ty,u)) -> Printf.sprintf "%s (%d): %s (%s)" x l (Lambda.type_to_string ty f) (match u with | None -> "Not used" | Some _ -> "Used")) l_env) in
     let () = Printf.printf "Non linear environment:\n%s\n" (Utils.string_of_list "\n" (fun (x,(l,ty)) -> Printf.sprintf "%s (%d): %s" x l (Lambda.type_to_string ty f) ) env) in
       Printf.printf "Next usage:\n%s\n" (Utils.string_of_list "\n" (fun (x,ab) -> Printf.sprintf "%s : %s" x (match ab with | Abstract_syntax.Linear -> "Linear" | _ -> "Non Linear")) lin)
-      
+	
   type typing_env_content = 
     | Delay of (int -> int -> Abstract_syntax.location -> Lambda.term)
     | Eval of (int -> int -> Abstract_syntax.location -> (Lambda.term * typing_env_content))
@@ -419,8 +445,15 @@ struct
 	| Not_linear ((s1,e1),(s2,e2)) -> raise (Error.Error (Error.Type_error (Error.Two_occurrences_of_linear_variable (s2,e2),(s1,s1))))
 	| Vacuous_abstraction (x,l1,l2) -> raise (Error.Error (Error.Type_error (Error.Vacuous_abstraction (x,l2),l1)))
 	    
+  (* We assume here that [term] is well typed and in beta-normal form
+     and that types and terms definitions have been unfolded*)
 	    
-	    
+  let eta_long_form term stype sg =      
+    Lambda.eta_long_form (Lambda.normalize (expand_term term sg)) (expand_type stype sg) (fun id -> get_type_of_const_id id sg)
+			   
+			   
+			   
+			   
   let add_entry e ({size=s} as sg) =
     match e with
       | Abstract_syntax.Type_decl (t,_,Abstract_syntax.K k) -> 
@@ -434,7 +467,7 @@ struct
 	  let t_type = convert_type ty sg in
 	  let t_term = typecheck term t_type sg in
 	    add_sig_term t (Term_definition (t,s,behavior,t_type,t_term)) sg
-	      
+				     
   let is_type s {types=syms} =
     try
       match Symbols.find s syms with
@@ -443,7 +476,7 @@ struct
 	| _ -> false
     with
       | Symbols.Not_found -> false
-	  
+				 
   let is_constant s {terms=syms} =
     try
       match Symbols.find s syms with
@@ -452,47 +485,36 @@ struct
 	| _ -> false,None
     with
       | Symbols.Not_found -> false,None
-
+				 
   let add_warnings _ sg = sg
-
+			   
   let get_warnings _  = []
-
-  let type_to_string ty sg = Lambda.type_to_string ty (id_to_string sg)
-
-  let term_to_string t sg = 
-    Lambda.term_to_string
-      t
-      (id_to_string sg)
-      (*      (fun i -> 
-	      match Id.find i ids with
-	      | Term_declaration(s,_,_) -> Abstract_syntax.Default,s
-	      | Term_definition(s,_,_,_) -> Abstract_syntax.Default,s
-	      | _ -> failwith "Call a term on a type")*)
-
+    
+      
   let raw_to_string t = Lambda.raw_to_string t
-
+    
   let behavior_to_string = function
     | Abstract_syntax.Default -> ""
     | Abstract_syntax.Prefix -> "prefix "
     | Abstract_syntax.Infix -> "infix "
     | Abstract_syntax.Binder -> "binder "
-      
+	
   let entry_to_string f = function
     | Type_declaration(s,_,k) -> Printf.sprintf "\t%s : %s;" s (Lambda.kind_to_string k f)
     | Type_definition(s,_,k,ty) -> Printf.sprintf "\t%s = %s : %s;" s (Lambda.type_to_string ty f) (Lambda.kind_to_string k f)
     | Term_declaration(s,_,behavior,ty) -> Printf.sprintf "\t%s%s : %s;" (behavior_to_string behavior) s (Lambda.type_to_string ty f)
     | Term_definition(s,_,behavior,ty,t) -> Printf.sprintf "\t%s%s = %s : %s;" (behavior_to_string behavior) s (Lambda.term_to_string t f) (Lambda.type_to_string ty f)
-
+	
   let to_string ({name=n;ids=ids} as sg) =
     Printf.sprintf "signature %s = \n%send\n"
       (fst n)
       (fst (Id.fold 
-	 (fun _ e (acc,b) ->
-	    match b with
-	      | true -> Printf.sprintf "%s%s\n" acc (entry_to_string (id_to_string sg) e),true
-	      | false -> Printf.sprintf "%s\n" (entry_to_string (id_to_string sg) e),true)
-	 ("",false)
-	 ids))
+	      (fun _ e (acc,b) ->
+		 match b with
+		   | true -> Printf.sprintf "%s%s\n" acc (entry_to_string (id_to_string sg) e),true
+		   | false -> Printf.sprintf "%s\n" (entry_to_string (id_to_string sg) e),true)
+	      ("",false)
+	      ids))
 
   let convert_term t ty sg =
     let t_type = convert_type ty sg in
@@ -501,11 +523,11 @@ struct
   let type_of_constant x ({terms=syms} as sg) =
     try
       match Symbols.find x syms with
-      | Term_declaration (s,_,_,ty) when x = s -> ty
-      | Term_definition (s,_,_,ty,_) when x = s -> ty
-      | _ -> failwith "Bug"
+	| Term_declaration (s,_,_,ty) when x = s -> ty
+	| Term_definition (s,_,_,ty,_) when x = s -> ty
+	| _ -> failwith "Bug in type_of_constant"
     with
-      | Symbols.Not_found -> failwith "Bug"
+      | Symbols.Not_found -> failwith "Bug in type_of_constant"
 
   let fold f a {ids=ids} =
     Id.fold
@@ -522,32 +544,32 @@ struct
 end	  
   
 module Table = Table.Make_table(struct let b = 10 end)
-(*module Table =
-struct
-  module IntMap = Map.Make(struct type t=int let compare i j = i-j end)
-  type 'a t = 'a IntMap.t
-  type key = int
-
-  exception Conflict
-  let empty = IntMap.empty
-  let add ?(override=false) k v t = 
+  (*module Table =
+    struct
+    module IntMap = Map.Make(struct type t=int let compare i j = i-j end)
+    type 'a t = 'a IntMap.t
+    type key = int
+
+    exception Conflict
+    let empty = IntMap.empty
+    let add ?(override=false) k v t = 
     try 
-      let _ = IntMap.find k t in
-	if override then IntMap.add k v t else raise Conflict
+    let _ = IntMap.find k t in
+    if override then IntMap.add k v t else raise Conflict
     with
-      | Not_found -> IntMap.add k v t
+    | Not_found -> IntMap.add k v t
 
 
-  exception Not_found
+    exception Not_found
 
-  let find k t = 
+    let find k t = 
     try
-      IntMap.find k t
+    IntMap.find k t
     with
-      | Not_found -> raise Not_found
-  let fold f acc t = IntMap.fold f t acc
-end
-*)
+    | Not_found -> raise Not_found
+    let fold f acc t = IntMap.fold f t acc
+    end
+  *)
 
 module Sylvains_signature = Make(Tries.Tries)(Table)
 
diff --git a/src/grammars/interface.ml b/src/grammars/interface.ml
index e98da5ce..4c8e724c 100644
--- a/src/grammars/interface.ml
+++ b/src/grammars/interface.ml
@@ -50,6 +50,7 @@ sig
   val fold : (entry -> 'a -> 'a) -> 'a -> t -> 'a
   val get_binder_argument_functional_type : string -> t -> Abstract_syntax.abstraction option
   val is_declared : entry -> t -> string option
+  val eta_long_form : term -> stype -> t -> term
 end
 
 module type Lexicon_sig =
diff --git a/src/grammars/interface.mli b/src/grammars/interface.mli
index 28baa116..87b09cc0 100644
--- a/src/grammars/interface.mli
+++ b/src/grammars/interface.mli
@@ -135,6 +135,10 @@ sig
       [None] otherwise *)
   val is_declared : entry -> t -> string option
 
+    (** [eta_long_form t ty sg] returns the eta-long form of [t] with
+	respect to the type [ty] and signature [sg]*)
+  val eta_long_form : term -> stype -> t -> term
+
 end
 
 (** This module signature describes the interface for modules implementing lexicons *)
diff --git a/src/grammars/syntactic_data_structures.ml b/src/grammars/syntactic_data_structures.ml
index f5a83ced..452e040f 100644
--- a/src/grammars/syntactic_data_structures.ml
+++ b/src/grammars/syntactic_data_structures.ml
@@ -295,6 +295,8 @@ struct
     let get_binder_argument_functional_type _ _ = Some Abstract_syntax.Linear
 
     let is_declared _ _ = None
+      
+    let eta_long_form _ _ _ = failwith "Not implemented: useless"
 
   let raw_to_string _ = failwith "TUTUTUT"
 
diff --git a/src/logic/lambda.ml b/src/logic/lambda.ml
index 58d563d7..ff205192 100644
--- a/src/logic/lambda.ml
+++ b/src/logic/lambda.ml
@@ -82,13 +82,13 @@ module Lambda =
      let rec unfold_labs acc level env = function
        | LAbs (x,t) ->
 	   let x' = generate_var_name x env in
-	     unfold_labs ((level,x')::acc) (level+1) env t
+	     unfold_labs ((level,x')::acc) (level+1) ((level,x')::env) t
        | t -> acc,level,t
 
      let rec unfold_abs acc level env = function
        | Abs (x,t) -> 
 	   let x' = generate_var_name x env in
-	     unfold_abs ((level,x')::acc) (level+1) env t
+	     unfold_abs ((level,x')::acc) (level+1) ((level,x')::env) t
        | t -> acc,level,t
 
      let rec unfold_app acc = function
@@ -163,7 +163,7 @@ module Lambda =
 	   | DConst i -> let _,x = id_to_sym i in x,true
 	   | Abs (x,t) ->
 	       let x' = generate_var_name x env in
-	       let vars,l,u=unfold_abs [level,x'] (level+1) env t in
+	       let vars,l,u=unfold_abs [level,x'] (level+1) ((level,x')::env) t in
 		 Printf.sprintf
 		   "Lambda %s. %s"
 		   (Utils.string_of_list " " (fun (_,x) -> x) (List.rev vars))
@@ -171,7 +171,7 @@ module Lambda =
 	       false
 	   | LAbs (x,t) ->
 	       let x' = generate_var_name x l_env in
-	       let vars,l,u=unfold_labs [l_level,x'] (l_level+1) l_env t in
+	       let vars,l,u=unfold_labs [l_level,x'] (l_level+1) ((l_level,x')::l_env) t in
 		 Printf.sprintf
 		   "lambda %s. %s"
 		   (Utils.string_of_list " " (fun (_,x) -> x) (List.rev vars))
@@ -492,5 +492,83 @@ module Lambda =
        in
        convert (type_normalize ty1) (type_normalize ty2)
 
+     let eta_expand t ty = 
+       let wrap t abstraction l_level nl_level =
+	 let f,l_length,nl_length,abs'=
+	   List.fold_left
+	     (fun (f,l_depth,nl_depth,acc) abs ->
+		match abs with
+		  | LVar _ -> (fun x -> App(f x,LVar (l_level-l_depth))),l_depth+1,nl_depth,abs::acc
+		  | Var _ -> (fun x -> App(f x,Var (nl_level-nl_depth))),l_depth,nl_depth+1,abs::acc
+		  | _ -> failwith "eta_expand should not be called here")
+	     ((fun x -> x),1,1,[])
+	     abstraction in
+	   List.fold_left
+	     (fun t abs ->
+		match abs with
+		  | Var _ -> Abs("x",t)
+		  | LVar _ -> LAbs("x",t)
+		  | _ -> failwith "eta_expand should not be called here")
+	     (f (lift (l_length-1) (nl_length-1) t))
+	     abs' in
+       let rec eta_expand_rec ty l_level nl_level acc =
+	 match ty with
+	   | Atom _ -> wrap t acc l_level nl_level 
+	   | DAtom _ -> failwith "type definitions should have been unfolded"
+	   | LFun (a,b) -> eta_expand_rec b (l_level+1) nl_level ((LVar 0)::acc)
+	   | Fun (a,b) -> eta_expand_rec b l_level (nl_level+1) ((Var 0)::acc)
+	   | _ -> failwith "Not yet implemented" in
+       let t' = eta_expand_rec ty 0 0 [] in
+	 t'
+	   
+       
+    (* We assume here that [term] is well typed and in beta-normal form
+       and that types and terms definitions have been unfolded*)
+     let eta_long_form term stype f_get_type_of_constant =  
+       let rec eta_long_form_rec term stype  linear_typing_env non_linear_typing_env =
+	 match term,stype with
+	   | LVar i , Some ty when ty = List.nth linear_typing_env i -> eta_expand term ty,ty
+	   | LVar i , Some _ -> failwith "Term should be well typed"
+	   | LVar i , None ->
+	       let ty = List.nth linear_typing_env i in
+		 eta_expand term ty,ty
+	   | Var i , Some ty when ty = List.nth non_linear_typing_env i -> eta_expand term ty,ty
+	   | Var i , Some _ -> failwith "Term should be well typed"
+	   | Var i , None ->
+	       let ty = List.nth non_linear_typing_env i in
+		 eta_expand term ty,ty
+	   | Const i , Some ty  -> eta_expand term ty,ty
+	   | Const i , None -> 
+	       let ty = f_get_type_of_constant i in
+		 eta_expand term ty,ty
+	   | DConst _ ,_ -> failwith "All the definitions should have been unfolded"
+	   | Abs (x,t),Some (Fun(a,b) as ty) -> 
+	       let t',_ = eta_long_form_rec t (Some b) linear_typing_env (a::non_linear_typing_env) in
+		 Abs(x,t'),ty
+	   | Abs (x,t), None -> failwith "Should be in beta normal form"
+	   | LAbs (x,t),Some (LFun(a,b) as ty) -> 
+	       let t',_ = eta_long_form_rec t (Some b) (a::linear_typing_env) non_linear_typing_env in
+		 LAbs(x,t'),ty
+	   | LAbs (x,t), None -> failwith "Should be in beta normal form"
+	   | App (u,v) , None ->
+	       let u',u_type = eta_long_form_rec u None linear_typing_env non_linear_typing_env in
+		 (match u_type with
+		    | (Fun (a,b)|LFun(a,b)) ->
+			let v',v_type =eta_long_form_rec v (Some a) linear_typing_env non_linear_typing_env  in
+			  eta_expand (normalize (App (u',v'))) b, b
+		    | _ -> failwith "Should be well typed")
+	   | App (u,v) , Some ty ->
+	       let u',u_type = eta_long_form_rec u None linear_typing_env non_linear_typing_env in
+		 (match u_type with
+		    | (Fun (a,b)|LFun(a,b)) when ty=b ->
+			let v',v_type =eta_long_form_rec v (Some a) linear_typing_env non_linear_typing_env  in
+			  eta_expand (normalize (App (u',v'))) b, b
+		    | _ -> failwith "Should be well typed")
+	   | _ -> raise Not_yet_implemented in
+       let t',_ = eta_long_form_rec term (Some stype) [] [] in
+	 normalize t'
+
+
+
 
   end
diff --git a/src/logic/lambda.mli b/src/logic/lambda.mli
index a213a35f..51c6f360 100644
--- a/src/logic/lambda.mli
+++ b/src/logic/lambda.mli
@@ -70,5 +70,14 @@ sig
   val term_to_string : term -> (int -> Abstract_syntax.syntactic_behavior * string) -> string
   val raw_to_string : term -> string
   val normalize : ?id_to_term:(int -> term) -> term -> term
+    
+
+  (** [eta_long_form t ty type_of_cst] returns the eta-long form of
+      [t] with respect of type [ty]. [t] is supposed to be in
+      beta-normal form and all the definitions of [t] and [ty] should
+      have been unfolded. [type_of_cst i] is a function that returns
+      the type (with unfolded definitions) of the constant whose id is
+      [i]. [i] is supposed to be an actual id of a constant.*)
+  val eta_long_form : term -> stype -> (int -> stype) -> term
 
 end
-- 
GitLab