Toploop doesn't execute valid Ocaml code with escaped strings

Hello, folks.

I’m trying to work with compiler-libs.toplevel api’s just to understand a little bit more of the REPL possibilities Ocaml can provide.

On the internet, I’ve found this simples function here:

let eval code =
  let as_buf = Lexing.from_string code in
  let parsed = !Toploop.parse_toplevel_phrase as_buf in
  ignore (Toploop.execute_phrase true Format.err_formatter parsed)

It just receives some ocaml code as string and send the result of the execution to a buffer output. It works like like a charm for some simple stuff. Here’s some example:

eval "1 + 1;;";;
- : int = 2
- : unit = ()

eval "let b = \"my name\";;";;
val b : string = "my name"
- : unit = ()

But for some reason, the execution Toploop.execute_phrase seems to break when I try to escape multiple things inside a string. For example:

let x = "Hello \"World!\""

it’s a perfect valid string in ocaml with the result val x : string = "Hello \"World!\"". But trying to do the same thing inside my eval function, like this:

eval "let x = \"Hello \"World!\"\";;"

Breaks at the executation with the error Exception: Typecore.Error (_, _, _)..

Does anyone has any idea what could be happening?

I’m not at a place where I can type easily, but it looks like you didn’t escape correctly. That is, you have to escape the escaping, and it doesn’t look correct

Can I suggest using raw strings ? They easy to nest, so no need trim get escaped escaping right

1 Like

Yeah! You’re totally right, I just had to escape the escapes, like this for example eval "let x = \"Hello \\\"World!\\\"\";;";;. I really thought I tried that, but I guess not

Raw strings are easier to handle, the problem is that my end goal is to send real code to be evaluated so it kinda has to accommodate things like this. To be honest I’m just a few weeks into studying Ocaml and I’m way over my head with this hehe but I’m a dreamer by heart so I’m giving it a shot.

Sure; I’ll just note that there’s code you write as if it were in a top-level, e.g.

let x = "Hello \"World!\""

and then there’s you passing that code to your evaluator:

eval {foo|let x = "Hello \"World!\""|foo}

That’s all I really meant: that you don’t have to do any quoting you wouldn’t already be doing in the toplevel.