caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Anil Madhavapeddy <anil@recoil.org>
To: Michael <michipili@gmail.com>
Cc: caml-list@inria.fr
Subject: Re: [Caml-list] Re: Opening a module from toploop startup
Date: Tue, 9 Jul 2013 10:36:20 +0100	[thread overview]
Message-ID: <EA82C5EE-41A1-4DDA-A635-BE7A4CFFF853@recoil.org> (raw)
In-Reply-To: <51DBD740.3020109@gmail.com>

This (rather rough) snippet of code is what we're using in Real World OCaml to automate the output generation. It's in turn based on Christophe's code from http://github.com/ocaml/ocaml.org.  It does run a set of initial phrases to activate and open Core, which is what you're looking for.

https://gist.github.com/avsm/5949199

It won't quite compile out of the box, and it requires 4.01.0dev+trunk due to its use of short_paths, so it's best to crib from it than try to use it directly.

One downside to the current toplevel is that it's rather hard to distinguish compiler output from the program output.  We'll either switch to utop (which has support for this), or modify this toplevel to pass the compiler output formatter a separate fd from the stdin/stdout so that they can be distinguished more clearly.

Hope that helps,
Anil

On 9 Jul 2013, at 10:26, Michael <michipili@gmail.com> wrote:

> Just a gentle ping on this one…
> 
> Maybe could someone suggest an open-source project where customisation of the toplevel takes place?
> 
> Also I am sorry about the poor formatting of my original message, I got tripped by HTML editing. The clean code is:
> ~~~~~~~~~
> open Format
> 
> module Tag =
> struct
>  type t = int
>  let format fft tag =
>    fprintf fft "Tag#%d" tag
>  let test_open_module () =
>    true
> end
> 
> let libdir = [
>  "/usr/local/lib/ocaml/compiler-libs";
> ]
> 
> let execute_phrase ident phrase =
>  if Toploop.execute_phrase false Format.std_formatter phrase
>  then
>    ()
>  else
>    failwith ident
> 
> let rec make_path_rev p =
>  match p with
>  | [] -> invalid_arg "make_path_rev"
>  | h :: [] -> Longident.Lident h
>  | h :: t -> Longident.Ldot (make_path_rev t, h)
> 
> let make_path p =
>  make_path_rev (List.rev p)
> 
> let install_printer path =
>  let longident = make_path_rev ("format" :: List.rev path) in
>  let phrase = Parsetree.Ptop_dir(
>    "install_printer", Parsetree.Pdir_ident longident
>  )
>  in
>  execute_phrase "install_printer" phrase
> 
> 
> let open_module p =
>  let open Parsetree in
>  let open Location in
>  let open Asttypes in
>  let loc = {
>    loc_start = Lexing.dummy_pos;
>    loc_end = Lexing.dummy_pos;
>    loc_ghost = false
>  }
>  in
>  let phrase = Ptop_def [
>    {
>      pstr_desc =
>    Pstr_open {
>      txt = make_path p;
>      loc;
>    };
>      pstr_loc = loc
>    };
>  ]
>  in
>  execute_phrase "open_module" phrase
> 
> let startup () =
>  begin
>    List.iter Topdirs.dir_directory libdir;
>    List.iter install_printer [["Demonstrate"; "Tag"]];
>    List.iter open_module [["Demonstrate"]; ["Demonstrate"; "Tag" ]];
>  end
> 
> let _ =
>  Toploop.toplevel_startup_hook := startup
> ~~~~~~~~~
> 
> Michael Le Barbier Grünewald schrieb:
>> Dear Camlers,
>> 
>> I am learning to produce customised toplevel loops and, while I was able
>> to automatically add custom printers, could not open modules.
>> 
>> Obviously, there is something I should know, and don't… could someone
>> help me?
>> 
>> My code (working example, see below) is a bit long, so let me outline it:
>> 
>> The _startup_ procedure issues a few toploop directives, adding search
>> directories, installing printers for the given modules (currently one)
>> and opening them.
>> 
>> _open_module_ and _install_printer_ produce and interpret toplevel
>> phrases corresponding to the directives with the same name.
>> 
>> Tank you for your help,
>> Michael
>> 
>> 
>> ----8<----
>> Compile:
>> 
>>     |ocamlfind ocamlc -c -package "compiler-libs" -o demonstrate.cmo
>>     demonstrate.ml|||
>>     |||ocamlfind ocamlmktop -package "compiler-libs" -custom -linkall
>>     -dllpath-all -linkpkg -package "compiler-libs" demonstrate.cmo -o
>>     mytoplevel|||
>>     ||
>> 
>> Demonstrate that the Demonstrate.Tag module is not opened:
>> 
>>     |> ./mytoplevel|||
>>     |||        OCaml version 4.00.1|||
>>     ||||
>>     |||# test_open_module;;|||
>>     |||Error: Unbound value test_open_module|||
>>     |||# ^D|||
>>     ||
>> 
>> Demonstrate that the custom printer is installed:
>> 
>>     |> ./mytoplevel|||
>>     |||        OCaml version 4.00.1|||
>>     ||||
>>     |||# open Demonstrate;;|||
>>     |||# (5 : Tag.t);;|||
>>     |||- : Demonstrate.Tag.t = Tag#5|||
>>     |||# ^D|
>> 
>> The whole code:
>> ~~~~
>> |open Format||
>> ||
>> ||module Tag =||
>> ||struct||
>> ||  type t = int||
>> ||  let format fft tag =||
>> ||    fprintf fft "Tag#%d" tag||
>> ||  let test_open_module () =||
>> ||    true||
>> ||end||
>> ||
>> ||let libdir = [||
>> ||  "/usr/local/lib/ocaml/compiler-libs";||
>> ||]||
>> ||
>> ||let execute_phrase ident phrase =||
>> ||  if Toploop.execute_phrase false Format.std_formatter phrase||
>> ||  then||
>> ||    ()||
>> ||  else||
>> ||    failwith ident||
>> ||
>> ||let rec make_path_rev p =||
>> ||  match p with||
>> ||  | [] -> invalid_arg "make_path_rev"||
>> ||  | h :: [] -> Longident.Lident h||
>> ||  | h :: t -> Longident.Ldot (make_path_rev t, h)||
>> ||
>> ||let make_path p =||
>> ||  make_path_rev (List.rev p)||
>> ||    ||
>> ||let install_printer path =||
>> ||  let longident = make_path_rev ("format" :: List.rev path) in||
>> ||  let phrase = Parsetree.Ptop_dir(||
>> ||    "install_printer", Parsetree.Pdir_ident longident||
>> ||  )||
>> ||  in||
>> ||  execute_phrase "install_printer" phrase||
>> ||
>> ||
>> ||let open_module p =||
>> ||  let open Parsetree in||
>> ||  let open Location in||
>> ||  let open Asttypes in||
>> ||  let loc = {||
>> ||    loc_start = Lexing.dummy_pos;||
>> ||    loc_end = Lexing.dummy_pos;||
>> ||    loc_ghost = false||
>> ||  }||
>> ||  in||
>> ||  let phrase = Ptop_def [||
>> ||    {||
>> ||      pstr_desc =||
>> ||    Pstr_open {||
>> ||      txt = make_path p;||
>> ||      loc;||
>> ||    };||
>> ||      pstr_loc = loc||
>> ||    };||
>> ||  ]||
>> ||  in||
>> ||  execute_phrase "open_module" phrase||
>> ||
>> ||let startup () =||
>> ||  begin||
>> ||    List.iter Topdirs.dir_directory libdir;||
>> ||    List.iter install_printer [["Demonstrate"; "Tag"]];||
>> ||    List.iter open_module [["Demonstrate"]; ["Demonstrate"; "Tag" ]];||
>> ||  end||
>> ||
>> ||let _ =||
>> ||  Toploop.toplevel_startup_hook := startup|
>> ---->8----
> 
> 
> -- 
> Caml-list mailing list.  Subscription management and archives:
> https://sympa.inria.fr/sympa/arc/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
> 


      parent reply	other threads:[~2013-07-09  9:36 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-01 21:30 [Caml-list] " Michael Le Barbier Grünewald
2013-07-09  9:26 ` [Caml-list] " Michael
2013-07-09  9:33   ` Daniel Bünzli
2013-07-14 18:23     ` Michael
2013-07-09  9:36   ` Anil Madhavapeddy [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=EA82C5EE-41A1-4DDA-A635-BE7A4CFFF853@recoil.org \
    --to=anil@recoil.org \
    --cc=caml-list@inria.fr \
    --cc=michipili@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).