caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Jeremie Dimino <jdimino@janestreet.com>
To: Kenichi Asai <asai@is.ocha.ac.jp>
Cc: caml users <caml-list@inria.fr>
Subject: Re: [Caml-list] a simple example of compiler-libs.toplevel?
Date: Fri, 5 Mar 2021 09:44:50 +0000	[thread overview]
Message-ID: <CANhEzE500WBfKuJaML35XECExZoa-oHHMXyhSq-sFV418oJJCA@mail.gmail.com> (raw)
In-Reply-To: <20210305050509.GA97697@pllab.is.ocha.ac.jp>

[-- Attachment #1: Type: text/plain, Size: 3915 bytes --]

Hi Kenichi,

It is possible to do this kind of thing. If you only want to change the
character for the prompt, you can set the Toploop.read_interactive_input
function. Then to create a custom toplevel, you need to call [Topmain.main]
and link your program with the compiler-libs.toplevel library. Here is a
complete example where I copied and adapted the default
[read_interactive_input] function from the compiler libraries, and used
dune to build a custom toplevel:

$ cat mytop.ml
let read_input prompt buffer len =
  let prompt =
    if prompt <> "" && prompt.[0] = '#' then
      String.mapi (fun i c -> if i = 0 then '%' else c) prompt
    else
      prompt
  in
  output_string stdout prompt; flush stdout;
  let i = ref 0 in
  try
    while true do
      if !i >= len then raise Exit;
      let c = input_char stdin in
      Bytes.set buffer !i c;
      Option.iter (fun b -> Buffer.add_char b c)
!Location.input_phrase_buffer;
      incr i;
      if c = '\n' then raise Exit;
    done;
    (!i, false)
  with
  | End_of_file ->
      (!i, true)
  | Exit ->
      (!i, false)

let () =
  Toploop.read_interactive_input := read_input;
  Topmain.main ()
$ cat dune
(executable
 (name mytop)
 (libraries compiler-libs.toplevel)
 (link_flags :standard -linkall)
 (modes byte))
$ dune exec ./mytop.exe
        OCaml version 4.11.1

% 1 + 1;;
- : int = 2

FTR, the compiler invocation to build myutop.exe is:
$ ocamlc -linkall -I +compiler-libs ocamlcommon.cma ocamlbytecomp.cma
ocamltoplevel.cma mytop.ml -o mytop.exe
$ ./mytop.exe
        OCaml version 4.11.1

% 1 + 1;;
- : int = 2

If you want to go further, there are few projects that add line edition
support to the toplevel, colors etc, using similar methods:
- utop: https://github.com/ocaml-community/utop
- down: https://erratique.ch/software/down

Finally, if you'd like to improve the toplevel API so that doing this kind
of thing is easier in the future, a PR is always welcome :)

Happy hacking,

Jeremie



On Fri, Mar 5, 2021 at 5:05 AM Kenichi Asai <asai@is.ocha.ac.jp> wrote:

> Is there a simple (but complete) example that uses
> compiler-libs.toplevel, like creating an OCaml toplevel that uses a
> different character for a prompt?  When I tried:
>
> - copy toplevel/topstart.ml to my_topstart.ml and change Topmain in it
>   to My_topmain
> - copy toplevel/topmain.ml to my_topmain.ml and change Toploop in it
>   to My_toploop
> - copy toplevel/toploop.ml to my_toploop.ml and change the prompt
>   character in it
> - optionally, copy toplevel/topdirs.ml to my_topdirs.ml and change
>   Toploop, etc., to My_toploop (this does not affect the story below)
>
> I ran into the following error:
>
> The ocamltoplevel.cma library from compiler-libs cannot be loaded
> inside the OCaml toplevel
>
> When I disable it (by removing the expression that raises this error
> in my_toploop.ml), I can launch the new toplevel, but I cannot define
> a new name:
>
> let a = 3
>
> results in "Fatal error: a unbound at toplevel".  Is it possible to do
> this kind of creating a new OCaml toplevel using compiler-libs.toplevel?
> Or is the compiler-libs.toplevel intended for something else?
>
> A bit of background.  I am developing an OCaml type debugger:
>
> http://pllab.is.ocha.ac.jp/~asai/TypeDebugger/
>
> and am currently trying to port it to a newer version of OCaml.  For
> the current type debugger, I inserted code for type debugging into the
> main loop in toploop.ml.  However, inserting code directly into the
> OCaml source requires me to recompile whole (or at least the core of)
> the OCaml.  If I could do the same with compiler-libs, that would be
> great.
>
> Any help is welcome.  (I also welcome the negative information saying
> that it is impossible to do this kind of thing.  Then, I would fall
> back to the old way of compiling whole the OCaml.)
>
> Thank you in advance.
>
> Sincerely,
>
> --
> Kenichi Asai
>


-- 
Jeremie

[-- Attachment #2: Type: text/html, Size: 7107 bytes --]

  reply	other threads:[~2021-03-05  9:45 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-05  5:05 Kenichi Asai
2021-03-05  9:44 ` Jeremie Dimino [this message]
2021-03-05 14:03   ` Kenichi Asai
2021-03-05 17:11     ` Jeremie Dimino

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=CANhEzE500WBfKuJaML35XECExZoa-oHHMXyhSq-sFV418oJJCA@mail.gmail.com \
    --to=jdimino@janestreet.com \
    --cc=asai@is.ocha.ac.jp \
    --cc=caml-list@inria.fr \
    /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).