ocaml / oloop

Evaluate code through the OCaml toploop for inclusion in educational material.
ISC License
12 stars 5 forks source link

stdout gets associated with wrong phrase in sequence #21

Closed agarwal closed 9 years ago

agarwal commented 9 years ago

Here's a utop session showing the behavior.

First, I first define a show function because Outcome.eval is abstract:

utop # open Oloop;;
utop # let show (x : 'a Outcome.t) = match x with
  | `Eval x -> `Eval (Outcome.result x, Outcome.stdout x, Outcome.warnings x)
  | `Uneval _ -> `Uneval x;;
val show : 'a Outcome.t -> [> `Eval of Outcometree.out_phrase * string * (Location.t * Warnings.t) list | `Uneval of 'a Outcome.t ] =
  <fun>

Now, create an oloop toplevel:

utop # let t = create Outcome.merged >>| ok_exn;;
val t : Outcome.merged t Deferred.t = <abstr>

Evaluate one phrase. Seems okay.

utop # t >>= fun t -> eval t "#use \"topfind\"" >>| show;;
- : [> `Eval of Outcometree.out_phrase * string * (Location.t * Warnings.t) list | `Uneval of Outcome.merged Outcome.t ] =
`Eval
(Outcometree.Ophr_eval (Outcometree.Oval_constr (Outcometree.Oide_ident "()", []), Outcometree.Otyp_constr (Outcometree.Oide_ident "unit", [])),    
   "Findlib has been successfully loaded. Additional directives:\n  #require \"package\";;      to load a package\n  #list;;                   to list the available packages\n  #camlp4o;;                to load camlp4 (standard syntax)\n  #camlp4r;;                to load camlp4 (revised syntax)\n  #predicates \"p,q,...\";;   to set these predicates\n  Topfind.reset();;         to force that packages will be reloaded\n  #thread;;                 to enable threads\n\n",
[])    

Evaluate a second phrase. There is a problem. We're not seeing the output.

utop # t >>= fun t -> eval t "#thread" >>| show;;
- : [> `Eval of Outcometree.out_phrase * string * (Location.t * Warnings.t) list | `Uneval of Outcome.merged Outcome.t ] =
`Eval
(Outcometree.Ophr_eval (Outcometree.Oval_constr (Outcometree.Oide_ident "()", []), Outcometree.Otyp_constr (Outcometree.Oide_ident "unit", [])),    
   "",
[])

Evaluate third phrase, and now you get the output that should have been returned above.

utop # t >>= fun t -> eval t "let _ = 2" >>| show;;
- : [> `Eval of Outcometree.out_phrase * string * (Location.t * Warnings.t) list | `Uneval of Outcome.merged Outcome.t ] =
`Eval
(Outcometree.Ophr_eval (Outcometree.Oval_int 2, Outcometree.Otyp_constr (Outcometree.Oide_ident "int", [])),                                        
   "/Users/ashish/.opam/rwo/lib/ocaml/threads: added to search path\n/Users/ashish/.opam/rwo/lib/ocaml/unix.cma: loaded\n/Users/ashish/.opam/rwo/lib/ocaml/threads/threads.cma: loaded\n",
[])
agarwal commented 9 years ago

Our CLI shows it more easily:

$ cat a.ml 
#use "topfind";;
#thread;;
let _ = 2;;

$ ./app.native a.ml 
(* part 0 *)
# #use "topfind";;
Findlib has been successfully loaded. Additional directives:
  #require "package";;      to load a package
  #list;;                   to list the available packages
  #camlp4o;;                to load camlp4 (standard syntax)
  #camlp4r;;                to load camlp4 (revised syntax)
  #predicates "p,q,...";;   to set these predicates
  Topfind.reset();;         to force that packages will be reloaded
  #thread;;                 to enable threads

# #thread;;

# let _ = 2;;
/Users/ashish/.opam/rwo/lib/ocaml/threads: added to search path
/Users/ashish/.opam/rwo/lib/ocaml/unix.cma: loaded
/Users/ashish/.opam/rwo/lib/ocaml/threads/threads.cma: loaded
Chris00 commented 9 years ago

FWIW test_require shows the correct behavior.