From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.1.3 (2006-06-01) on yquem.inria.fr X-Spam-Level: * X-Spam-Status: No, score=1.5 required=5.0 tests=AWL,NO_REAL_NAME,SPF_FAIL autolearn=disabled version=3.1.3 X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr Received: from concorde.inria.fr (concorde.inria.fr [192.93.2.39]) by yquem.inria.fr (Postfix) with ESMTP id E8ED5BC68 for ; Tue, 26 Sep 2006 10:05:09 +0200 (CEST) Received: from selenite.metnet.navy.mil (selenite.metnet.navy.mil [192.16.167.32]) by concorde.inria.fr (8.13.6/8.13.6) with ESMTP id k8Q852ZG006636 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL) for ; Tue, 26 Sep 2006 10:05:09 +0200 Received: (qmail 4931 invoked by uid 107); 26 Sep 2006 08:04:58 -0000 Received: from unknown (HELO Adric.metnet.fnmoc.navy.mil) (10.100.105.102) by selenite.metnet.navy.mil with SMTP; 26 Sep 2006 08:04:58 -0000 Received: by Adric.metnet.fnmoc.navy.mil (Postfix, from userid 760) id 5B3B7AC04; Tue, 26 Sep 2006 01:01:20 -0700 (PDT) To: caml-list@inria.fr, John.Harrison@cl.cam.ac.uk Subject: Listing toplevel bindings Reply-To: oleg@pobox.com Errors-To: oleg@okmij.org From: oleg@pobox.com Message-Id: <20060926080120.5B3B7AC04@Adric.metnet.fnmoc.navy.mil> Date: Tue, 26 Sep 2006 01:01:20 -0700 (PDT) X-Miltered: at concorde with ID 4518DF2E.002 by Joe's j-chkmail (http://j-chkmail.ensmp.fr)! X-Spam: no; 0.00; toplevel:01 bindings:01 oleg:01 ocaml:01 toplevel:01 bindings:01 recompile:01 ocaml:01 oleg:01 genprintval:01 cmo:01 val:01 val:01 toploop:01 metaocaml:01 John Harrison wrote: > When inside the OCaml toplevel, is there any way of getting a list of > all (top-level) bindings of names to objects of some specified type 'a? Yes, there is. No need to recompile anything. However, you need the OCaml installation directory (after your have compiled the top-level and before you did make clean). First, please retrieve the following file http://pobox.com/~oleg/ftp/ML/gprint/gprint_toplevel.ml and adjust the paths in the "directory" directives to point to your OCaml installation directory. Please run your Ocaml top-level and execute all #directory and the #load directives in that file up to, but not including the loading of genprintval.cmo. Please do NOT change the order of the load directives! It took about half an hour to find the right order.... Next, please enter the code given in the appendix of this message. The code will print the signature of the values in the existing top-level environment. For example: binding: get_value_bindings/79 val get_value_bindings : Env.t -> (Ident.t * Types.value_description) list binding: print_bindings/107 val print_bindings : Format.formatter -> (Ident.t * Types.value_description) list -> unit Done - : unit = () We then can enter # let x = 1;; val x : int = 1 # let x = 2;; val x : int = 2 # let y = 10;; val y : int = 10 # print_int_toplevel Format.std_formatter (get_value_bindings (!Toploop.toplevel_env));; binding: x/186 value: 2 binding: x/187 value: 2 binding: y/188 value: 10 Done - : unit = () As we can see, the type environment keeps track of all the previous definitions of a name. Because "x" was defined twice, there are two entries in the type environment: "x/186" and "x/187". The counter is the timestamp. The top-level value environment keeps the last value, however. The function print_int_toplevel cannot, generally, be polymorphic over type -- unless you're willing to assume responsibility that your type representation string matches your desired type -- or you're willing to use MetaOCaml. Appendix. open Ident;; open Env;; let get_value_bindings env = let rec get_val acc = function | Env_empty -> acc | Env_value (next, ident, val_descr) -> get_val ((ident,val_descr)::acc) next | Env_type (next,_,_) -> get_val acc next | Env_exception (next,_,_) -> get_val acc next | Env_module (next,_,_) -> get_val acc next | Env_modtype (next,_,_) -> get_val acc next | Env_class (next,_,_) -> get_val acc next | Env_cltype (next,_,_) -> get_val acc next | Env_open (next,_) -> get_val acc next in get_val [] (summary env); ;; let print_bindings ppf bindings = List.iter (fun (ident,val_descr) -> Format.fprintf ppf "@\nbinding: "; Ident.print ppf ident; Format.fprintf ppf "@ @ @ "; Printtyp.value_description ident ppf val_descr) bindings; Format.fprintf ppf "@\nDone@." ;; print_bindings Format.std_formatter (get_value_bindings (!Toploop.toplevel_env));; let type_to_str (x : Types.type_expr) = Printtyp.type_expr Format.str_formatter x; Format.flush_str_formatter ();; (* Print all top-level int bindings *) let print_int_toplevel ppf bindings = let print_int_binding (ident,val_descr) = if type_to_str val_descr.Types.val_type = "int" then begin Format.fprintf ppf "@\nbinding: "; Ident.print ppf ident; Format.fprintf ppf " value: %d" (Obj.obj (Toploop.getvalue (name ident))); end else () in List.iter print_int_binding bindings; Format.fprintf ppf "@\nDone@." ;; print_int_toplevel Format.std_formatter (get_value_bindings (!Toploop.toplevel_env));;