[
  {
    "path": ".gitignore",
    "content": "*.out\n*.out.full\n*.a\na.out\n.*.swp\n*.aux\n*.aux\n*.byte\n*.cmo\n*.cmi\n*.cmx\n*.cmxa\n*.cma\n*.idx\n*.log\n*.native\n*.byte\n*.o\n*.omakedb.lock\n*.omc\n*.tmp\n*.toc\n*~\n.*.swp\n.DS_Store\n.bzr\n.bzrignore\n.project\n.pydevproject\n.settings\n/commenting-build\n_build\n"
  },
  {
    "path": "INSTALL.sh",
    "content": "#!/bin/sh\n\nopam install -j 4 --yes \\\n  core \\\n  core_extended \\\n  cryptokit \\\n  core_bench \\\n  atdgen \\\n  async \\\n  yojson \\\n  textwrap \\\n  cohttp \\\n  async_graphics \\\n  menhir \\\n  utop \\\n  cmdliner \\\n  cow \\\n  ocp-indent \\\n  ctypes \\\n  ocp-index\n\necho You also need Pygments installed.\necho This is python-pygments in Debian\n"
  },
  {
    "path": "Makefile",
    "content": ".PHONY: all depend clean distclean\n\nall:\n\tcd code && $(MAKE) -j1\n\ndepend:\n\t./INSTALL.sh\n\nclean:\n\trm -rf scripts/_build\n\tcd code && $(MAKE) clean\n\ndistclean: clean\n\tcd code && $(MAKE) distclean\n"
  },
  {
    "path": "README.md",
    "content": "This repository contains all the code samples from Real World OCaml.  The\nrepository tags represent a particular release of the book.\n"
  },
  {
    "path": "UNLICENSE",
    "content": "This is free and unencumbered software released into the public domain.\n\nAnyone is free to copy, modify, publish, use, compile, sell, or\ndistribute this software, either in source code form or as a compiled\nbinary, for any purpose, commercial or non-commercial, and by any\nmeans.\n\nIn jurisdictions that recognize copyright laws, the author or authors\nof this software dedicate any and all copyright interest in the\nsoftware to the public domain. We make this dedication for the benefit\nof the public at large and to the detriment of our heirs and\nsuccessors. We intend this dedication to be an overt act of\nrelinquishment in perpetuity of all present and future rights to this\nsoftware under copyright law.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR\nOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nFor more information, please refer to <http://unlicense.org/>\n"
  },
  {
    "path": "code/Makefile",
    "content": "#OCAMLPARAM=_,we=+A\n#export OCAMLPARAM\n\ndirs= json \\\n      command-line-parsing guided-tour \\\n      variables-and-functions \\\n      lists-and-patterns \\\n      sexpr \\\n      parsing \\\n      parsing-test \\\n      maps-and-hash-tables \\\n      files-modules-and-programs \\\n      files-modules-and-programs-freq \\\n      files-modules-and-programs-freq-obuild \\\n      files-modules-and-programs-freq-with-counter \\\n      files-modules-and-programs-freq-with-sig \\\n      files-modules-and-programs-freq-with-sig-abstract \\\n      files-modules-and-programs-freq-with-sig-abstract-fixed \\\n      files-modules-and-programs-freq-fast \\\n      files-modules-and-programs-freq-median \\\n      files-modules-and-programs-freq-with-sig-mismatch \\\n      files-modules-and-programs-freq-with-missing-def \\\n      files-modules-and-programs-freq-with-type-mismatch \\\n      files-modules-and-programs-freq-cyclic1 \\\n      files-modules-and-programs-freq-cyclic2 \\\n      records \\\n      variants \\\n      variants-termcol \\\n      variants-termcol-annotated \\\n      variants-termcol-fixed \\\n      objects \\\n      classes \\\n      classes-async \\\n      imperative-programming \\\n      error-handling \\\n      memory-repr \\\n      gc \\\n      front-end \\\n      packing \\\n      principal \\\n      back-end \\\n      back-end-bench \\\n      back-end-embed \\\n      functors \\\n      fcm \\\n      async \\\n      ffi \\\n      ctypes \\\n      ocp-index \\\n      installation\n\n# html/xml files directory\nOBJ=         _build\n\n# All the source files\nml_src=       $(wildcard $(dirs:%=%/*.ml))\nmli_src=      $(wildcard $(dirs:%=%/*.mli))\nmll_src=      $(wildcard $(dirs:%=%/*.mll))\nmly_src=      $(wildcard $(dirs:%=%/*.mly))\njson_src=     $(wildcard $(dirs:%=%/*.json))\njava_src=     $(wildcard $(dirs:%=%/*.java))\nc_src=        $(wildcard $(dirs:%=%/*.c))\nh_src=        $(wildcard $(dirs:%=%/*.h))\nasm_src=      $(wildcard $(dirs:%=%/*.S))\ncmd_src=      $(wildcard $(dirs:%=%/*.cmd))\ncpp_src=      $(wildcard $(dirs:%=%/*.cpp))\natd_src=      $(wildcard $(dirs:%=%/*.atd))\nscm_src=      $(wildcard $(dirs:%=%/*.scm))\nsyn_src=      $(wildcard $(dirs:%=%/*.syntax))\nascii_src=    $(wildcard $(dirs:%=%/*.ascii))\nscripts=      $(wildcard $(dirs:%=%/*.sh))\nrawscripts=   $(wildcard $(dirs:%=%/*.rawsh))\nerrscripts=   $(wildcard $(dirs:%=%/*.errsh))\ntopscripts=   $(wildcard $(dirs:%=%/*.topscript))\nrawtscripts=   $(wildcard $(dirs:%=%/*.rawscript))\n\nall_src=      $(ml_src) $(mli_src) $(json_src) $(java_src) $(c_src) \\\n\t      $(cmd_src) $(cpp_src) $(atd_src) $(scm_src) $(syn_src) \\\n\t      $(ascii_src) $(asm_src) $(mll_src) $(mly_src) $(h_src)\nall_scripts=  $(scripts:%.sh=%.out) $(errscripts:%.errsh=%.out) \\\n\t      $(topscripts) $(rawtscripts) $(rawscripts:%.rawsh=%.out)\n\n# The source files all map to %.<part>.html and %.<part>.xml\nall_src_html= $(all_src:%=$(OBJ)/%.0.html) $(all_scripts:%=$(OBJ)/%.0.html)\nall_src_md=   $(all_src:%=$(OBJ)/%.0.xml) $(all_scripts:%=$(OBJ)/%.0.xml)\n\n# Binaries we run\nruntop=      rwo-run-toplevel\nhighlight=   rwo-syntax-highlight\n\n.PHONY: all\nall: $(all_src_html) $(all_src_md)\n\t@ :\n\nprint-%:\n\t@echo $($*)\n\njson/run_github_org.out:: json/build_github_org.out\ncommand-line-parsing/run_basic_md5.out:: command-line-parsing/build_basic_md5.out\ncommand-line-parsing/get_basic_md5_version.out:: command-line-parsing/build_basic_md5.out\ncommand-line-parsing/run_basic_and_default_md5.out:: command-line-parsing/build_basic_md5_with_optional_file.out command-line-parsing/build_basic_md5_with_default_file.out\ncommand-line-parsing/run_cal_add_sub_days.out:: command-line-parsing/build_cal_add_sub_days.out\ncommand-line-parsing/md5_completion.out:: command-line-parsing/build_basic_md5_with_flags.out\ncommand-line-parsing/cal_completion.out:: command-line-parsing/build_cal_add_sub_days.out\nparsing-test/run_broken_test.out:: parsing-test/build_test.out\n\n$(OBJ)/%.mli.0.html $(OBJ)/%.mli.0.xml: %.mli\n\t@mkdir -p $(@D)\n\t$(highlight) -builddir $(OBJ) -cow $< || (cat $@ && rm -f $@)\n\n$(OBJ)/%.ml.0.html $(OBJ)/%.ml.0.xml: %.ml\n\t@mkdir -p $(@D)\n\t$(highlight) -builddir $(OBJ) -cow $<  || (cat $@ && rm -f $@)\n\n$(OBJ)/%.mll.0.html $(OBJ)/%.mll.0.xml: %.mll\n\t@mkdir -p $(@D)\n\t$(highlight) -builddir $(OBJ) -cow $<  || (cat $@ && rm -f $@)\n\n$(OBJ)/%.mly.0.html $(OBJ)/%.mly.0.xml: %.mly\n\t@mkdir -p $(@D)\n\t$(highlight) -builddir $(OBJ) -cow $<  || (cat $@ && rm -f $@)\n\n$(OBJ)/%.json.0.html $(OBJ)/%.json.0.xml: %.json\n\t@mkdir -p $(@D)\n\t$(highlight) -builddir $(OBJ) -pygments json $< || (cat $@ && rm -f $@)\n\n$(OBJ)/%.syntax.0.html $(OBJ)/%.syntax.0.xml: %.syntax\n\t@mkdir -p $(@D)\n\t$(highlight) -builddir $(OBJ) -raw ocamlsyntax $< || (cat $@ && rm -f $@)\n\n$(OBJ)/%.cmd.0.html $(OBJ)/%.cmd.0.xml: %.cmd\n\t@mkdir -p $(@D)\n\t$(highlight) -builddir $(OBJ) -pygments bash $< || (cat $@ && rm -f $@)\n\n$(OBJ)/%.atd.0.html $(OBJ)/%.atd.0.xml: %.atd\n\t@mkdir -p $(@D)\n\t$(highlight) -builddir $(OBJ) -cow $< || (cat $@ && rm -f $@)\n\n$(OBJ)/%.ascii.0.html $(OBJ)/%.ascii.0.xml: %.ascii\n\t@mkdir -p $(@D)\n\t$(highlight) -builddir $(OBJ) -raw ascii $< || (cat $@ && rm -f $@)\n\n$(OBJ)/%.java.0.html $(OBJ)/%.java.0.xml: %.java\n\t@mkdir -p $(@D)\n\t$(highlight) -builddir $(OBJ) -pygments java $< || (cat $@ && rm -f $@)\n\n$(OBJ)/%.S.0.html $(OBJ)/%.S.0.xml: %.S\n\t@mkdir -p $(@D)\n\t$(highlight) -builddir $(OBJ) -pygments gas $< || (cat $@ && rm -f $@)\n\n$(OBJ)/%.c.0.html $(OBJ)/%.c.0.xml: %.c\n\t@mkdir -p $(@D)\n\t$(highlight) -builddir $(OBJ) -pygments c $< || (cat $@ && rm -f $@)\n\n$(OBJ)/%.h.0.html $(OBJ)/%.h.0.xml: %.h\n\t@mkdir -p $(@D)\n\t$(highlight) -builddir $(OBJ) -pygments c $< || (cat $@ && rm -f $@)\n\n$(OBJ)/%.cpp.0.html $(OBJ)/%.cpp.0.xml: %.cpp\n\t@mkdir -p $(@D)\n\t$(highlight) -builddir $(OBJ) -pygments cpp $< || (cat $@ && rm -f $@)\n\n$(OBJ)/%.scm.0.html $(OBJ)/%.scm.0.xml: %.scm\n\t@mkdir -p $(@D)\n\t$(highlight) -builddir $(OBJ) -pygments scheme $< || (cat $@ && rm -f $@)\n\n$(OBJ)/%.topscript.0.xml $(OBJ)/%.topscript.0.html: %.topscript\n\t@mkdir -p $(@D)\n\tcd $(*D) && $(runtop) $(*F).topscript -fullfile \"$<\" -builddir \"../$(@D)\"\n\n$(OBJ)/%.rawscript.0.xml $(OBJ)/%.rawscript.0.html: %.rawscript\n\t@mkdir -p $(@D)\n\t$(highlight) -builddir $(OBJ) -rawscript $<\n\n$(OBJ)/%.out.0.html $(OBJ)/%.out.0.xml: %.out\n\t@mkdir -p $(@D)\n\t$(highlight) -builddir $(OBJ) -console $<\n\n# The outputs of the shell scripts should be checked in.\n%.out.full: %.sh\n\t./exec_script.sh $< > $@ 2>&1 || (cat $@ && rm -f $@)\n\n%.out: %.out.full\n\tegrep -v '(^ocamlfind |^\\+|^menhir --|added to search path$$)' < $< > $@\n\n%.out.full: %.errsh\n\t! ./exec_script.sh $< > $@ 2>&1 || (cat $@ && rm -f $@)\n\n%.out: %.rawsh\n\tcp $< $@\n\nclean:\n\tfind . -name \\*.out | xargs rm -f\n\trm -rf $(OBJ)\n\nclean-%:\n\tfind $* -name \\*.out | xargs rm -f\n\trm -rf $*/_build\n\trm -rf _build/$*\n\ndistclean:\n\tfor i in $(dirs); do $(MAKE) clean-$$i; done\n\n.PRECIOUS: $(all_src) $(all_scripts)\n"
  },
  {
    "path": "code/async/#build_other_searches.sh#",
    "content": "corebuild -pkg cohttp.async,yojson,textwrap search_out_of_order.native\n\n"
  },
  {
    "path": "code/async/#main.topscript#",
    "content": "let x = 3;;\n#part 1\nIn_channel.read_all;;\nOut_channel.write_all \"test.txt\" ~data:\"This is only a test.\";;\nIn_channel.read_all \"test.txt\";;\n#part 2\nlet x = 3;;\n#part 3\n#require \"async\";;\nopen Async.Std;;\nReader.file_contents;;\n#part 4\nlet contents = Reader.file_contents \"test.txt\";;\nDeferred.peek contents;;\n#part 5\ncontents;;\n#part 6\nDeferred.peek contents;;\n#part 7\nDeferred.bind ;;\n#part 8\nlet uppercase_file filename =\n    Deferred.bind (Reader.file_contents filename)\n     (fun text ->\n         Writer.save filename ~contents:(String.uppercase text))\n  ;;\nuppercase_file \"test.txt\";;\nReader.file_contents \"test.txt\";;\n#part 9\nlet uppercase_file filename =\n    Reader.file_contents filename\n    >>= fun text ->\n    Writer.save filename ~contents:(String.uppercase text)\n  ;;\n#part 10\nlet count_lines filename =\n    Reader.file_contents filename\n    >>= fun text ->\n    List.length (String.split text ~on:'\\n')\n  ;;\n#part 11\nreturn;;\nlet three = return 3;;\nthree;;\n#part 12\nlet count_lines filename =\n    Reader.file_contents filename\n    >>= fun text ->\n    return (List.length (String.split text ~on:'\\n'))\n  ;;\n#part 13\nDeferred.map;;\n#part 14\nlet count_lines filename =\n    Reader.file_contents filename\n    >>| fun text ->\n    List.length (String.split text ~on:'\\n')\n  ;;\ncount_lines \"/etc/hosts\";;\n#part 15\nlet ivar = Ivar.create ();;\nlet def = Ivar.read ivar;;\nDeferred.peek def;;\nIvar.fill ivar \"Hello\";;\nDeferred.peek def;;\n#part 16\nmodule type Delayer_intf = sig\n    type t\n    val create : Time.Span.t -> t\n    val schedule : t -> (unit -> 'a Deferred.t) -> 'a Deferred.t\n  end;;\n#part 17\nupon;;\n#part 18\nmodule Delayer : Delayer_intf = struct\n    type t = { delay: Time.Span.t;\n               jobs: (unit -> unit) Queue.t;\n             }\n\n    let create delay =\n      { delay; jobs = Queue.create () }\n\n    let schedule t thunk =\n      let ivar = Ivar.create () in\n      Queue.enqueue t.jobs (fun () ->\n        upon (thunk ()) (fun x -> Ivar.fill ivar x));\n      upon (after t.delay) (fun () ->\n        let job = Queue.dequeue_exn t.jobs in\n        job ());\n      Ivar.read ivar\n  end;;\n#part 19\nlet rec loop_forever () = loop_forever ();;\nlet always_fail () = assert false;;\n#part 20\nlet do_stuff n =\n    let x = 3 in\n    if n > 0 then loop_forever ();\n    x + n\n  ;;\n#part 21\nlet rec loop_forever () : never_returns = loop_forever ();;\n#part 22\nlet do_stuff n =\n    let x = 3 in\n    if n > 0 then loop_forever ();\n    x + n\n  ;;\n#part 23\nnever_returns;;\nlet do_stuff n =\n    let x = 3 in\n    if n > 0 then never_returns (loop_forever ());\n    x + n\n  ;;\n#part 24\nlet (r,w) = Pipe.create ();;\n#part 25\nlet (r,w) = Pipe.create ();;\nlet write_complete = Pipe.write w \"Hello World!\";;\nPipe.read r;;\nwrite_complete;;\n#part 26\nPipe.transfer;;\n#part 27\nCommand.async_basic;;\n#part 28\n#require \"cohttp.async\";;\nCohttp_async.Client.get;;\n#part 29\nDeferred.all;;\n#part 30\nDeferred.all_unit;;\n#part 31\nlet maybe_raise =\n    let should_fail = ref false in\n    fun () ->\n      let will_fail = !should_fail in\n      should_fail := not will_fail;\n      after (Time.Span.of_sec 0.5)\n      >>= fun () ->\n      if will_fail then raise Exit else return ()\n ;;\nmaybe_raise ();;\nmaybe_raise ();;\n#part 32\nlet handle_error () =\n    try\n      maybe_raise ()\n      >>| fun () -> \"success\"\n    with _ -> return \"failure\"\n  ;;\nhandle_error ();;\nhandle_error ();;\n#part 33\nlet handle_error () =\n    try_with (fun () -> maybe_raise ())\n    >>| function\n    | Ok ()   -> \"success\"\n    | Error _ -> \"failure\"\n  ;;\nhandle_error ();;\nhandle_error ();;\n#part 34\nlet blow_up () =\n    let monitor = Monitor.create ~name:\"blow up monitor\" () in\n    within' ~monitor maybe_raise\n  ;;\nblow_up ();;\nblow_up ();;\n#part 35\nlet swallow_error () =\n    let monitor = Monitor.create () in\n    Stream.iter (Monitor.errors monitor) ~f:(fun _exn ->\n      printf \"an error happened\\n\");\n    within' ~monitor (fun () ->\n      after (Time.Span.of_sec 0.5) >>= fun () -> failwith \"Kaboom!\")\n  ;;\n(* swallow_error ();; *)\n#part 36\nexception Ignore_me;;\nlet swallow_some_errors exn_to_raise =\n    let child_monitor  = Monitor.create  () in\n    let parent_monitor = Monitor.current () in\n    Stream.iter (Monitor.errors child_monitor) ~f:(fun error ->\n      match Monitor.extract_exn error with\n      | Ignore_me -> printf \"ignoring exn\\n\"\n      | _ -> Monitor.send_exn parent_monitor error);\n    within' ~monitor:child_monitor (fun () ->\n       after (Time.Span.of_sec 0.5)\n       >>= fun () -> raise exn_to_raise)\n  ;;\n#part 37\nswallow_some_errors Not_found;;\n#part 38\n(* swallow_some_errors Ignore_me;; *)\n#part 39\nlet string_and_float = Deferred.both\n   (after (sec 0.5)  >>| fun () -> \"A\")\n   (after (sec 0.25) >>| fun () -> 32.33);;\nstring_and_float;;\n#part 40\nDeferred.any [ (after (sec 0.5) >>| fun () -> \"half a second\")\n               ; (after (sec 10.) >>| fun () -> \"ten seconds\") ] ;;\n#part 41\nchoice;;\nchoose;;\n#part 42\nlet def = In_thread.run (fun () -> List.range 1 10);;\ndef;;\n#part 43\nlet log_delays thunk =\n    let start = Time.now () in\n    let print_time () =\n      let diff = Time.diff (Time.now ()) start in\n      printf \"%s, \" (Time.Span.to_string diff)\n    in\n    let d = thunk () in\n    Clock.every (sec 0.1) ~stop:d print_time;\n    d >>| fun () -> print_time (); printf \"\\n\"\n  ;;\n#part 44\nlog_delays (fun () -> after (sec 1.));;\n#part 45\nlet busy_loop () =\n    let x = ref None in\n    for i = 1 to 100_000_000 do x := Some i done\n  ;;\nlog_delays ( >>| fun () -> busy_loop 100);;\n#part 46\nlog_delays (In_thread.run (fun () -> busy_loop 100));;\n#part 47\nlet noalloc_busy_loop n =\n    let rec loop n =\n      if n <= 0 then ()\n      else loop (n-1)\n    in\n    loop (n * 100_000)\n  ;;\nlog_delays (In_thread.run (fun () -> noalloc_busy_loop 500));;\n"
  },
  {
    "path": "code/async/better_echo.ml",
    "content": "open Core.Std\nopen Async.Std\n\nlet run ~uppercase ~port =\n  let host_and_port =\n    Tcp.Server.create\n      ~on_handler_error:`Raise\n      (Tcp.on_port port)\n      (fun _addr r w ->\n        Pipe.transfer (Reader.pipe r) (Writer.pipe w)\n           ~f:(if uppercase then String.uppercase else Fn.id))\n  in\n  ignore (host_and_port : (Socket.Address.Inet.t, int) Tcp.Server.t Deferred.t);\n  Deferred.never ()\n\nlet () =\n  Command.async_basic\n    ~summary:\"Start an echo server\"\n    Command.Spec.(\n      empty\n      +> flag \"-uppercase\" no_arg\n        ~doc:\" Convert to uppercase before echoing back\"\n      +> flag \"-port\" (optional_with_default 8765 int)\n        ~doc:\" Port to listen on (default 8765)\"\n    )\n    (fun uppercase port () -> run ~uppercase ~port)\n  |> Command.run\n"
  },
  {
    "path": "code/async/build_echo.sh",
    "content": "corebuild -pkg async echo.native\ncorebuild -pkg async better_echo.native\n"
  },
  {
    "path": "code/async/build_other_searches.sh",
    "content": "corebuild -pkg cohttp.async,yojson,textwrap search_out_of_order.native\n\n"
  },
  {
    "path": "code/async/echo.ml",
    "content": "open Core.Std\nopen Async.Std\n\n(* Copy data from the reader to the writer, using the provided buffer\n   as scratch space *)\nlet rec copy_blocks buffer r w =\n  Reader.read r buffer\n  >>= function\n  | `Eof -> return ()\n  | `Ok bytes_read ->\n    Writer.write w buffer ~len:bytes_read;\n    Writer.flushed w\n    >>= fun () ->\n    copy_blocks buffer r w\n\n(* part 1 *)\n(** Starts a TCP server, which listens on the specified port, invoking\n    copy_blocks every time a client connects. *)\nlet run () =\n  let host_and_port =\n    Tcp.Server.create\n      ~on_handler_error:`Raise\n      (Tcp.on_port 8765)\n      (fun _addr r w ->\n         let buffer = String.create (16 * 1024) in\n         copy_blocks buffer r w)\n  in\n  ignore (host_and_port : (Socket.Address.Inet.t, int) Tcp.Server.t Deferred.t)\n\n(* part 2 *)\n(* Call [run], and then start the scheduler *)\nlet () =\n  run ();\n  never_returns (Scheduler.go ())\n"
  },
  {
    "path": "code/async/main-35.rawscript",
    "content": "# let swallow_error () =\n    let monitor = Monitor.create () in\n    Stream.iter (Monitor.errors monitor) ~f:(fun _exn ->\n      printf \"an error happened\\n\");\n    within' ~monitor (fun () ->\n      after (Time.Span.of_sec 0.5) >>= fun () -> failwith \"Kaboom!\")\n  ;;\nval swallow_error : unit -> 'a Deferred.t = <fun>\n# swallow_error ();;\nan error happened\n\n"
  },
  {
    "path": "code/async/main-38.rawscript",
    "content": "# swallow_some_errors Ignore_me;;\nignoring exn\n"
  },
  {
    "path": "code/async/main-44.rawscript",
    "content": "# log_delays (fun () -> after (sec 0.5));;\n0.154972ms, 102.126ms, 203.658ms, 305.73ms, 407.903ms, 501.563ms,\n- : unit = ()\n"
  },
  {
    "path": "code/async/main-45.rawscript",
    "content": "# let busy_loop n =\n    let x = ref None in\n    for i = 1 to 100_000_000 do x := Some i done\n  ;;\nval busy_loop : 'a -> unit = <fun>\n# log_delays (fun () -> return (busy_loop ()));;\n19.2185s,\n- : unit = ()\n"
  },
  {
    "path": "code/async/main-46.rawscript",
    "content": "# log_delays (fun () -> In_thread.run busy_loop);;\n0.332117ms, 16.6319s, 18.8722s,\n- : unit = ()\n"
  },
  {
    "path": "code/async/main-47.rawscript",
    "content": "# let noalloc_busy_loop () =\n    for i = 0 to 100_000_000 do () done\n;;\nval noalloc_busy_loop : unit -> unit = <fun>\n# log_delays (fun () -> In_thread.run noalloc_busy_loop);;\n0.169039ms, 4.58345s, 4.77866s, 4.87957s, 12.4723s, 15.0134s,\n- : unit = ()\n"
  },
  {
    "path": "code/async/main.topscript",
    "content": "let x = 3;;\n#part 1\nIn_channel.read_all;;\nOut_channel.write_all \"test.txt\" ~data:\"This is only a test.\";;\nIn_channel.read_all \"test.txt\";;\n#part 2\nlet x = 3;;\n#part 3\n#require \"async\";;\nopen Async.Std;;\nReader.file_contents;;\n#part 4\nlet contents = Reader.file_contents \"test.txt\";;\nDeferred.peek contents;;\n#part 5\ncontents;;\n#part 6\nDeferred.peek contents;;\n#part 7\nDeferred.bind ;;\n#part 8\nlet uppercase_file filename =\n    Deferred.bind (Reader.file_contents filename)\n     (fun text ->\n         Writer.save filename ~contents:(String.uppercase text))\n  ;;\nuppercase_file \"test.txt\";;\nReader.file_contents \"test.txt\";;\n#part 9\nlet uppercase_file filename =\n    Reader.file_contents filename\n    >>= fun text ->\n    Writer.save filename ~contents:(String.uppercase text)\n  ;;\n#part 10\nlet count_lines filename =\n    Reader.file_contents filename\n    >>= fun text ->\n    List.length (String.split text ~on:'\\n')\n  ;;\n#part 11\nreturn;;\nlet three = return 3;;\nthree;;\n#part 12\nlet count_lines filename =\n    Reader.file_contents filename\n    >>= fun text ->\n    return (List.length (String.split text ~on:'\\n'))\n  ;;\n#part 13\nDeferred.map;;\n#part 14\nlet count_lines filename =\n    Reader.file_contents filename\n    >>| fun text ->\n    List.length (String.split text ~on:'\\n')\n  ;;\ncount_lines \"/etc/hosts\";;\n#part 15\nlet ivar = Ivar.create ();;\nlet def = Ivar.read ivar;;\nDeferred.peek def;;\nIvar.fill ivar \"Hello\";;\nDeferred.peek def;;\n#part 16\nmodule type Delayer_intf = sig\n    type t\n    val create : Time.Span.t -> t\n    val schedule : t -> (unit -> 'a Deferred.t) -> 'a Deferred.t\n  end;;\n#part 17\nupon;;\n#part 18\nmodule Delayer : Delayer_intf = struct\n    type t = { delay: Time.Span.t;\n               jobs: (unit -> unit) Queue.t;\n             }\n\n    let create delay =\n      { delay; jobs = Queue.create () }\n\n    let schedule t thunk =\n      let ivar = Ivar.create () in\n      Queue.enqueue t.jobs (fun () ->\n        upon (thunk ()) (fun x -> Ivar.fill ivar x));\n      upon (after t.delay) (fun () ->\n        let job = Queue.dequeue_exn t.jobs in\n        job ());\n      Ivar.read ivar\n  end;;\n#part 19\nlet rec loop_forever () = loop_forever ();;\nlet always_fail () = assert false;;\n#part 20\nlet do_stuff n =\n    let x = 3 in\n    if n > 0 then loop_forever ();\n    x + n\n  ;;\n#part 21\nlet rec loop_forever () : never_returns = loop_forever ();;\n#part 22\nlet do_stuff n =\n    let x = 3 in\n    if n > 0 then loop_forever ();\n    x + n\n  ;;\n#part 23\nnever_returns;;\nlet do_stuff n =\n    let x = 3 in\n    if n > 0 then never_returns (loop_forever ());\n    x + n\n  ;;\n#part 24\nlet (r,w) = Pipe.create ();;\n#part 25\nlet (r,w) = Pipe.create ();;\nlet write_complete = Pipe.write w \"Hello World!\";;\nPipe.read r;;\nwrite_complete;;\n#part 26\nPipe.transfer;;\n#part 27\nCommand.async_basic;;\n#part 28\n#require \"cohttp.async\";;\nCohttp_async.Client.get;;\n#part 29\nDeferred.all;;\n#part 30\nDeferred.all_unit;;\n#part 31\nlet maybe_raise =\n    let should_fail = ref false in\n    fun () ->\n      let will_fail = !should_fail in\n      should_fail := not will_fail;\n      after (Time.Span.of_sec 0.5)\n      >>= fun () ->\n      if will_fail then raise Exit else return ()\n ;;\nmaybe_raise ();;\nmaybe_raise ();;\n#part 32\nlet handle_error () =\n    try\n      maybe_raise ()\n      >>| fun () -> \"success\"\n    with _ -> return \"failure\"\n  ;;\nhandle_error ();;\nhandle_error ();;\n#part 33\nlet handle_error () =\n    try_with (fun () -> maybe_raise ())\n    >>| function\n    | Ok ()   -> \"success\"\n    | Error _ -> \"failure\"\n  ;;\nhandle_error ();;\nhandle_error ();;\n#part 34\nlet blow_up () =\n    let monitor = Monitor.create ~name:\"blow up monitor\" () in\n    within' ~monitor maybe_raise\n  ;;\nblow_up ();;\nblow_up ();;\n#part 35\nlet swallow_error () =\n    let monitor = Monitor.create () in\n    Stream.iter (Monitor.errors monitor) ~f:(fun _exn ->\n      printf \"an error happened\\n\");\n    within' ~monitor (fun () ->\n      after (Time.Span.of_sec 0.5) >>= fun () -> failwith \"Kaboom!\")\n  ;;\n(* swallow_error ();; *)\n#part 36\nexception Ignore_me;;\nlet swallow_some_errors exn_to_raise =\n    let child_monitor  = Monitor.create  () in\n    let parent_monitor = Monitor.current () in\n    Stream.iter (Monitor.errors child_monitor) ~f:(fun error ->\n      match Monitor.extract_exn error with\n      | Ignore_me -> printf \"ignoring exn\\n\"\n      | _ -> Monitor.send_exn parent_monitor error);\n    within' ~monitor:child_monitor (fun () ->\n       after (Time.Span.of_sec 0.5)\n       >>= fun () -> raise exn_to_raise)\n  ;;\n#part 37\nswallow_some_errors Not_found;;\n#part 38\n(* swallow_some_errors Ignore_me;; *)\n#part 39\nlet string_and_float = Deferred.both\n   (after (sec 0.5)  >>| fun () -> \"A\")\n   (after (sec 0.25) >>| fun () -> 32.33);;\nstring_and_float;;\n#part 40\nDeferred.any [ (after (sec 0.5) >>| fun () -> \"half a second\")\n               ; (after (sec 10.) >>| fun () -> \"ten seconds\") ] ;;\n#part 41\nchoice;;\nchoose;;\n#part 42\nlet def = In_thread.run (fun () -> List.range 1 10);;\ndef;;\n#part 43\nlet log_delays thunk =\n    let start = Time.now () in\n    let print_time () =\n      let diff = Time.diff (Time.now ()) start in\n      printf \"%s, \" (Time.Span.to_string diff)\n    in\n    let d = thunk () in\n    Clock.every (sec 0.1) ~stop:d print_time;\n    d >>| fun () -> print_time (); printf \"\\n\"\n  ;;\n#part 44\nlog_delays (fun () -> after (sec 0.5));;\n#part 45\nlet busy_loop n =\n    let x = ref None in\n    for i = 1 to 100_000_000 do x := Some i done\n  ;;\nlog_delays (fun () -> return (busy_loop ()));;\n#part 46\nlog_delays (fun () -> In_thread.run busy_loop);;\n#part 47\nlet noalloc_busy_loop () =\n    for i = 0 to 100_000_000 do () done\n  ;;\nlog_delays (fun () -> In_thread.run noalloc_busy_loop);;\n"
  },
  {
    "path": "code/async/native_code_log_delays.ml",
    "content": "open Core.Std\nopen Async.Std\n\nlet log_delays thunk =\n  let start = Time.now () in\n  let print_time () =\n    let diff = Time.diff (Time.now ()) start in\n    printf \"%s, \" (Time.Span.to_string diff)\n  in\n  let d = thunk () in\n  Clock.every (sec 0.1) ~stop:d print_time;\n  d >>| fun () -> print_time (); printf \"\\n\"\n\nlet noalloc_busyloop () =\n  for _i = 1 to 25_000_000_000 do () done;\n  Deferred.unit\n\nlet () =\n  Command.async_basic\n    ~summary:\"run logger without busy loop\"\n    Command.Spec.(empty)\n    (fun () -> log_delays noalloc_busyloop)\n  |> Command.run\n"
  },
  {
    "path": "code/async/pipe_write_break.rawscript",
    "content": "# Pipe.write w \"Hello World!\";;\nInterrupted.\n"
  },
  {
    "path": "code/async/pipe_write_break.rawtopscript",
    "content": "# Pipe.write w \"Hello World!\";;\nInterrupted.\n"
  },
  {
    "path": "code/async/run_echo.rawsh",
    "content": "$ ./echo.native &\n$ nc 127.0.0.1 8765\nThis is an echo server\nThis is an echo server\nIt repeats whatever I write.\nIt repeats whatever I write.\n"
  },
  {
    "path": "code/async/run_native_code_log_delays.rawsh",
    "content": "$ corebuild -pkg async native_code_log_delays.native\n$ ./native_code_log_delays.native\n15.5686s, \n$ \n"
  },
  {
    "path": "code/async/run_native_code_log_delays_orig.sh",
    "content": "corebuild -pkg async native_code_log_delays.native\n./native_code_log_delays.native\n\n"
  },
  {
    "path": "code/async/run_search.rawsh",
    "content": "$ corebuild -pkg cohttp.async,yojson,textwrap search.native\n$ ./search.native \"Concurrent Programming\" \"OCaml\"\nConcurrent Programming\n----------------------\n\n\"Concurrent computing is a form of computing in which programs are\ndesigned as collections of interacting computational processes that\nmay be executed in parallel.\"\n\nOCaml\n-----\n\n\"OCaml, originally known as Objective Caml, is the main implementation\nof the Caml programming language, created by Xavier Leroy, Jérôme\nVouillon, Damien Doligez, Didier Rémy and others in 1996.\"\n\n"
  },
  {
    "path": "code/async/run_search_orig.sh",
    "content": "corebuild -pkg cohttp.async,yojson,textwrap search.native\n./search.native \"Concurrent Programming\" \"OCaml\"\n"
  },
  {
    "path": "code/async/run_search_with_configurable_server.rawsh",
    "content": "$ corebuild -pkg cohttp.async,yojson,textwrap \\\n    search_with_configurable_server.native\n$ ./search_with_configurable_server.native \\\n    -servers localhost,api.duckduckgo.com \\\n    \"Concurrent Programming\" OCaml\n(\"unhandled exception\"\n ((lib/monitor.ml.Error_\n   ((exn (Unix.Unix_error \"Connection refused\" connect 127.0.0.1:80))\n    (backtrace\n     (\"Raised by primitive operation at file \\\"lib/unix_syscalls.ml\\\", line 797, characters 12-69\"\n      \"Called from file \\\"lib/deferred.ml\\\", line 20, characters 62-65\"\n      \"Called from file \\\"lib/scheduler.ml\\\", line 125, characters 6-17\"\n      \"Called from file \\\"lib/jobs.ml\\\", line 65, characters 8-13\" \"\"))\n    (monitor\n     (((name Tcp.close_sock_on_error) (here ()) (id 5) (has_seen_error true)\n       (someone_is_listening true) (kill_index 0))\n      ((name main) (here ()) (id 1) (has_seen_error true)\n       (someone_is_listening false) (kill_index 0))))))\n  (Pid 15971)))\n"
  },
  {
    "path": "code/async/run_search_with_configurable_server_orig.errsh",
    "content": "corebuild -pkg cohttp.async,yojson,textwrap search_with_configurable_server.native\n./search_with_configurable_server.native -servers localhost,api.duckduckgo.com \"Concurrent Programming\" OCaml\n"
  },
  {
    "path": "code/async/run_search_with_error_handling.rawsh",
    "content": "$ corebuild -pkg cohttp.async,yojson,textwrap \\\n    search_with_error_handling.native\n$ ./search_with_error_handling.native \\\n    -servers localhost,api.duckduckgo.com \\\n    \"Concurrent Programming\" OCaml\nConcurrent Programming\n----------------------\n\nDuckDuckGo query failed: Unexpected failure\n\nOCaml\n-----\n\n\"OCaml, originally known as Objective Caml, is the main implementation\nof the Caml programming language, created by Xavier Leroy, Jérôme\nVouillon, Damien Doligez, Didier Rémy and others in 1996.\"\n\n"
  },
  {
    "path": "code/async/run_search_with_error_handling_orig.sh",
    "content": "corebuild -pkg cohttp.async,yojson,textwrap search_with_error_handling.native\n./search_with_error_handling.native -servers localhost,api.duckduckgo.com \"Concurrent Programming\" OCaml\n"
  },
  {
    "path": "code/async/run_search_with_timeout_no_leak.rawsh",
    "content": "$ corebuild -pkg cohttp.async,yojson,textwrap \\\n     search_with_timeout_no_leak.native\n$ ./search_with_timeout_no_leak.native \\\n     \"concurrent programming\" ocaml -timeout 0.2s\nconcurrent programming\n----------------------\n\nDuckDuckGo query failed: Timed out\n\nocaml\n-----\n\n\"OCaml or Objective Caml, is the main implementation of the Caml\nprogramming language, created by Xavier Leroy, Jérôme Vouillon,\nDamien Doligez, Didier Rémy and others in 1996.\"\n"
  },
  {
    "path": "code/async/run_search_with_timeout_no_leak_orig.sh",
    "content": "corebuild -pkg cohttp.async,yojson,textwrap search_with_timeout_no_leak.native\n./search_with_timeout_no_leak.native \"concurrent programming\" ocaml -timeout 0.2s\n"
  },
  {
    "path": "code/async/run_thread.sh",
    "content": "corebuild -pkg async thread_exp_async_only.native\n./thread_exp_async_only.native\n"
  },
  {
    "path": "code/async/search.ml",
    "content": "open Core.Std\nopen Async.Std\n\n(* Generate a DuckDuckGo search URI from a query string *)\nlet query_uri query =\n  let base_uri = Uri.of_string \"http://api.duckduckgo.com/?format=json\" in\n  Uri.add_query_param base_uri (\"q\", [query])\n\n(* part 1 *)\n(* Extract the \"Definition\" or \"Abstract\" field from the DuckDuckGo results *)\nlet get_definition_from_json json =\n  match Yojson.Safe.from_string json with\n  | `Assoc kv_list ->\n    let find key =\n      begin match List.Assoc.find kv_list key with\n      | None | Some (`String \"\") -> None\n      | Some s -> Some (Yojson.Safe.to_string s)\n      end\n    in\n    begin match find \"Abstract\" with\n    | Some _ as x -> x\n    | None -> find \"Definition\"\n    end\n  | _ -> None\n\n(* part 2 *)\n(* Execute the DuckDuckGo search *)\nlet get_definition word =\n  Cohttp_async.Client.get (query_uri word)\n  >>= fun (_, body) ->\n  Pipe.to_list (Cohttp_async.Body.to_pipe body)\n  >>| fun strings ->\n  (word, get_definition_from_json (String.concat strings))\n\n(* part 3 *)\n(* Print out a word/definition pair *)\nlet print_result (word,definition) =\n  printf \"%s\\n%s\\n\\n%s\\n\\n\"\n    word\n    (String.init (String.length word) ~f:(fun _ -> '-'))\n    (match definition with\n    | None -> \"No definition found\"\n    | Some def ->\n      String.concat ~sep:\"\\n\"\n        (Wrapper.wrap (Wrapper.make 70) def))\n\n(* part 4 *)\n(* Run many searches in parallel, printing out the results after they're all\n   done. *)\nlet search_and_print words =\n  Deferred.all (List.map words ~f:get_definition)\n  >>| fun results ->\n  List.iter results ~f:print_result\n\n(* part 5 *)\nlet () =\n  Command.async_basic\n    ~summary:\"Retrieve definitions from duckduckgo search engine\"\n    Command.Spec.(\n      empty\n      +> anon (sequence (\"word\" %: string))\n    )\n    (fun words () -> search_and_print words)\n  |> Command.run\n\n"
  },
  {
    "path": "code/async/search_out_of_order.ml",
    "content": "open Core.Std\nopen Async.Std\n\n(* Generate a DuckDuckGo search URI from a query string *)\nlet query_uri =\n  let base_uri = Uri.of_string \"http://api.duckduckgo.com/?format=json\" in\n  fun query -> Uri.add_query_param base_uri (\"q\", [query])\n\n(* Extract the \"Definition\" or \"Abstract\" field from the DuckDuckGo results *)\nlet get_definition_from_json json =\n  match Yojson.Safe.from_string json with\n  | `Assoc kv_list ->\n    let find key =\n      begin match List.Assoc.find kv_list key with\n      | None | Some (`String \"\") -> None\n      | Some s -> Some (Yojson.Safe.to_string s)\n      end\n    in\n    begin match find \"Abstract\" with\n    | Some _ as x -> x\n    | None -> find \"Definition\"\n    end\n  | _ -> None\n\n(* Execute the DuckDuckGo search *)\nlet get_definition word =\n  Cohttp_async.Client.get (query_uri word)\n  >>= fun (_,body) ->\n  Pipe.to_list body\n  >>| fun strings ->\n  (word, get_definition_from_json (String.concat strings))\n\n(* Print out a word/definition pair *)\nlet print_result (word,definition) =\n  printf \"%s\\n%s\\n\\n%s\\n\\n\"\n    word\n    (String.init (String.length word) ~f:(fun _ -> '-'))\n    (match definition with\n    | None -> \"No definition found\"\n    | Some def -> String.concat ~sep:\"\\n\" (Wrapper.wrap (Wrapper.make 70)  def))\n\n(* part 1 *)\n(* Run many searches in parallel, printing out the results as you go *)\nlet search_and_print words =\n  Deferred.all_unit (List.map words ~f:(fun word ->\n    get_definition word >>| print_result))\n(* part 2 *)\n\nlet () =\n  Command.async_basic\n    ~summary:\"Retrieve definitions from duckduckgo search engine\"\n    Command.Spec.(\n      empty\n      +> anon (sequence (\"word\" %: string))\n    )\n    (fun words () -> search_and_print words)\n  |> Command.run\n"
  },
  {
    "path": "code/async/search_with_configurable_server.ml",
    "content": "open Core.Std\nopen Async.Std\n\n(* part 1 *)\n(* Generate a DuckDuckGo search URI from a query string *)\nlet query_uri ~server query =\n  let base_uri =\n    Uri.of_string (String.concat [\"http://\";server;\"/?format=json\"])\n  in\n  Uri.add_query_param base_uri (\"q\", [query])\n(* part 2 *)\n(* Extract the \"Definition\" or \"Abstract\" field from the DuckDuckGo results *)\nlet get_definition_from_json json =\n  match Yojson.Safe.from_string json with\n  | `Assoc kv_list ->\n    let find key =\n      begin match List.Assoc.find kv_list key with\n      | None | Some (`String \"\") -> None\n      | Some s -> Some (Yojson.Safe.to_string s)\n      end\n    in\n    begin match find \"Abstract\" with\n    | Some _ as x -> x\n    | None -> find \"Definition\"\n    end\n  | _ -> None\n\n(* Execute the DuckDuckGo search *)\nlet get_definition ~server word =\n  Cohttp_async.Client.get (query_uri ~server word)\n  >>= fun  (_, body) ->\n  Pipe.to_list body\n  >>| fun strings ->\n  (word, get_definition_from_json (String.concat strings))\n\n(* Print out a word/definition pair *)\nlet print_result (word,definition) =\n  printf \"%s\\n%s\\n\\n%s\\n\\n\"\n    word\n    (String.init (String.length word) ~f:(fun _ -> '-'))\n    (match definition with\n    | None -> \"No definition found\"\n    | Some def ->\n      String.concat ~sep:\"\\n\"\n        (Wrapper.wrap (Wrapper.make 70) def))\n\n(* Run many searches in parallel, printing out the results after they're all\n   done. *)\nlet search_and_print ~servers words =\n  let servers = Array.of_list servers in\n  Deferred.all (List.mapi words ~f:(fun i word ->\n    let server = servers.(i mod Array.length servers) in\n    get_definition ~server word))\n  >>| fun results ->\n  List.iter results ~f:print_result\n\nlet () =\n  Command.async_basic\n    ~summary:\"Retrieve definitions from duckduckgo search engine\"\n    Command.Spec.(\n      let string_list = Arg_type.create (String.split ~on:',') in\n      empty\n      +> anon (sequence (\"word\" %: string))\n      +> flag \"-servers\"\n           (optional_with_default [\"api.duckduckgo.com\"] string_list)\n           ~doc:\" Specify server to connect to\"\n    )\n    (fun words servers () -> search_and_print ~servers words)\n  |> Command.run\n"
  },
  {
    "path": "code/async/search_with_error_handling.ml",
    "content": "open Core.Std\nopen Async.Std\n\n(* Generate a DuckDuckGo search URI from a query string *)\nlet query_uri ~server query =\n  let base_uri =\n    Uri.of_string (String.concat [\"http://\";server;\"/?format=json\"])\n  in\n  Uri.add_query_param base_uri (\"q\", [query])\n\n(* Extract the \"Definition\" or \"Abstract\" field from the DuckDuckGo results *)\nlet get_definition_from_json json =\n  match Yojson.Safe.from_string json with\n  | `Assoc kv_list ->\n    let find key =\n      begin match List.Assoc.find kv_list key with\n      | None | Some (`String \"\") -> None\n      | Some s -> Some (Yojson.Safe.to_string s)\n      end\n    in\n    begin match find \"Abstract\" with\n    | Some _ as x -> x\n    | None -> find \"Definition\"\n    end\n  | _ -> None\n\n(* part 1 *)\n(* Execute the DuckDuckGo search *)\nlet get_definition ~server word =\n  try_with (fun () ->\n    Cohttp_async.Client.get (query_uri ~server word)\n    >>= fun  (_, body) ->\n    Pipe.to_list (Cohttp_async.Body.to_pipe body)\n    >>| fun strings ->\n    (word, get_definition_from_json (String.concat strings)))\n  >>| function\n  | Ok (word,result) -> (word, Ok result)\n  | Error _          -> (word, Error \"Unexpected failure\")\n(* part 2 *)\n(* Print out a word/definition pair *)\nlet print_result (word,definition) =\n  printf \"%s\\n%s\\n\\n%s\\n\\n\"\n    word\n    (String.init (String.length word) ~f:(fun _ -> '-'))\n    (match definition with\n     | Error s -> \"DuckDuckGo query failed: \" ^ s\n     | Ok None -> \"No definition found\"\n     | Ok (Some def) ->\n       String.concat ~sep:\"\\n\"\n         (Wrapper.wrap (Wrapper.make 70) def))\n(* part 3 *)\n(* Run many searches in parallel, printing out the results after they're all\n   done. *)\nlet search_and_print ~servers words =\n  let servers = Array.of_list servers in\n  Deferred.all (List.mapi words ~f:(fun i word ->\n    let server = servers.(i mod Array.length servers) in\n    get_definition ~server word))\n  >>| fun results ->\n  List.iter results ~f:print_result\n\nlet () =\n  Command.async_basic\n    ~summary:\"Retrieve definitions from duckduckgo search engine\"\n    Command.Spec.(\n      let string_list = Arg_type.create (String.split ~on:',') in\n      empty\n      +> anon (sequence (\"word\" %: string))\n      +> flag \"-servers\"\n           (optional_with_default [\"api.duckduckgo.com\"] string_list)\n           ~doc:\" Specify server to connect to\"\n    )\n    (fun words servers () -> search_and_print ~servers words)\n  |> Command.run\n"
  },
  {
    "path": "code/async/search_with_error_handling_deprecated.ml",
    "content": "open Core.Std\nopen Async.Std\n\n(* Generate a DuckDuckGo search URI from a query string *)\nlet query_uri ~server query =\n  let base_uri =\n    Uri.of_string (String.concat [\"http://\";server;\"/?format=json\"])\n  in\n  Uri.add_query_param base_uri (\"q\", [query])\n\n(* Extract the \"Definition\" or \"Abstract\" field from the DuckDuckGo results *)\nlet get_definition_from_json json =\n  match Yojson.Safe.from_string json with\n  | `Assoc kv_list ->\n    let find key =\n      begin match List.Assoc.find kv_list key with\n      | None | Some (`String \"\") -> None\n      | Some s -> Some (Yojson.Safe.to_string s)\n      end\n    in\n    begin match find \"Abstract\" with\n    | Some _ as x -> x\n    | None -> find \"Definition\"\n    end\n  | _ -> None\n\n(* Execute the DuckDuckGo search *)\nlet get_definition ~server word =\n  try_with (fun () ->\n    Cohttp_async.Client.get (query_uri ~server word)\n    >>= fun (_, body) ->\n    Pipe.to_list body\n    >>| fun strings ->\n    (word, get_definition_from_json (String.concat strings)))\n  >>| function\n  | Ok (word,result) -> (word, Ok result)\n  | Error exn        -> (word, Error exn)\n\n\n(* Print out a word/definition pair *)\nlet print_result (word,definition) =\n  printf \"%s\\n%s\\n\\n%s\\n\\n\"\n    word\n    (String.init (String.length word) ~f:(fun _ -> '-'))\n    (match definition with\n     | Error _ -> \"DuckDuckGo query failed unexpectedly\"\n     | Ok None -> \"No definition found\"\n     | Ok (Some def) ->\n       String.concat ~sep:\"\\n\"\n         (Wrapper.wrap (Wrapper.make 70) def))\n\n(* Run many searches in parallel, printing out the results after they're all\n   done. *)\nlet search_and_print ~server words =\n  Deferred.all (List.map ~f:(get_definition ~server) words)\n  >>| fun results ->\n  List.iter results ~f:print_result\n\nlet () =\n  Command.async_basic\n    ~summary:\"Retrieve definitions from duckduckgo search engine\"\n    Command.Spec.(\n      empty\n      +> anon (sequence (\"word\" %: string))\n      +> flag \"-server\" (optional_with_default \"api.duckduckgo.com\" string)\n           ~doc:\" Specify server to connect to\"\n    )\n    (fun words server () -> search_and_print ~server words)\n  |> Command.run\n"
  },
  {
    "path": "code/async/search_with_timeout.ml",
    "content": "open Core.Std\nopen Async.Std\n\n(* Generate a DuckDuckGo search URI from a query string *)\nlet query_uri ~server query =\n  let base_uri =\n    Uri.of_string (String.concat [\"http://\";server;\"/?format=json\"])\n  in\n  Uri.add_query_param base_uri (\"q\", [query])\n\n(* Extract the \"Definition\" or \"Abstract\" field from the DuckDuckGo results *)\nlet get_definition_from_json json =\n  match Yojson.Safe.from_string json with\n  | `Assoc kv_list ->\n    let find key =\n      begin match List.Assoc.find kv_list key with\n      | None | Some (`String \"\") -> None\n      | Some s -> Some (Yojson.Safe.to_string s)\n      end\n    in\n    begin match find \"Abstract\" with\n    | Some _ as x -> x\n    | None -> find \"Definition\"\n    end\n  | _ -> None\n\n(* Execute the DuckDuckGo search *)\nlet get_definition ~server word =\n  try_with (fun () ->\n    Cohttp_async.Client.get (query_uri ~server word)\n    >>= fun  (_, body) ->\n    Pipe.to_list body\n    >>| fun strings ->\n    (word, get_definition_from_json (String.concat strings)))\n  >>| function\n  | Ok (word,result) -> (word, Ok result)\n  | Error exn        -> (word, Error exn)\n\n(* part 1 *)\nlet get_definition_with_timeout ~server ~timeout word =\n  Deferred.any\n    [ (after timeout >>| fun () -> (word,Error \"Timed out\"))\n    ; (get_definition ~server word\n       >>| fun (word,result) ->\n       let result' = match result with\n         | Ok _ as x -> x\n         | Error _ -> Error \"Unexpected failure\"\n       in\n       (word,result')\n      )\n    ]\n(* part 2 *)\n(* Print out a word/definition pair *)\nlet print_result (word,definition) =\n  printf \"%s\\n%s\\n\\n%s\\n\\n\"\n    word\n    (String.init (String.length word) ~f:(fun _ -> '-'))\n    (match definition with\n     | Error s -> \"DuckDuckGo query failed: \" ^ s\n     | Ok None -> \"No definition found\"\n     | Ok (Some def) ->\n       String.concat ~sep:\"\\n\"\n         (Wrapper.wrap (Wrapper.make 70) def))\n\n(* Run many searches in parallel, printing out the results after they're all\n   done. *)\nlet search_and_print ~servers ~timeout words =\n  let servers = Array.of_list servers in\n  Deferred.all (List.mapi words ~f:(fun i word ->\n    let server = servers.(i mod Array.length servers) in\n    get_definition_with_timeout ~server ~timeout word))\n  >>| fun results ->\n  List.iter results ~f:print_result\n\nlet () =\n  Command.async_basic\n    ~summary:\"Retrieve definitions from duckduckgo search engine\"\n    Command.Spec.(\n      let string_list = Arg_type.create (String.split ~on:',') in\n      empty\n      +> anon (sequence (\"word\" %: string))\n      +> flag \"-servers\"\n           (optional_with_default [\"api.duckduckgo.com\"] string_list)\n           ~doc:\" Specify server to connect to\"\n      +> flag \"-timeout\" (optional_with_default (sec 5.) time_span)\n           ~doc:\" Abandon queries that take longer than this time\"\n    )\n    (fun words servers timeout () ->\n       search_and_print ~servers ~timeout words)\n  |> Command.run\n"
  },
  {
    "path": "code/async/search_with_timeout_choice.ml",
    "content": "open Core.Std\nopen Async.Std\n\n(* Generate a DuckDuckGo search URI from a query string *)\nlet query_uri ~server query =\n  let base_uri =\n    Uri.of_string (String.concat [\"http://\";server;\"/?format=json\"])\n  in\n  Uri.add_query_param base_uri (\"q\", [query])\n\n(* Extract the \"Definition\" or \"Abstract\" field from the DuckDuckGo results *)\nlet get_definition_from_json json =\n  match Yojson.Safe.from_string json with\n  | `Assoc kv_list ->\n    let find key =\n      begin match List.Assoc.find kv_list key with\n      | None | Some (`String \"\") -> None\n      | Some s -> Some (Yojson.Safe.to_string s)\n      end\n    in\n    begin match find \"Abstract\" with\n    | Some _ as x -> x\n    | None -> find \"Definition\"\n    end\n  | _ -> None\n\n(* Execute the DuckDuckGo search *)\nlet get_definition ~server ~interrupt word =\n  try_with (fun () ->\n    Cohttp_async.Client.get ~interrupt (query_uri ~server word)\n    >>= fun  (_, body) ->\n    Pipe.to_list body\n    >>| fun strings ->\n    (word, get_definition_from_json (String.concat strings)))\n  >>| function\n  | Ok (word,result) -> (word, Ok result)\n  | Error exn        -> (word, Error exn)\n\nlet get_definition_with_timeout ~server ~timeout word =\n  let interrupt = Ivar.create () in\n  choose\n    [ choice (after timeout) (fun () ->\n       Ivar.fill interrupt ();\n       (word,Error \"Timed out\"))\n    ; choice (get_definition ~server ~interrupt:(Ivar.read interrupt) word)\n        (fun (word,result) ->\n           let result' = match result with\n             | Ok _ as x -> x\n             | Error _ -> Error \"Unexpected failure\"\n           in\n           (word,result')\n        )\n    ]\n\n(* Print out a word/definition pair *)\nlet print_result (word,definition) =\n  printf \"%s\\n%s\\n\\n%s\\n\\n\"\n    word\n    (String.init (String.length word) ~f:(fun _ -> '-'))\n    (match definition with\n     | Error _ -> \"DuckDuckGo query failed unexpectedly\"\n     | Ok None -> \"No definition found\"\n     | Ok (Some def) ->\n       String.concat ~sep:\"\\n\"\n         (Wrapper.wrap (Wrapper.make 70) def))\n\n(* Run many searches in parallel, printing out the results after they're all\n   done. *)\nlet search_and_print ~servers ~timeout words =\n  let servers = Array.of_list servers in\n  Deferred.all (List.mapi words ~f:(fun i word ->\n    let server = servers.(i mod Array.length servers) in\n    get_definition_with_timeout ~server ~timeout word))\n  >>| fun results ->\n  List.iter results ~f:print_result\n\nlet () =\n  Command.async_basic\n    ~summary:\"Retrieve definitions from duckduckgo search engine\"\n    Command.Spec.(\n      let string_list = Arg_type.create (String.split ~on:',') in\n      empty\n      +> anon (sequence (\"word\" %: string))\n      +> flag \"-servers\"\n           (optional_with_default [\"api.duckduckgo.com\"] string_list)\n           ~doc:\" Specify server to connect to\"\n      +> flag \"-timeout\" (optional_with_default (sec 5.) time_span)\n           ~doc:\" Abandon queries that take longer than this time\"\n    )\n    (fun words servers timeout () ->\n       search_and_print ~servers ~timeout words)\n  |> Command.run\n"
  },
  {
    "path": "code/async/search_with_timeout_no_leak.ml",
    "content": "open Core.Std\nopen Async.Std\n\n(* Generate a DuckDuckGo search URI from a query string *)\nlet query_uri ~server query =\n  let base_uri =\n    Uri.of_string (String.concat [\"http://\";server;\"/?format=json\"])\n  in\n  Uri.add_query_param base_uri (\"q\", [query])\n\n(* Extract the \"Definition\" or \"Abstract\" field from the DuckDuckGo results *)\nlet get_definition_from_json json =\n  match Yojson.Safe.from_string json with\n  | `Assoc kv_list ->\n    let find key =\n      begin match List.Assoc.find kv_list key with\n      | None | Some (`String \"\") -> None\n      | Some s -> Some (Yojson.Safe.to_string s)\n      end\n    in\n    begin match find \"Abstract\" with\n    | Some _ as x -> x\n    | None -> find \"Definition\"\n    end\n  | _ -> None\n(* part 1 *)\n(* Execute the DuckDuckGo search *)\nlet get_definition ~server ~interrupt word =\n  try_with (fun () ->\n    Cohttp_async.Client.get ~interrupt (query_uri ~server word)\n    >>= fun  (_, body) ->\n    Pipe.to_list (Cohttp_async.Body.to_pipe body)\n    >>| fun strings ->\n    (word, get_definition_from_json (String.concat strings)))\n  >>| function\n  | Ok (word,result) -> (word, Ok result)\n  | Error exn        -> (word, Error exn)\n(* part 2 *)\nlet get_definition_with_timeout ~server ~timeout word =\n  let interrupt = Ivar.create () in\n  choose\n    [ choice (after timeout) (fun () ->\n       Ivar.fill interrupt ();\n       (word,Error \"Timed out\"))\n    ; choice (get_definition ~server ~interrupt:(Ivar.read interrupt) word)\n        (fun (word,result) ->\n           let result' = match result with\n             | Ok _ as x -> x\n             | Error _ -> Error \"Unexpected failure\"\n           in\n           (word,result')\n        )\n    ]\n(* part 3 *)\n\n(* Print out a word/definition pair *)\nlet print_result (word,definition) =\n  printf \"%s\\n%s\\n\\n%s\\n\\n\"\n    word\n    (String.init (String.length word) ~f:(fun _ -> '-'))\n    (match definition with\n     | Error s -> \"DuckDuckGo query failed: \" ^ s\n     | Ok None -> \"No definition found\"\n     | Ok (Some def) ->\n       String.concat ~sep:\"\\n\"\n         (Wrapper.wrap (Wrapper.make 70) def))\n\n(* Run many searches in parallel, printing out the results after they're all\n   done. *)\nlet search_and_print ~servers ~timeout words =\n  let servers = Array.of_list servers in\n  Deferred.all (List.mapi words ~f:(fun i word ->\n    let server = servers.(i mod Array.length servers) in\n    get_definition_with_timeout ~server ~timeout word))\n  >>| fun results ->\n  List.iter results ~f:print_result\n\nlet () =\n  Command.async_basic\n    ~summary:\"Retrieve definitions from duckduckgo search engine\"\n    Command.Spec.(\n      let string_list = Arg_type.create (String.split ~on:',') in\n      empty\n      +> anon (sequence (\"word\" %: string))\n      +> flag \"-servers\"\n           (optional_with_default [\"api.duckduckgo.com\"] string_list)\n           ~doc:\" Specify server to connect to\"\n      +> flag \"-timeout\" (optional_with_default (sec 5.) time_span)\n           ~doc:\" Abandon queries that take longer than this time\"\n    )\n    (fun words servers timeout () ->\n       search_and_print ~servers ~timeout words)\n  |> Command.run\n"
  },
  {
    "path": "code/async/search_with_timeout_no_leak_simple.ml",
    "content": "open Core.Std\nopen Async.Std\n\n(* Generate a DuckDuckGo search URI from a query string *)\nlet query_uri ~server query =\n  let base_uri =\n    Uri.of_string (String.concat [\"http://\";server;\"/?format=json\"])\n  in\n  Uri.add_query_param base_uri (\"q\", [query])\n\n(* Extract the \"Definition\" or \"Abstract\" field from the DuckDuckGo results *)\nlet get_definition_from_json json =\n  match Yojson.Safe.from_string json with\n  | `Assoc kv_list ->\n    let find key =\n      begin match List.Assoc.find kv_list key with\n      | None | Some (`String \"\") -> None\n      | Some s -> Some (Yojson.Safe.to_string s)\n      end\n    in\n    begin match find \"Abstract\" with\n    | Some _ as x -> x\n    | None -> find \"Definition\"\n    end\n  | _ -> None\n(* part 1 *)\n(* Execute the DuckDuckGo search *)\nlet get_definition ~server ~interrupt word =\n  try_with (fun () ->\n    Cohttp_async.Client.get ~interrupt (query_uri ~server word)\n    >>= fun  (_, body) ->\n    Pipe.to_list body\n    >>| fun strings ->\n    (word, get_definition_from_json (String.concat strings)))\n  >>| function\n  | Ok (word,result) -> (word, Ok result)\n  | Error exn        -> (word, Error exn)\n(* part 2 *)\nlet get_definition_with_timeout ~server ~timeout word =\n  get_definition ~server ~interrupt:(after timeout) word\n  >>| fun (word,result) ->\n  let result' = match result with\n    | Ok _ as x -> x\n    | Error _ -> Error \"Unexpected failure\"\n  in\n  (word,result')\n(* part 3 *)\n(* Print out a word/definition pair *)\nlet print_result (word,definition) =\n  printf \"%s\\n%s\\n\\n%s\\n\\n\"\n    word\n    (String.init (String.length word) ~f:(fun _ -> '-'))\n    (match definition with\n     | Error _ -> \"DuckDuckGo query failed unexpectedly\"\n     | Ok None -> \"No definition found\"\n     | Ok (Some def) ->\n       String.concat ~sep:\"\\n\"\n         (Wrapper.wrap (Wrapper.make 70) def))\n\n(* Run many searches in parallel, printing out the results after they're all\n   done. *)\nlet search_and_print ~servers ~timeout words =\n  let servers = Array.of_list servers in\n  Deferred.all (List.mapi words ~f:(fun i word ->\n    let server = servers.(i mod Array.length servers) in\n    get_definition_with_timeout ~server ~timeout word))\n  >>| fun results ->\n  List.iter results ~f:print_result\n\nlet () =\n  Command.async_basic\n    ~summary:\"Retrieve definitions from duckduckgo search engine\"\n    Command.Spec.(\n      let string_list = Arg_type.create (String.split ~on:',') in\n      empty\n      +> anon (sequence (\"word\" %: string))\n      +> flag \"-servers\"\n           (optional_with_default [\"api.duckduckgo.com\"] string_list)\n           ~doc:\" Specify server to connect to\"\n      +> flag \"-timeout\" (optional_with_default (sec 5.) time_span)\n           ~doc:\" Abandon queries that take longer than this time\"\n    )\n    (fun words servers timeout () ->\n       search_and_print ~servers ~timeout words)\n  |> Command.run\n"
  },
  {
    "path": "code/async/search_with_timeout_simple.ml",
    "content": "open Core.Std\nopen Async.Std\n\n(* Generate a DuckDuckGo search URI from a query string *)\nlet query_uri ~server query =\n  let base_uri =\n    Uri.of_string (String.concat [\"http://\";server;\"/?format=json\"])\n  in\n  Uri.add_query_param base_uri (\"q\", [query])\n\n(* Extract the \"Definition\" or \"Abstract\" field from the DuckDuckGo results *)\nlet get_definition_from_json json =\n  match Yojson.Safe.from_string json with\n  | `Assoc kv_list ->\n    let find key =\n      begin match List.Assoc.find kv_list key with\n      | None | Some (`String \"\") -> None\n      | Some s -> Some (Yojson.Safe.to_string s)\n      end\n    in\n    begin match find \"Abstract\" with\n    | Some _ as x -> x\n    | None -> find \"Definition\"\n    end\n  | _ -> None\n\n(* Execute the DuckDuckGo search *)\nlet get_definition ~server word =\n  try_with (fun () ->\n    Cohttp_async.Client.get (query_uri ~server word)\n    >>= fun (_, body) ->\n    Pipe.to_list body\n    >>| fun strings ->\n    (word, get_definition_from_json (String.concat strings)))\n  >>| function\n  | Ok (word,result) -> (word, Ok result)\n  | Error exn        -> (word, Error exn)\n\nlet get_definition_with_timeout ~server ~timeout word =\n  choose\n    [ choice (after timeout) (fun () -> (word,Error \"Timed out\"))\n    ; choice (get_definition ~server word)\n        (fun (word,result) ->\n           let result' = match result with\n             | Ok x    -> Ok x\n             | Error _ -> Error \"Unexpected failure\"\n           in\n           (word,result')\n        )\n    ]\n\n(* Print out a word/definition pair *)\nlet print_result (word,definition) =\n  printf \"%s\\n%s\\n\\n%s\\n\\n\"\n    word\n    (String.init (String.length word) ~f:(fun _ -> '-'))\n    (match definition with\n     | Error msg -> \"ERROR: \" ^ msg\n     | Ok None -> \"No definition found\"\n     | Ok (Some def) ->\n       String.concat ~sep:\"\\n\"\n         (Wrapper.wrap (Wrapper.make 70) def))\n\n(* Run many searches in parallel, printing out the results after they're all\n   done. *)\nlet search_and_print ~server ~timeout words =\n  Deferred.all (List.map words\n                  ~f:(get_definition_with_timeout ~timeout ~server))\n  >>| fun results ->\n  List.iter results ~f:print_result\n\nlet () =\n  Command.async_basic\n    ~summary:\"Retrieve definitions from duckduckgo search engine\"\n    Command.Spec.(\n      empty\n      +> anon (sequence (\"word\" %: string))\n      +> flag \"-server\" (optional_with_default \"api.duckduckgo.com\" string)\n           ~doc:\" Specify server to connect to\"\n      +> flag \"-timeout\" (optional_with_default (sec 5.) time_span)\n           ~doc:\" Abandon queries that take longer than this time\"\n    )\n    (fun words server timeout () ->\n       search_and_print ~server ~timeout words)\n  |> Command.run\n"
  },
  {
    "path": "code/async/test.txt",
    "content": "This is only a test."
  },
  {
    "path": "code/async/thread_exp_async_busy_loop.ml",
    "content": "open Core.Std\nopen Async.Std\nopen Thread_exp_common\n\n\n(* part 1 *)\nlet busy_loop n =\n  let x = ref None in\n  for i = 1 to 100_000_000 do x := Some i done\n\nlet () =\n  don't_wait_for\n    (log_delays (Deferred.unit >>= busy_loop))\n\n(* part 2 *)\nlet () = finish ()\n\n\n\n"
  },
  {
    "path": "code/async/thread_exp_async_busy_loop_in_thread.ml",
    "content": "open Core.Std\nopen Async.Std\nopen Thread_exp_common\n\n\n(* part 1 *)\nlet busy_loop n =\n  let x = ref None in\n  for i = 1 to 100_000_000 do x := Some i done\n\nlet () =\n  don't_wait_for\n    (log_delays (In_thread.run busy_loop))\n\n(* part 2 *)\nlet () = finish ()\n\n\n\n"
  },
  {
    "path": "code/async/thread_exp_async_noalloc_busy_loop.ml",
    "content": "open Core.Std\nopen Async.Std\nopen Thread_exp_common\n\n\n(* part 1 *)\nlet busy_loop () =\n  for i = 1 to 200_000_000 do () done\n\nlet () =\n  don't_wait_for\n    (log_delays (In_thread.run busy_loop))\n\n(* part 2 *)\nlet () = finish ()\n\n\n\n"
  },
  {
    "path": "code/async/thread_exp_async_noalloc_busy_loop_in_thread.ml",
    "content": "open Core.Std\nopen Async.Std\nopen Thread_exp_common\n\n\n(* part 1 *)\nlet busy_loop () =\n  for i = 1 to 200_000_000 do () done\n\nlet () =\n  don't_wait_for\n    (log_delays (In_thread.run busy_loop))\n\n(* part 2 *)\nlet () = finish ()\n\n\n\n"
  },
  {
    "path": "code/async/thread_exp_async_only.ml",
    "content": "open Core.Std\nopen Async.Std\nopen Thread_exp_common\n\nlet () =\n  Command.async_basic\n    ~summary:\"run logger without busy loop\"\n    Command.Spec.(empty)\n    (fun () ->\n       log_delays (after (sec 1.))\n    )\n  |> Command.run\n"
  },
  {
    "path": "code/async/thread_exp_common.ml",
    "content": "open Core.Std\nopen Async.Std\n\nlet log_delays d =\n    let start = Time.now () in\n    let rec loop stamps =\n      let delay = Time.diff (Time.now ()) start in\n      match Deferred.peek d with\n      | Some () -> return (delay :: stamps)\n      | None ->\n        after (sec 0.1)\n        >>= fun () ->\n        loop (delay :: stamps)\n    in\n    loop []\n    >>| fun delays ->\n    let sexp = <:sexp_of<Time.Span.t list>> (List.rev delays) in\n    printf \"%s\\n\" (Sexp.to_string sexp)\n\nlet finish () =\n  shutdown 0;\n  never_returns (Scheduler.go ())\n"
  },
  {
    "path": "code/async/thread_experiments.ml",
    "content": "open Core.Std\nopen Async.Std\n\nlet log_delays thunk =\n  let start = Time.now () in\n  let print_time () =\n    let diff = Time.diff (Time.now ()) start in\n    Caml.Printf.printf \".%!\";\n    printf \"%s, \" (Time.Span.to_string diff)\n  in\n  let d = thunk () in\n  Clock.every (sec 0.1) ~stop:d print_time;\n  d >>| fun () -> print_time (); printf \"\\n\"\n\ntype how_to_wait =\n  | After\n  | Busyloop\n  | Busyloop_in_thread\n  | Noalloc_busyloop_in_thread\n  | Noalloc_busyloop_in_thread_2\nwith sexp\n\nlet busyloop () =\n  let x = ref None in\n  for i = 1 to 50_000_000 do x := Some i done\n\nlet noalloc_busyloop () =\n  for _i = 1 to 50_000_000 do () done\n\nlet noalloc_busyloop_2 () =\n  let rec loop i =\n    if i = 0 then () else loop (i-1)\n  in\n  loop 50_000_000\n\nlet wait_and_log how_to_wait =\n  let until = match how_to_wait with\n    | After                        -> (fun () -> after (sec 1.))\n    | Busyloop                     -> (fun () -> busyloop (); return ())\n    | Busyloop_in_thread           -> (fun () -> In_thread.run busyloop)\n    | Noalloc_busyloop_in_thread   -> (fun () -> In_thread.run noalloc_busyloop)\n    | Noalloc_busyloop_in_thread_2 -> (fun () -> In_thread.run noalloc_busyloop_2)\n  in\n  log_delays until\n\nlet how_to_wait =\n  Command.Spec.Arg_type.create\n    (fun s -> Sexp.of_string s |> how_to_wait_of_sexp)\n\nlet () =\n  Command.async_basic\n    ~summary:\"run logger without busy loop\"\n    Command.Spec.(\n      empty\n      +> anon (\"how-to-wait\" %: how_to_wait)\n    )\n    (fun how () -> wait_and_log how)\n  |> Command.run\n"
  },
  {
    "path": "code/async/timeout_search.ml",
    "content": "open Core.Std\nopen Async.Std\nmodule Cohttp = Cohttp_async\n\n(* Generate a DuckDuckGo search URI from a query string *)\nlet query_uri =\n  let base_uri = Uri.of_string \"http://api.duckduckgo.com/?format=json\" in\n  fun query -> Uri.add_query_param base_uri (\"q\", [query])\n\n(* Extract the \"Definition\" field from the DuckDuckGo results *)\nlet get_definition_from_json json =\n  match Yojson.Safe.from_string json with\n  | `Assoc kv_list ->\n    begin match List.Assoc.find kv_list \"Definition\" with\n    | None | Some (`String \"\") -> Or_error.error_string \"No definition found\"\n    | Some s -> Ok (Yojson.Safe.to_string s)\n    end\n  | _ -> Or_error.error_string \"malformed reply\"\n\n(* Execute the DuckDuckGo search *)\nlet get_definition ~timeout word =\n  let get =\n    Cohttp.Client.call `GET (query_uri word)\n    >>= fun (_, body) ->\n    Pipe.to_list body\n    >>| fun strings ->\n    get_definition_from_json (String.concat strings)\n  in\n  match timeout with\n  | None -> get\n  | Some timeout ->\n    let timeout = Clock.after timeout in\n    choose [ choice get     Fn.id\n           ; choice timeout (fun () -> Or_error.error_string \"timed out\")\n           ]\n\n(* Run a single search and print out the results *)\nlet run_one_search ~timeout search_string =\n  get_definition ~timeout search_string >>| fun result ->\n  printf \"%-10s : %s\\n\" search_string\n    (match result with\n    | Ok x -> x\n    | Error err -> \"{\" ^ Error.to_string_hum err ^ \"}\")\n\n(* Run many searches in parallel, printing out the results as you go *)\nlet run_many_searches ~parallel ~timeout search_strings =\n  Deferred.List.iter search_strings ~f:(run_one_search ~timeout)\n    ~how:(if parallel then `Parallel else `Sequential)\n\nlet () =\n  Command.async_basic\n    ~summary:\"Retrieve definitions from duckduckgo search engine\"\n    Command.Spec.(\n      empty\n      +> flag \"-timeout\" (optional time_span) ~doc:\" Whether to run queries in parallel\"\n      +> flag \"-parallel\" no_arg ~doc:\" Run queries in parallel\"\n      +> anon (sequence (\"search term\" %: string))\n    )\n    (fun timeout parallel search_strings () ->\n      run_many_searches ~parallel ~timeout search_strings)\n  |> Command.run\n"
  },
  {
    "path": "code/back-end/alternate_list.ml",
    "content": "open Core.Std\n\nlet rec take =\n  function\n  |[] -> []\n  |hd::tl -> hd :: (skip tl)\nand skip =\n  function\n  |[] -> []\n  |_::tl -> take tl\n\nlet () =\n  take [1;2;3;4;5;6;7;8;9]\n  |> List.map ~f:string_of_int\n  |> String.concat ~sep:\",\"\n  |> print_endline\n"
  },
  {
    "path": "code/back-end/asm_from_compare_mono.sh",
    "content": "ocamlopt -inline 20 -nodynlink -S compare_mono.ml\n"
  },
  {
    "path": "code/back-end/cmp.S",
    "content": "_camlCompare_mono__cmp_1008:\n        .cfi_startproc\n.L101:\n        cmpq    %rbx, %rax\n        jle     .L100\n        ret\n        .align  2\n.L100:\n        movq    %rbx, %rax\n        ret\n        .cfi_endproc\n"
  },
  {
    "path": "code/back-end/compare_mono.ml",
    "content": "let cmp (a:int) (b:int) =\n  if a > b then a else b\n"
  },
  {
    "path": "code/back-end/compare_mono.s",
    "content": "\t.data\n\t.globl\t_camlCompare_mono__data_begin\n_camlCompare_mono__data_begin:\n\t.text\n\t.globl\t_camlCompare_mono__code_begin\n_camlCompare_mono__code_begin:\n\tnop\n\t.data\n\t.quad\t1024\n\t.globl\t_camlCompare_mono\n_camlCompare_mono:\n\t.space\t8\n\t.data\n\t.quad\t3319\n_camlCompare_mono__1:\n\t.quad\t_caml_curry2\n\t.quad\t5\n\t.quad\t_camlCompare_mono__cmp_1008\n\t.text\n\t.align\t4\n\t.globl\t_camlCompare_mono__cmp_1008\n_camlCompare_mono__cmp_1008:\n\t.cfi_startproc\n.L101:\n\tcmpq\t%rbx, %rax\n\tjle\t.L100\n\tret\n\t.align\t2\n.L100:\n\tmovq\t%rbx, %rax\n\tret\n\t.cfi_endproc\n\t.text\n\t.align\t4\n\t.globl\t_camlCompare_mono__entry\n_camlCompare_mono__entry:\n\t.cfi_startproc\n.L102:\n\tleaq\t_camlCompare_mono__1(%rip), %rax\n\tmovq\t%rax, _camlCompare_mono(%rip)\n\tmovq\t$1, %rax\n\tret\n\t.cfi_endproc\n\t.data\n\t.text\n\tnop\n\t.globl\t_camlCompare_mono__code_end\n_camlCompare_mono__code_end:\n\t.data\n\t.globl\t_camlCompare_mono__data_end\n_camlCompare_mono__data_end:\n\t.long\t0\n\t.globl\t_camlCompare_mono__frametable\n_camlCompare_mono__frametable:\n\t.quad\t0\n"
  },
  {
    "path": "code/back-end/compare_poly.ml",
    "content": "let cmp a b =\n  if a > b then a else b\n"
  },
  {
    "path": "code/back-end/compare_poly_asm.S",
    "content": "_camlCompare_poly__cmp_1008:\n        .cfi_startproc\n        subq    $24, %rsp\n        .cfi_adjust_cfa_offset  24\n.L101:\n        movq    %rax, 8(%rsp)\n        movq    %rbx, 0(%rsp)\n        movq    %rax, %rdi\n        movq    %rbx, %rsi\n        leaq    _caml_greaterthan(%rip), %rax\n        call    _caml_c_call\n.L102:\n        leaq    _caml_young_ptr(%rip), %r11\n        movq    (%r11), %r15\n        cmpq    $1, %rax\n        je      .L100\n        movq    8(%rsp), %rax\n        addq    $24, %rsp\n        .cfi_adjust_cfa_offset  -24\n        ret\n        .cfi_adjust_cfa_offset  24\n        .align  2\n.L100:\n        movq    0(%rsp), %rax\n        addq    $24, %rsp\n        .cfi_adjust_cfa_offset  -24\n        ret\n        .cfi_adjust_cfa_offset  24\n        .cfi_endproc\n"
  },
  {
    "path": "code/back-end/gdb_alternate0.rawsh",
    "content": "$ gdb ./alternate_list.native\nGNU gdb (GDB) 7.4.1-debian\nCopyright (C) 2012 Free Software Foundation, Inc.\nLicense GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.  Type \"show copying\"\nand \"show warranty\" for details.\nThis GDB was configured as \"x86_64-linux-gnu\".\nFor bug reporting instructions, please see:\n<http://www.gnu.org/software/gdb/bugs/>...\nReading symbols from /home/avsm/alternate_list.native...done.\n(gdb)\n"
  },
  {
    "path": "code/back-end/gdb_alternate1.rawsh",
    "content": "(gdb) break camlAlternate_list__take_69242 \nBreakpoint 1 at 0x5658d0: file alternate_list.ml, line 5.\n"
  },
  {
    "path": "code/back-end/gdb_alternate2.rawsh",
    "content": "(gdb) run\nStarting program: /home/avsm/alternate_list.native\n[Thread debugging using libthread_db enabled]\nUsing host libthread_db library \"/lib/x86_64-linux-gnu/libthread_db.so.1\".\n\nBreakpoint 1, camlAlternate_list__take_69242 () at alternate_list.ml:5\n4         function\n"
  },
  {
    "path": "code/back-end/gdb_alternate3.rawsh",
    "content": "(gdb) cont\nContinuing.\n\nBreakpoint 1, camlAlternate_list__take_69242 () at alternate_list.ml:5\n4         function\n(gdb) cont\nContinuing.\n\nBreakpoint 1, camlAlternate_list__take_69242 () at alternate_list.ml:5\n4         function\n(gdb) bt\n#0  camlAlternate_list__take_69242 () at alternate_list.ml:4\n#1  0x00000000005658e7 in camlAlternate_list__take_69242 () at alternate_list.ml:6\n#2  0x00000000005658e7 in camlAlternate_list__take_69242 () at alternate_list.ml:6\n#3  0x00000000005659f7 in camlAlternate_list__entry () at alternate_list.ml:14\n#4  0x0000000000560029 in caml_program ()\n#5  0x000000000080984a in caml_start_program ()\n#6  0x00000000008099a0 in ?? ()\n#7  0x0000000000000000 in ?? ()\n(gdb) clear camlAlternate_list__take_69242\nDeleted breakpoint 1 \n(gdb) cont\nContinuing.\n1,3,5,7,9\n[Inferior 1 (process 3546) exited normally]\n"
  },
  {
    "path": "code/back-end/instr_for_pattern_monomorphic_small.sh",
    "content": "ocamlc -dinstr pattern_monomorphic_small.ml 2>&1\n"
  },
  {
    "path": "code/back-end/lambda_for_pattern_monomorphic_large.sh",
    "content": "ocamlc -dlambda -c pattern_monomorphic_large.ml 2>&1\n"
  },
  {
    "path": "code/back-end/lambda_for_pattern_monomorphic_small.sh",
    "content": "ocamlc -dlambda -c pattern_monomorphic_small.ml 2>&1\n"
  },
  {
    "path": "code/back-end/lambda_for_pattern_polymorphic.sh",
    "content": "ocamlc -dlambda -c pattern_polymorphic.ml 2>&1\n"
  },
  {
    "path": "code/back-end/opam_switch.rawsh",
    "content": "$ opam switch 4.01.0dev+fp\n"
  },
  {
    "path": "code/back-end/pattern_monomorphic_large.ml",
    "content": "type t = | Alice | Bob | Charlie | David\n\nlet test v =\n  match v with\n  | Alice   -> 100\n  | Bob     -> 101\n  | Charlie -> 102\n  | David   -> 103\n"
  },
  {
    "path": "code/back-end/pattern_monomorphic_small.ml",
    "content": "type t = | Alice | Bob \n\nlet test v =\n  match v with\n  | Alice   -> 100\n  | Bob     -> 101\n"
  },
  {
    "path": "code/back-end/pattern_polymorphic.ml",
    "content": "let test v =\n  match v with\n  | `Alice   -> 100\n  | `Bob     -> 101\n  | `Charlie -> 102\n  | `David   -> 103\n  | `Eve     -> 104\n"
  },
  {
    "path": "code/back-end/perf_record.rawsh",
    "content": "$ perf record -g ./barrier_bench.native\nEstimated testing time 20s (change using -quota SECS).\n\n  Name        Time (ns)             Time 95ci   Percentage\n  ----        ---------             ---------   ----------\n  mutable     7_306_219   7_250_234-7_372_469        96.83\n  immutable   7_545_126   7_537_837-7_551_193       100.00\n\n[ perf record: Woken up 11 times to write data ]\n[ perf record: Captured and wrote 2.722 MB perf.data (~118926 samples) ]\nperf record -g ./barrier.native\nEstimated testing time 20s (change using -quota SECS).\n\n  Name        Time (ns)             Time 95ci   Percentage\n  ----        ---------             ---------   ----------\n  mutable     7_306_219   7_250_234-7_372_469        96.83\n  immutable   7_545_126   7_537_837-7_551_193       100.00\n\n[ perf record: Woken up 11 times to write data ]\n[ perf record: Captured and wrote 2.722 MB perf.data (~118926 samples) ]\n"
  },
  {
    "path": "code/back-end/perf_report.rawsh",
    "content": "$ perf report -g\n+  48.86%  barrier.native  barrier.native  [.] camlBarrier__test_immutable_69282\n+  30.22%  barrier.native  barrier.native  [.] camlBarrier__test_mutable_69279\n+  20.22%  barrier.native  barrier.native  [.] caml_modify\n"
  },
  {
    "path": "code/back-end-bench/bench_patterns.ml",
    "content": "open Core.Std\nopen Core_bench.Std\n\ntype t = | Alice | Bob \ntype s = | A | B | C | D | E\n\nlet polymorphic_pattern () =\n  let test v =\n    match v with\n    | `Alice   -> 100\n    | `Bob     -> 101\n    | `Charlie -> 102\n    | `David   -> 103\n    | `Eve     -> 104\n  in\n  List.iter ~f:(fun v -> ignore(test v))\n    [`Alice; `Bob; `Charlie; `David]\n\nlet monomorphic_pattern_small () =\n  let test v =\n    match v with\n    | Alice   -> 100\n    | Bob     -> 101 in\n  List.iter ~f:(fun v -> ignore(test v))\n    [ Alice; Bob ]\n\nlet monomorphic_pattern_large () =\n  let test v =\n    match v with\n    | A       -> 100\n    | B       -> 101\n    | C       -> 102\n    | D       -> 103\n    | E       -> 104\n  in\n  List.iter ~f:(fun v -> ignore(test v))\n    [ A; B; C; D ]\n\nlet tests = [\n  \"Polymorphic pattern\", polymorphic_pattern;\n  \"Monomorphic larger pattern\", monomorphic_pattern_large;\n  \"Monomorphic small pattern\", monomorphic_pattern_small;\n]\n\nlet () =\n  List.map tests ~f:(fun (name,test) -> Bench.Test.create ~name test)\n  |> Bench.make_command\n  |> Command.run\n"
  },
  {
    "path": "code/back-end-bench/bench_poly_and_mono.ml",
    "content": "open Core.Std\nopen Core_bench.Std\n\nlet polymorphic_compare () =\n  let cmp a b = if a > b then a else b in\n  for i = 0 to 1000 do\n    ignore(cmp 0 i)\n  done\n\nlet monomorphic_compare () =\n  let cmp (a:int) (b:int) =\n    if a > b then a else b in\n  for i = 0 to 1000 do\n    ignore(cmp 0 i)\n  done\n\nlet tests =\n  [ \"Polymorphic comparison\", polymorphic_compare;\n    \"Monomorphic comparison\", monomorphic_compare ]\n\nlet () =\n  List.map tests ~f:(fun (name,test) -> Bench.Test.create ~name test)\n  |> Bench.make_command\n  |> Command.run\n"
  },
  {
    "path": "code/back-end-bench/run_alternate_list.sh",
    "content": "corebuild -tag debug alternate_list.native\n./alternate_list.native -ascii\n"
  },
  {
    "path": "code/back-end-bench/run_bench_patterns.sh",
    "content": "corebuild -pkg core_bench bench_patterns.native\n./bench_patterns.native -ascii\n"
  },
  {
    "path": "code/back-end-bench/run_bench_poly_and_mono.sh",
    "content": "corebuild -pkg core_bench bench_poly_and_mono.native\n./bench_poly_and_mono.native -ascii\n"
  },
  {
    "path": "code/back-end-embed/build_embed.sh",
    "content": "rm -f embed_out.c\nocamlc -output-obj -o embed_out.o embed_me1.ml embed_me2.ml\n"
  },
  {
    "path": "code/back-end-embed/build_embed_binary.rawsh",
    "content": "$ gcc -fPIC -Wall -I`ocamlc -where` -L`ocamlc -where` -ltermcap -lm -ldl \\\n  -o finalbc.native main.c embed_out.o -lcamlrun\n$ ./finalbc.native\nBefore calling OCaml\nhello embedded world 1\nhello embedded world 2\nAfter calling OCaml\n"
  },
  {
    "path": "code/back-end-embed/build_embed_c.sh",
    "content": "ocamlc -output-obj -o embed_out.c embed_me1.ml embed_me2.ml\n"
  },
  {
    "path": "code/back-end-embed/build_embed_native.rawsh",
    "content": "$ ocamlopt -output-obj -o embed_native.o embed_me1.ml embed_me2.ml\n$ gcc -Wall -I `ocamlc -where` -o final.native embed_native.o main.c \\\n   -L `ocamlc -where` -lasmrun -ltermcap -lm -ldl\n$ ./final.native\nBefore calling OCaml\nhello embedded world 1\nhello embedded world 2\nAfter calling OCaml\n"
  },
  {
    "path": "code/back-end-embed/embed_me1.ml",
    "content": "let () = print_endline \"hello embedded world 1\"\n"
  },
  {
    "path": "code/back-end-embed/embed_me2.ml",
    "content": "let () = print_endline \"hello embedded world 2\"\n"
  },
  {
    "path": "code/back-end-embed/embed_out.c",
    "content": "#ifdef __cplusplus\nextern \"C\" {\n#endif\n#include <caml/mlvalues.h>\nCAMLextern void caml_startup_code(\n           code_t code, asize_t code_size,\n           char *data, asize_t data_size,\n           char *section_table, asize_t section_table_size,\n           char **argv);\nstatic int caml_code[] = {\n0x00000054, 0x000003e3, 0x00000029, 0x0000002a, 0x00000001, 0x00000000, \n0x00000056, 0x0000000e, 0x00000000, 0x00000044, 0x0000000b, 0x00000043, \n0x0000000d, 0x0000000c, 0x00000032, 0x00000022, 0x0000000b, 0x00000040, \n0x00000000, 0x00000028, 0x00000004, 0x00000001, 0x00000028, 0x00000002, \n0x00000029, 0x0000002a, 0x00000003, 0x00000003, 0x00000085, 0x00000000, \n0x00000004, 0x00000063, 0x00000028, 0x00000004, 0x00000003, 0x0000000d, \n0x0000000d, 0x0000000d, 0x00000060, 0x0000009f, 0x0000000a, 0x00000084, \n0x00000000, 0x00000006, 0x00000035, 0x00000004, 0x0000003f, 0x00000000, \n0x0000005b, 0x00000000, 0x0000000f, 0x0000006f, 0x0000000b, 0x0000000f, \n0x0000006e, 0x0000000e, 0x0000000e, 0x00000032, 0x00000024, 0x00000004, \n0x00000009, 0x00000000, 0x0000005d, 0x0000009d, 0x00000028, 0x00000001, \n0x00000029, 0x0000002a, 0x00000001, 0x00000001, 0x0000000b, 0x0000005e, \n0x000000a7, 0x00000028, 0x00000002, 0x00000029, 0x0000002a, 0x00000001, \n0x00000001, 0x0000000b, 0x0000005e, 0x000000a7, 0x00000028, 0x00000002, \n0x00000029, 0x0000002a, 0x00000001, 0x00000001, 0x0000000b, 0x0000005e, \n0x000000a8, 0x00000028, 0x00000002, 0x00000029, 0x0000002a, 0x00000001, \n0x00000001, 0x0000000b, 0x0000005e, 0x000000b0, 0x00000028, 0x00000002, \n0x00000000, 0x0000005d, 0x000000ac, 0x00000028, 0x00000001, 0x00000000, \n0x0000005d, 0x0000009a, 0x00000028, 0x00000001, 0x00000029, 0x0000002a, \n0x00000001, 0x00000001, 0x0000000b, 0x0000005e, 0x000000b2, 0x00000028, \n0x00000002, 0x00000000, 0x0000005d, 0x000000a0, 0x00000028, 0x00000001, \n0x00000000, 0x0000005d, 0x000000a0, 0x00000028, 0x00000001, 0x00000000, \n0x0000005d, 0x000000a1, 0x00000028, 0x00000001, 0x00000000, 0x0000005d, \n0x00000052, 0x00000028, 0x00000001, 0x00000029, 0x0000002a, 0x00000001, \n0x00000001, 0x0000000b, 0x0000005e, 0x000000ae, 0x00000028, 0x00000002, \n0x00000000, 0x0000005d, 0x000000aa, 0x00000028, 0x00000001, 0x00000000, \n0x0000005d, 0x0000009a, 0x00000028, 0x00000001, 0x00000000, 0x0000005d, \n0x0000009c, 0x00000028, 0x00000001, 0x00000029, 0x0000002a, 0x00000001, \n0x00000001, 0x0000000b, 0x0000005e, 0x000000b2, 0x00000028, 0x00000002, \n0x00000029, 0x0000002a, 0x00000001, 0x00000001, 0x0000000b, 0x0000005e, \n0x000000b1, 0x00000028, 0x00000002, 0x00000000, 0x0000005d, 0x000000ad, \n0x00000028, 0x00000001, 0x00000000, 0x0000005d, 0x0000009b, 0x00000028, \n0x00000001, 0x00000029, 0x0000002a, 0x00000001, 0x00000001, 0x0000000b, \n0x0000005e, 0x000000af, 0x00000028, 0x00000002, 0x00000000, 0x0000005d, \n0x000000ab, 0x00000028, 0x00000001, 0x00000000, 0x0000005d, 0x0000009b, \n0x00000028, 0x00000001, 0x00000063, 0x0000001a, 0x00000021, 0x00000000, \n0x0000005d, 0x00000100, 0x00000028, 0x00000001, 0x00000063, 0x0000001a, \n0x00000043, 0x00000025, 0x00000002, 0x00000063, 0x0000001a, 0x00000021, \n0x00000063, 0x0000001b, 0x00000025, 0x00000002, 0x00000015, 0x00000043, \n0x0000000a, 0x0000000c, 0x0000002b, 0x00000002, 0xfffffff3, 0x0000001a, \n0x00000049, 0x00000028, 0x00000002, 0x00000000, 0x0000000a, 0x0000005d, \n0x000000b3, 0x0000000a, 0x0000005d, 0x00000023, 0x0000000b, 0x00000068, \n0x0000000c, 0x00000068, 0x00000010, 0x00000061, 0x00000019, 0x00000000, \n0x00000028, 0x00000004, 0x00000029, 0x0000002a, 0x00000001, 0x00000001, \n0x00000036, 0x0000000c, 0x0000001a, 0x00000022, 0x0000000b, 0x0000001a, \n0x00000026, 0x00000004, 0x00000063, 0x0000001a, 0x00000021, 0x0000005d, \n0x00000034, 0x00000028, 0x00000001, 0x00000063, 0x0000001a, 0x00000021, \n0x0000005d, 0x00000087, 0x00000028, 0x00000001, 0x00000016, 0x0000005d, \n0x0000009d, 0x00000015, 0x0000001c, 0x00000025, 0x00000002, 0x00000067, \n0x0000000a, 0x0000001a, 0x0000005e, 0x000000a7, 0x00000015, 0x0000005d, \n0x0000009d, 0x00000028, 0x00000001, 0x00000000, 0x0000001a, 0x0000001b, \n0x00000022, 0x00000067, 0x0000000a, 0x0000001a, 0x0000005e, 0x000000a7, \n0x00000015, 0x0000005d, 0x0000009d, 0x00000028, 0x00000001, 0x00000000, \n0x0000001a, 0x00000021, 0x0000001b, 0x0000001c, 0x00000026, 0x00000003, \n0x00000000, 0x0000001a, 0x00000021, 0x0000001b, 0x0000001c, 0x00000026, \n0x00000003, 0x00000000, 0x0000001a, 0x0000001b, 0x00000026, 0x00000003, \n0x00000000, 0x0000001a, 0x0000005e, 0x000000a7, 0x00000028, 0x00000001, \n0x00000067, 0x0000000a, 0x0000001a, 0x0000005e, 0x000000a7, 0x00000015, \n0x0000005d, 0x0000009d, 0x00000028, 0x00000001, 0x00000000, 0x0000001a, \n0x0000001b, 0x00000022, 0x00000067, 0x0000000a, 0x0000001a, 0x0000005e, \n0x000000a7, 0x00000015, 0x0000005d, 0x0000009d, 0x00000028, 0x00000001, \n0x00000000, 0x0000001a, 0x00000021, 0x0000001b, 0x0000001c, 0x00000026, \n0x00000003, 0x00000000, 0x0000001a, 0x00000021, 0x0000001b, 0x0000001c, \n0x00000026, 0x00000003, 0x00000000, 0x0000001a, 0x0000001b, 0x00000026, \n0x00000003, 0x00000000, 0x0000001a, 0x0000005e, 0x000000a7, 0x00000028, \n0x00000001, 0x00000059, 0x00000007, 0x00000004, 0x0000005d, 0x0000009c, \n0x0000005a, 0x00000028, 0x00000001, 0x00000068, 0x00000028, 0x00000002, \n0x00000029, 0x0000002a, 0x00000002, 0x00000002, 0x00000056, 0x00000019, \n0x00000002, 0x00000044, 0x0000000d, 0x00000043, 0x0000000a, 0x0000005d, \n0x000000b3, 0x0000000a, 0x0000000b, 0x00000010, 0x0000006f, 0x0000000f, \n0x00000068, 0x0000000f, 0x00000061, 0x00000019, 0x00000002, 0x0000000b, \n0x00000010, 0x0000006f, 0x0000000f, 0x00000032, 0x00000027, 0x00000009, \n0x00000000, 0x00000028, 0x00000003, 0x00000029, 0x0000002a, 0x00000001, \n0x00000015, 0x0000005d, 0x000000a2, 0x0000000a, 0x00000084, 0x00000000, \n0x00000011, 0x00000001, 0x00000056, 0x00000009, 0x00000001, 0x0000000d, \n0x0000000e, 0x0000005d, 0x00000023, 0x0000001b, 0x00000027, 0x00000006, \n0x00000035, 0x00000004, 0x0000003f, 0x00000000, 0x0000005b, 0x00000000, \n0x00000088, 0x00000000, 0x00000029, 0x00000000, 0x0000007f, 0xffffffff, \n0x0000005d, 0x00000023, 0x0000000b, 0x0000007f, 0xffffffff, 0x00000068, \n0x0000000c, 0x0000001a, 0x00000060, 0x0000009f, 0x00000063, 0x00000015, \n0x0000005d, 0x000000a0, 0x00000063, 0x00000002, 0x00000056, 0x00000011, \n0x00000001, 0x0000000e, 0x0000006e, 0x0000007f, 0xffffffff, 0x0000000d, \n0x0000000c, 0x00000040, 0x00000000, 0x0000000b, 0x0000000c, 0x0000005d, \n0x00000023, 0x0000001b, 0x00000027, 0x00000008, 0x00000000, 0x00000028, \n0x00000004, 0x00000000, 0x0000006d, 0x0000005d, 0x00000023, 0x0000000b, \n0x0000006d, 0x00000068, 0x0000000c, 0x0000001a, 0x00000060, 0x0000009f, \n0x00000063, 0x00000001, 0x0000000e, 0x0000006f, 0x0000000d, 0x0000000c, \n0x00000040, 0x00000000, 0x00000032, 0x00000026, 0x00000006, 0x0000002c, \n0x00000001, 0x00000000, 0xffffff81, 0x00000000, 0x0000000c, 0x0000002c, \n0x00000001, 0x00000002, 0xffffff9c, 0x00000063, 0x00000068, 0x0000000c, \n0x00000026, 0x00000005, 0x00000029, 0x0000002a, 0x00000003, 0x00000002, \n0x00000087, 0x00000000, 0x0000000e, 0x00000003, 0x00000087, 0x00000000, \n0x0000000a, 0x00000003, 0x0000000c, 0x0000005d, 0x000000b3, 0x0000006f, \n0x0000000d, 0x0000007d, 0x00000056, 0x00000006, 0x00000035, 0x0000000d, \n0x0000001a, 0x00000025, 0x00000005, 0x00000003, 0x0000000d, 0x0000000d, \n0x0000000d, 0x0000001b, 0x00000024, 0x00000004, 0x00000008, 0x00000029, \n0x0000002a, 0x00000003, 0x00000002, 0x00000087, 0x00000000, 0x0000000e, \n0x00000003, 0x00000087, 0x00000000, 0x0000000a, 0x00000003, 0x0000000c, \n0x0000005d, 0x000000b3, 0x0000006f, 0x0000000d, 0x0000007d, 0x00000056, \n0x00000006, 0x00000035, 0x0000000e, 0x0000001a, 0x00000025, 0x00000005, \n0x00000003, 0x0000000d, 0x0000000d, 0x0000000d, 0x00000060, 0x0000009f, \n0x00000028, 0x00000004, 0x00000000, 0x00000068, 0x00000036, 0x0000000f, \n0x0000001a, 0x00000027, 0x00000004, 0x00000000, 0x00000068, 0x00000036, \n0x00000010, 0x0000001a, 0x00000027, 0x00000004, 0x00000029, 0x0000002a, \n0x00000002, 0x00000001, 0x0000000b, 0x0000000e, 0x0000005f, 0x00000107, \n0x0000005d, 0x000000a3, 0x00000028, 0x00000003, 0x00000059, 0x00000007, \n0x00000004, 0x0000005d, 0x0000009d, 0x0000005a, 0x00000054, 0x00000004, \n0x00000068, 0x00000013, 0x00000001, 0x00000059, 0x00000007, 0x00000004, \n0x0000005d, 0x0000009c, 0x0000005a, 0x00000028, 0x00000001, 0x00000068, \n0x00000028, 0x00000002, 0x00000000, 0x0000005d, 0x0000009d, 0x00000000, \n0x0000005d, 0x0000009c, 0x00000028, 0x00000001, 0x00000029, 0x0000002a, \n0x00000001, 0x00000063, 0x0000000c, 0x0000000c, 0x0000005f, 0x000000d7, \n0x00000028, 0x00000002, 0x00000029, 0x0000002a, 0x00000003, 0x00000002, \n0x00000087, 0x00000000, 0x0000000e, 0x00000003, 0x00000087, 0x00000000, \n0x0000000a, 0x00000003, 0x0000000c, 0x0000005d, 0x000000b3, 0x0000006f, \n0x0000000d, 0x0000007d, 0x00000056, 0x00000006, 0x00000035, 0x00000011, \n0x0000001a, 0x00000025, 0x00000005, 0x00000003, 0x0000000d, 0x0000000d, \n0x0000000d, 0x00000060, 0x000000a6, 0x00000028, 0x00000004, 0x00000029, \n0x0000002a, 0x00000001, 0x00000001, 0x0000005d, 0x000000b3, 0x00000068, \n0x0000000d, 0x0000000d, 0x00000060, 0x000000a6, 0x00000028, 0x00000002, \n0x00000000, 0x00000056, 0x00000015, 0x00000000, 0x00000044, 0x0000000b, \n0x00000043, 0x00000009, 0x00000059, 0x00000007, 0x00000004, 0x0000005d, \n0x0000009d, 0x0000005a, 0x00000054, 0x00000004, 0x00000068, 0x00000013, \n0x00000001, 0x00000001, 0x00000032, 0x00000025, 0x00000004, 0x00000063, \n0x00000028, 0x00000001, 0x0000002c, 0x00000001, 0x00000000, 0xffffffe3, \n0x00000063, 0x0000005d, 0x000000a5, 0x0000000b, 0x00000025, 0x00000003, \n0x00000000, 0x0000006c, 0x000001b6, 0x00000036, 0x00000012, 0x0000001a, \n0x00000027, 0x00000004, 0x00000000, 0x0000006c, 0x000001b6, 0x00000036, \n0x00000013, 0x0000001a, 0x00000027, 0x00000004, 0x00000029, 0x0000002a, \n0x00000002, 0x00000001, 0x0000000b, 0x0000000e, 0x0000005f, 0x00000107, \n0x0000005d, 0x000000a4, 0x00000028, 0x00000003, 0x00000000, 0x00000036, \n0x00000014, 0x0000005e, 0x00000037, 0x0000001a, 0x00000025, 0x00000002, \n0x00000017, 0x0000000b, 0x0000007e, 0x00000056, 0x00000007, 0x00000035, \n0x00000015, 0x0000001b, 0x0000001a, 0x00000026, 0x00000003, 0x00000000, \n0x0000001b, 0x0000005e, 0x000000eb, 0x0000000a, 0x00000087, 0x00000030, \n0x00000007, 0x00000000, 0x00000086, 0x0000003a, 0x00000009, 0x00000054, \n0x0000000a, 0x00000000, 0x00000084, 0x0000002d, 0x00000003, 0x00000054, \n0x00000004, 0x00000016, 0x00000028, 0x00000002, 0x00000001, 0x0000007f, \n0x00000001, 0x00000032, 0x00000025, 0x00000003, 0x00000000, 0x0000005d, \n0x000000b3, 0x0000000a, 0x0000000c, 0x0000001a, 0x0000002c, 0x00000001, \n0x00000003, 0xffffffcf, 0x00000063, 0x0000000b, 0x00000025, 0x00000004, \n0x00000000, 0x00000036, 0x00000016, 0x0000005e, 0x00000038, 0x00000028, \n0x00000001, 0x00000035, 0x00000017, 0x0000000b, 0x0000005e, 0x000000f3, \n0x00000056, 0x00000010, 0x00000035, 0x00000018, 0x0000000b, 0x0000005e, \n0x000000f3, 0x00000056, 0x00000006, 0x00000035, 0x00000019, 0x0000001a, \n0x00000025, 0x00000002, 0x00000064, 0x00000028, 0x00000001, 0x00000063, \n0x00000028, 0x00000001, 0x00000000, 0x00000056, 0x00000005, 0x00000035, \n0x0000001a, 0x00000028, 0x00000001, 0x00000035, 0x0000001b, 0x00000028, \n0x00000001, 0x00000000, 0x00000087, 0x00000000, 0x00000005, 0x00000000, \n0x00000088, 0x000000ff, 0x00000006, 0x00000035, 0x0000001c, 0x0000001a, \n0x00000025, 0x00000002, 0x00000000, 0x00000028, 0x00000001, 0x00000029, \n0x0000002a, 0x00000001, 0x00000000, 0x0000005d, 0x000000b3, 0x0000000c, \n0x0000005d, 0x000000b3, 0x0000000a, 0x0000000c, 0x0000006e, 0x0000005d, \n0x00000023, 0x0000000c, 0x00000068, 0x0000000c, 0x00000068, 0x00000011, \n0x00000061, 0x00000019, 0x00000001, 0x0000000d, 0x0000000c, 0x00000068, \n0x00000012, 0x00000008, 0x00000061, 0x00000019, 0x00000000, 0x00000028, \n0x00000005, 0x00000067, 0xffffffff, 0x0000000b, 0x00000075, 0x00000028, \n0x00000001, 0x00000000, 0x00000087, 0x00000000, 0x00000004, 0x00000000, \n0x00000028, 0x00000001, 0x00000000, 0x0000006d, 0x00000028, 0x00000001, \n0x00000029, 0x0000002a, 0x00000001, 0x00000001, 0x0000000b, 0x0000005e, \n0x0000004c, 0x00000056, 0x00000004, 0x00000000, 0x00000028, 0x00000002, \n0x00000001, 0x00000028, 0x00000002, 0x00000029, 0x0000002a, 0x00000001, \n0x00000001, 0x0000000b, 0x0000005e, 0x0000008e, 0x00000056, 0x00000004, \n0x00000000, 0x00000028, 0x00000002, 0x00000001, 0x00000028, 0x00000002, \n0x00000000, 0x00000036, 0x00000003, 0x00000040, 0x00000000, 0x0000005b, \n0x00000000, 0x00000036, 0x00000002, 0x00000040, 0x00000000, 0x0000005b, \n0x0000002b, 0x00000000, 0xfffffff8, 0x00000009, 0x0000002b, 0x00000000, \n0xffffffee, 0x00000036, 0x0000001d, 0x0000003f, 0x00000000, 0x00000009, \n0x0000002b, 0x00000000, 0xffffffd8, 0x00000009, 0x0000002b, 0x00000000, \n0xffffffc5, 0x00000009, 0x0000002b, 0x00000000, 0xffffffb5, 0x00000009, \n0x0000002b, 0x00000000, 0xffffffab, 0x0000006c, 0x0000001f, 0x00000069, \n0x00000076, 0x00000084, 0x00000000, 0x00000005, 0x00000067, 0x0000001e, \n0x00000054, 0x00000003, 0x00000067, 0x0000003e, 0x00000069, 0x00000076, \n0x0000000a, 0x0000007f, 0xffffffff, 0x00000036, 0x0000001e, 0x0000005d, \n0x00000071, 0x00000036, 0x0000001f, 0x0000005d, 0x00000071, 0x00000036, \n0x00000020, 0x0000005d, 0x00000071, 0x00000036, 0x00000021, 0x0000005d, \n0x00000071, 0x00000036, 0x00000022, 0x0000005d, 0x00000071, 0x00000036, \n0x00000023, 0x0000005d, 0x00000071, 0x00000009, 0x0000002b, 0x00000000, \n0xffffff5e, 0x00000012, 0x0000000e, 0x0000002b, 0x00000001, 0xffffff48, \n0x00000009, 0x0000002b, 0x00000000, 0xffffff39, 0x00000012, 0x00000010, \n0x0000002b, 0x00000001, 0xffffff1b, 0x00000009, 0x0000002b, 0x00000000, \n0xffffff10, 0x00000009, 0x0000003a, 0x0000000f, 0x0000002b, 0x00000001, \n0xfffffefc, 0x0000000a, 0x0000002b, 0x00000001, 0xfffffec8, 0x00000009, \n0x0000002c, 0x00000001, 0x00000000, 0xfffffbb6, 0x00000063, 0x0000005d, \n0x000000a3, 0x00000069, 0x0000005d, 0x000000a4, 0x0000006a, 0x0000005d, \n0x000000a4, 0x00000009, 0x0000002b, 0x00000000, 0xfffffeab, 0x0000000a, \n0x0000002b, 0x00000001, 0xfffffe9e, 0x0000000b, 0x0000002b, 0x00000001, \n0xfffffe92, 0x00000009, 0x0000002b, 0x00000000, 0xfffffe84, 0x00000009, \n0x0000002b, 0x00000000, 0xfffffe5a, 0x00000012, 0x0000001e, 0x0000002b, \n0x00000001, 0xfffffe34, 0x00000009, 0x0000002b, 0x00000000, 0xfffffe26, \n0x00000009, 0x0000002b, 0x00000000, 0xfffffe19, 0x00000009, 0x0000002b, \n0x00000000, 0xfffffdff, 0x00000009, 0x0000002b, 0x00000000, 0xfffffdf0, \n0x0000000a, 0x0000002b, 0x00000001, 0xfffffde4, 0x0000000b, 0x0000002b, \n0x00000001, 0xfffffdd9, 0x00000012, 0x00000025, 0x0000002b, 0x00000001, \n0xfffffdb4, 0x00000009, 0x0000002c, 0x00000001, 0x00000000, 0xfffffb88, \n0x00000000, 0x00000012, 0x00000028, 0x0000002b, 0x00000002, 0xfffffd88, \n0x00000009, 0x0000002b, 0x00000000, 0xfffffd74, 0x00000009, 0x0000002b, \n0x00000000, 0xfffffce8, 0x00000012, 0x00000012, 0x0000002b, 0x00000001, \n0xfffffcdd, 0x00000012, 0x0000000d, 0x00000012, 0x00000014, 0x0000002b, \n0x00000002, 0xfffffcd1, 0x00000012, 0x0000000e, 0x00000012, 0x00000015, \n0x00000012, 0x0000001c, 0x0000002b, 0x00000003, 0xfffffcc1, 0x00000012, \n0x0000000f, 0x00000012, 0x00000016, 0x00000012, 0x0000001a, 0x0000002b, \n0x00000003, 0xfffffcb1, 0x00000012, 0x00000010, 0x00000012, 0x00000017, \n0x0000002b, 0x00000002, 0xfffffc9c, 0x00000012, 0x00000017, 0x0000002b, \n0x00000001, 0xfffffc8d, 0x00000012, 0x00000017, 0x0000002b, 0x00000001, \n0xfffffc82, 0x00000012, 0x00000013, 0x00000012, 0x00000019, 0x0000002b, \n0x00000002, 0xfffffc76, 0x00000012, 0x00000014, 0x00000012, 0x0000001a, \n0x00000012, 0x00000022, 0x0000002b, 0x00000003, 0xfffffc66, 0x00000012, \n0x00000015, 0x00000012, 0x0000001b, 0x00000012, 0x00000020, 0x0000002b, \n0x00000003, 0xfffffc56, 0x00000012, 0x00000016, 0x00000012, 0x0000001c, \n0x0000002b, 0x00000002, 0xfffffc41, 0x00000012, 0x0000001c, 0x0000002b, \n0x00000001, 0xfffffc32, 0x00000012, 0x0000000d, 0x00000012, 0x0000001f, \n0x00000012, 0x00000021, 0x0000002b, 0x00000003, 0xfffffc22, 0x0000000a, \n0x0000002b, 0x00000001, 0xfffffc17, 0x0000000b, 0x0000002b, 0x00000001, \n0xfffffc0c, 0x00000009, 0x0000003a, 0x00000012, 0x0000002c, 0x0000002b, \n0x00000001, 0xfffffbfa, 0x00000009, 0x0000002b, 0x00000000, 0xfffffbe4, \n0x00000012, 0x0000001f, 0x0000003f, 0x00000000, 0x0000000a, 0x0000002b, \n0x00000001, 0xfffffbd1, 0x0000000b, 0x0000002b, 0x00000001, 0xfffffbc1, \n0x0000000a, 0x0000002b, 0x00000001, 0xfffffbb5, 0x0000000b, 0x00000036, \n0x00000024, 0x0000005e, 0x000000df, 0x00000001, 0x00000012, 0x0000001a, \n0x00000012, 0x0000002e, 0x0000000f, 0x0000000e, 0x00000012, 0x0000000a, \n0x00000012, 0x0000000a, 0x00000009, 0x0000002b, 0x00000000, 0xfffffb9c, \n0x00000009, 0x0000002b, 0x00000000, 0xfffffb93, 0x00000009, 0x0000002b, \n0x00000000, 0xfffffb87, 0x00000009, 0x0000002b, 0x00000000, 0xfffffb7d, \n0x00000009, 0x0000002b, 0x00000000, 0xfffffb74, 0x00000009, 0x0000002b, \n0x00000000, 0xfffffb68, 0x0000003e, 0x00000006, 0x00000000, 0x00000009, \n0x0000002b, 0x00000000, 0xfffffb58, 0x00000012, 0x0000001f, 0x00000009, \n0x0000002b, 0x00000000, 0xfffffb4c, 0x00000009, 0x0000002b, 0x00000000, \n0xfffffb43, 0x00000009, 0x0000002b, 0x00000000, 0xfffffb3a, 0x00000009, \n0x0000002b, 0x00000000, 0xfffffb2e, 0x00000009, 0x0000002b, 0x00000000, \n0xfffffb24, 0x00000009, 0x0000002b, 0x00000000, 0xfffffb1b, 0x00000009, \n0x0000002b, 0x00000000, 0xfffffb12, 0x00000012, 0x00000029, 0x00000012, \n0x0000002c, 0x00000012, 0x0000002a, 0x00000009, 0x0000002b, 0x00000000, \n0xfffffb03, 0x00000012, 0x00000032, 0x00000012, 0x00000031, 0x00000012, \n0x00000033, 0x00000009, 0x0000002b, 0x00000000, 0xfffffaf1, 0x00000012, \n0x00000037, 0x00000012, 0x00000039, 0x00000009, 0x0000002b, 0x00000000, \n0xfffffae3, 0x00000009, 0x0000002b, 0x00000000, 0xfffffada, 0x00000009, \n0x0000002b, 0x00000000, 0xffffface, 0x00000012, 0x0000003e, 0x00000009, \n0x0000002b, 0x00000000, 0xfffffabf, 0x00000009, 0x0000002b, 0x00000000, \n0xfffffab2, 0x00000012, 0x00000042, 0x00000012, 0x00000044, 0x00000009, \n0x0000002b, 0x00000000, 0xfffffaa1, 0x00000012, 0x00000047, 0x00000009, \n0x0000002b, 0x00000000, 0xfffffa95, 0x00000012, 0x0000004c, 0x00000012, \n0x0000004b, 0x00000012, 0x0000004d, 0x00000012, 0x00000030, 0x00000012, \n0x00000032, 0x00000012, 0x00000034, 0x00000012, 0x00000036, 0x00000012, \n0x00000038, 0x00000012, 0x0000003a, 0x00000012, 0x0000003c, 0x00000012, \n0x0000003e, 0x00000012, 0x00000040, 0x00000012, 0x00000042, 0x00000012, \n0x00000044, 0x00000012, 0x00000046, 0x00000012, 0x00000048, 0x00000012, \n0x0000004a, 0x00000012, 0x0000004c, 0x00000012, 0x0000005f, 0x00000012, \n0x00000061, 0x00000012, 0x00000063, 0x00000012, 0x00000065, 0x00000012, \n0x00000067, 0x00000012, 0x0000006b, 0x00000012, 0x0000006d, 0x00000012, \n0x0000006f, 0x00000012, 0x00000071, 0x00000012, 0x00000073, 0x00000012, \n0x00000075, 0x00000012, 0x00000077, 0x00000012, 0x00000079, 0x00000012, \n0x0000007b, 0x00000012, 0x0000007d, 0x00000012, 0x0000007f, 0x00000012, \n0x00000083, 0x00000012, 0x00000083, 0x00000012, 0x00000083, 0x00000012, \n0x00000087, 0x00000012, 0x00000089, 0x00000012, 0x0000008b, 0x00000012, \n0x0000008d, 0x00000012, 0x00000090, 0x00000012, 0x00000090, 0x0000003e, \n0x00000051, 0x00000000, 0x00000013, 0x00000042, 0x00000039, 0x00000025, \n0x00000035, 0x00000026, 0x00000038, 0x00000025, 0x0000001d, 0x00000021, \n0x00000009, 0x0000003a, 0x00000013, 0x00000001, 0x00000039, 0x00000027, \n0x00000035, 0x00000028, 0x00000038, 0x00000025, 0x0000001d, 0x00000021, \n0x00000009, 0x0000003a, 0x00000013, 0x00000001, 0x00000039, 0x00000029, \n\n0x8f};\n\nstatic char caml_data[] = {\n132, 149, 166, 190, 0, 0, 1, 211, 0, 0, 0, 60, \n0, 0, 0, 254, 0, 0, 0, 204, 8, 0, 0, 168, \n0, 144, 45, 79, 117, 116, 95, 111, 102, 95, 109, 101, \n109, 111, 114, 121, 144, 41, 83, 121, 115, 95, 101, 114, \n114, 111, 114, 144, 39, 70, 97, 105, 108, 117, 114, 101, \n144, 48, 73, 110, 118, 97, 108, 105, 100, 95, 97, 114, \n103, 117, 109, 101, 110, 116, 144, 43, 69, 110, 100, 95, \n111, 102, 95, 102, 105, 108, 101, 144, 48, 68, 105, 118, \n105, 115, 105, 111, 110, 95, 98, 121, 95, 122, 101, 114, \n111, 144, 41, 78, 111, 116, 95, 102, 111, 117, 110, 100, \n144, 45, 77, 97, 116, 99, 104, 95, 102, 97, 105, 108, \n117, 114, 101, 144, 46, 83, 116, 97, 99, 107, 95, 111, \n118, 101, 114, 102, 108, 111, 119, 144, 46, 83, 121, 115, \n95, 98, 108, 111, 99, 107, 101, 100, 95, 105, 111, 144, \n46, 65, 115, 115, 101, 114, 116, 95, 102, 97, 105, 108, \n117, 114, 101, 144, 58, 85, 110, 100, 101, 102, 105, 110, \n101, 100, 95, 114, 101, 99, 117, 114, 115, 105, 118, 101, \n95, 109, 111, 100, 117, 108, 101, 34, 37, 44, 44, 114, \n101, 97, 108, 108, 121, 95, 105, 110, 112, 117, 116, 37, \n105, 110, 112, 117, 116, 160, 64, 160, 70, 64, 160, 64, \n160, 71, 64, 38, 111, 117, 116, 112, 117, 116, 160, 65, \n160, 67, 160, 68, 160, 70, 64, 160, 65, 160, 67, 160, \n68, 160, 71, 64, 37, 37, 46, 49, 50, 103, 33, 46, \n34, 37, 100, 37, 102, 97, 108, 115, 101, 36, 116, 114, \n117, 101, 46, 98, 111, 111, 108, 95, 111, 102, 95, 115, \n116, 114, 105, 110, 103, 36, 116, 114, 117, 101, 37, 102, \n97, 108, 115, 101, 43, 99, 104, 97, 114, 95, 111, 102, \n95, 105, 110, 116, 47, 80, 101, 114, 118, 97, 115, 105, \n118, 101, 115, 46, 69, 120, 105, 116, 18, 95, 106, 0, \n127, 240, 0, 0, 0, 0, 0, 0, 18, 95, 106, 0, \n255, 240, 0, 0, 0, 0, 0, 0, 18, 95, 106, 0, \n127, 240, 0, 0, 0, 0, 0, 1, 18, 95, 106, 0, \n127, 239, 255, 255, 255, 255, 255, 255, 18, 95, 106, 0, \n0, 16, 0, 0, 0, 0, 0, 0, 18, 95, 106, 0, \n60, 176, 0, 0, 0, 0, 0, 0, 53, 80, 101, 114, \n118, 97, 115, 105, 118, 101, 115, 46, 100, 111, 95, 97, \n116, 95, 101, 120, 105, 116, 64, 54, 104, 101, 108, 108, \n111, 32, 101, 109, 98, 101, 100, 100, 101, 100, 32, 119, \n111, 114, 108, 100, 32, 49, 64, 54, 104, 101, 108, 108, \n111, 32, 101, 109, 98, 101, 100, 100, 101, 100, 32, 119, \n111, 114, 108, 100, 32, 50, 64, \n};\n\nstatic char caml_sections[] = {\n132, 149, 166, 190, 0, 0, 22, 254, 0, 0, 0, 66, \n0, 0, 6, 126, 0, 0, 3, 176, 160, 160, 36, 83, \n89, 77, 66, 160, 106, 208, 208, 208, 208, 64, 176, 64, \n41, 69, 109, 98, 101, 100, 95, 109, 101, 49, 65, 103, \n208, 64, 176, 64, 41, 69, 109, 98, 101, 100, 95, 109, \n101, 50, 65, 105, 64, 65, 66, 176, 64, 42, 80, 101, \n114, 118, 97, 115, 105, 118, 101, 115, 65, 101, 208, 208, \n64, 176, 80, 45, 77, 97, 116, 99, 104, 95, 102, 97, \n105, 108, 117, 114, 101, 67, 71, 64, 65, 176, 81, 45, \n79, 117, 116, 95, 111, 102, 95, 109, 101, 109, 111, 114, \n121, 67, 64, 208, 64, 176, 82, 48, 73, 110, 118, 97, \n108, 105, 100, 95, 97, 114, 103, 117, 109, 101, 110, 116, \n67, 67, 64, 65, 66, 67, 176, 83, 39, 70, 97, 105, \n108, 117, 114, 101, 67, 66, 208, 208, 64, 176, 84, 41, \n78, 111, 116, 95, 102, 111, 117, 110, 100, 67, 70, 64, \n65, 176, 85, 41, 83, 121, 115, 95, 101, 114, 114, 111, \n114, 67, 65, 64, 66, 68, 176, 86, 43, 69, 110, 100, \n95, 111, 102, 95, 102, 105, 108, 101, 67, 68, 208, 208, \n64, 176, 87, 48, 68, 105, 118, 105, 115, 105, 111, 110, \n95, 98, 121, 95, 122, 101, 114, 111, 67, 69, 64, 65, \n176, 88, 46, 83, 116, 97, 99, 107, 95, 111, 118, 101, \n114, 102, 108, 111, 119, 67, 72, 208, 208, 64, 176, 89, \n46, 83, 121, 115, 95, 98, 108, 111, 99, 107, 101, 100, \n95, 105, 111, 67, 73, 64, 65, 176, 90, 46, 65, 115, \n115, 101, 114, 116, 95, 102, 97, 105, 108, 117, 114, 101, \n67, 74, 208, 64, 176, 91, 58, 85, 110, 100, 101, 102, \n105, 110, 101, 100, 95, 114, 101, 99, 117, 114, 115, 105, \n118, 101, 95, 109, 111, 100, 117, 108, 101, 67, 75, 64, \n65, 66, 67, 69, 160, 160, 36, 80, 82, 73, 77, 10, \n0, 0, 21, 97, 99, 97, 109, 108, 95, 97, 98, 115, \n95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, \n97, 99, 111, 115, 95, 102, 108, 111, 97, 116, 0, 99, \n97, 109, 108, 95, 97, 100, 100, 95, 102, 108, 111, 97, \n116, 0, 99, 97, 109, 108, 95, 97, 108, 108, 111, 99, \n95, 100, 117, 109, 109, 121, 0, 99, 97, 109, 108, 95, \n97, 108, 108, 111, 99, 95, 100, 117, 109, 109, 121, 95, \n102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 97, \n114, 114, 97, 121, 95, 97, 112, 112, 101, 110, 100, 0, \n99, 97, 109, 108, 95, 97, 114, 114, 97, 121, 95, 98, \n108, 105, 116, 0, 99, 97, 109, 108, 95, 97, 114, 114, \n97, 121, 95, 99, 111, 110, 99, 97, 116, 0, 99, 97, \n109, 108, 95, 97, 114, 114, 97, 121, 95, 103, 101, 116, \n0, 99, 97, 109, 108, 95, 97, 114, 114, 97, 121, 95, \n103, 101, 116, 95, 97, 100, 100, 114, 0, 99, 97, 109, \n108, 95, 97, 114, 114, 97, 121, 95, 103, 101, 116, 95, \n102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 97, \n114, 114, 97, 121, 95, 115, 101, 116, 0, 99, 97, 109, \n108, 95, 97, 114, 114, 97, 121, 95, 115, 101, 116, 95, \n97, 100, 100, 114, 0, 99, 97, 109, 108, 95, 97, 114, \n114, 97, 121, 95, 115, 101, 116, 95, 102, 108, 111, 97, \n116, 0, 99, 97, 109, 108, 95, 97, 114, 114, 97, 121, \n95, 115, 117, 98, 0, 99, 97, 109, 108, 95, 97, 114, \n114, 97, 121, 95, 117, 110, 115, 97, 102, 101, 95, 103, \n101, 116, 0, 99, 97, 109, 108, 95, 97, 114, 114, 97, \n121, 95, 117, 110, 115, 97, 102, 101, 95, 103, 101, 116, \n95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, \n97, 114, 114, 97, 121, 95, 117, 110, 115, 97, 102, 101, \n95, 115, 101, 116, 0, 99, 97, 109, 108, 95, 97, 114, \n114, 97, 121, 95, 117, 110, 115, 97, 102, 101, 95, 115, \n101, 116, 95, 97, 100, 100, 114, 0, 99, 97, 109, 108, \n95, 97, 114, 114, 97, 121, 95, 117, 110, 115, 97, 102, \n101, 95, 115, 101, 116, 95, 102, 108, 111, 97, 116, 0, \n99, 97, 109, 108, 95, 97, 115, 105, 110, 95, 102, 108, \n111, 97, 116, 0, 99, 97, 109, 108, 95, 97, 116, 97, \n110, 50, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, \n108, 95, 97, 116, 97, 110, 95, 102, 108, 111, 97, 116, \n0, 99, 97, 109, 108, 95, 98, 97, 99, 107, 116, 114, \n97, 99, 101, 95, 115, 116, 97, 116, 117, 115, 0, 99, \n97, 109, 108, 95, 98, 105, 116, 118, 101, 99, 116, 95, \n116, 101, 115, 116, 0, 99, 97, 109, 108, 95, 98, 108, \n105, 116, 95, 115, 116, 114, 105, 110, 103, 0, 99, 97, \n109, 108, 95, 98, 115, 119, 97, 112, 49, 54, 0, 99, \n97, 109, 108, 95, 99, 101, 105, 108, 95, 102, 108, 111, \n97, 116, 0, 99, 97, 109, 108, 95, 99, 104, 97, 110, \n110, 101, 108, 95, 100, 101, 115, 99, 114, 105, 112, 116, \n111, 114, 0, 99, 97, 109, 108, 95, 99, 108, 97, 115, \n115, 105, 102, 121, 95, 102, 108, 111, 97, 116, 0, 99, \n97, 109, 108, 95, 99, 111, 109, 112, 97, 114, 101, 0, \n99, 97, 109, 108, 95, 99, 111, 110, 118, 101, 114, 116, \n95, 114, 97, 119, 95, 98, 97, 99, 107, 116, 114, 97, \n99, 101, 0, 99, 97, 109, 108, 95, 99, 111, 112, 121, \n115, 105, 103, 110, 95, 102, 108, 111, 97, 116, 0, 99, \n97, 109, 108, 95, 99, 111, 115, 95, 102, 108, 111, 97, \n116, 0, 99, 97, 109, 108, 95, 99, 111, 115, 104, 95, \n102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 99, \n114, 101, 97, 116, 101, 95, 115, 116, 114, 105, 110, 103, \n0, 99, 97, 109, 108, 95, 100, 105, 118, 95, 102, 108, \n111, 97, 116, 0, 99, 97, 109, 108, 95, 100, 121, 110, \n108, 105, 110, 107, 95, 97, 100, 100, 95, 112, 114, 105, \n109, 105, 116, 105, 118, 101, 0, 99, 97, 109, 108, 95, \n100, 121, 110, 108, 105, 110, 107, 95, 99, 108, 111, 115, \n101, 95, 108, 105, 98, 0, 99, 97, 109, 108, 95, 100, \n121, 110, 108, 105, 110, 107, 95, 103, 101, 116, 95, 99, \n117, 114, 114, 101, 110, 116, 95, 108, 105, 98, 115, 0, \n99, 97, 109, 108, 95, 100, 121, 110, 108, 105, 110, 107, \n95, 108, 111, 111, 107, 117, 112, 95, 115, 121, 109, 98, \n111, 108, 0, 99, 97, 109, 108, 95, 100, 121, 110, 108, \n105, 110, 107, 95, 111, 112, 101, 110, 95, 108, 105, 98, \n0, 99, 97, 109, 108, 95, 101, 110, 115, 117, 114, 101, \n95, 115, 116, 97, 99, 107, 95, 99, 97, 112, 97, 99, \n105, 116, 121, 0, 99, 97, 109, 108, 95, 101, 113, 95, \n102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 101, \n113, 117, 97, 108, 0, 99, 97, 109, 108, 95, 101, 120, \n112, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, \n95, 101, 120, 112, 109, 49, 95, 102, 108, 111, 97, 116, \n0, 99, 97, 109, 108, 95, 102, 105, 108, 108, 95, 115, \n116, 114, 105, 110, 103, 0, 99, 97, 109, 108, 95, 102, \n105, 110, 97, 108, 95, 114, 101, 103, 105, 115, 116, 101, \n114, 0, 99, 97, 109, 108, 95, 102, 105, 110, 97, 108, \n95, 114, 101, 108, 101, 97, 115, 101, 0, 99, 97, 109, \n108, 95, 102, 108, 111, 97, 116, 95, 99, 111, 109, 112, \n97, 114, 101, 0, 99, 97, 109, 108, 95, 102, 108, 111, \n97, 116, 95, 111, 102, 95, 105, 110, 116, 0, 99, 97, \n109, 108, 95, 102, 108, 111, 97, 116, 95, 111, 102, 95, \n115, 116, 114, 105, 110, 103, 0, 99, 97, 109, 108, 95, \n102, 108, 111, 111, 114, 95, 102, 108, 111, 97, 116, 0, \n99, 97, 109, 108, 95, 102, 109, 111, 100, 95, 102, 108, \n111, 97, 116, 0, 99, 97, 109, 108, 95, 102, 111, 114, \n109, 97, 116, 95, 102, 108, 111, 97, 116, 0, 99, 97, \n109, 108, 95, 102, 111, 114, 109, 97, 116, 95, 105, 110, \n116, 0, 99, 97, 109, 108, 95, 102, 114, 101, 120, 112, \n95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, \n103, 99, 95, 99, 111, 109, 112, 97, 99, 116, 105, 111, \n110, 0, 99, 97, 109, 108, 95, 103, 99, 95, 99, 111, \n117, 110, 116, 101, 114, 115, 0, 99, 97, 109, 108, 95, \n103, 99, 95, 102, 117, 108, 108, 95, 109, 97, 106, 111, \n114, 0, 99, 97, 109, 108, 95, 103, 99, 95, 103, 101, \n116, 0, 99, 97, 109, 108, 95, 103, 99, 95, 109, 97, \n106, 111, 114, 0, 99, 97, 109, 108, 95, 103, 99, 95, \n109, 97, 106, 111, 114, 95, 115, 108, 105, 99, 101, 0, \n99, 97, 109, 108, 95, 103, 99, 95, 109, 105, 110, 111, \n114, 0, 99, 97, 109, 108, 95, 103, 99, 95, 113, 117, \n105, 99, 107, 95, 115, 116, 97, 116, 0, 99, 97, 109, \n108, 95, 103, 99, 95, 115, 101, 116, 0, 99, 97, 109, \n108, 95, 103, 99, 95, 115, 116, 97, 116, 0, 99, 97, \n109, 108, 95, 103, 101, 95, 102, 108, 111, 97, 116, 0, \n99, 97, 109, 108, 95, 103, 101, 116, 95, 99, 117, 114, \n114, 101, 110, 116, 95, 99, 97, 108, 108, 115, 116, 97, \n99, 107, 0, 99, 97, 109, 108, 95, 103, 101, 116, 95, \n99, 117, 114, 114, 101, 110, 116, 95, 101, 110, 118, 105, \n114, 111, 110, 109, 101, 110, 116, 0, 99, 97, 109, 108, \n95, 103, 101, 116, 95, 101, 120, 99, 101, 112, 116, 105, \n111, 110, 95, 98, 97, 99, 107, 116, 114, 97, 99, 101, \n0, 99, 97, 109, 108, 95, 103, 101, 116, 95, 101, 120, \n99, 101, 112, 116, 105, 111, 110, 95, 114, 97, 119, 95, \n98, 97, 99, 107, 116, 114, 97, 99, 101, 0, 99, 97, \n109, 108, 95, 103, 101, 116, 95, 103, 108, 111, 98, 97, \n108, 95, 100, 97, 116, 97, 0, 99, 97, 109, 108, 95, \n103, 101, 116, 95, 112, 117, 98, 108, 105, 99, 95, 109, \n101, 116, 104, 111, 100, 0, 99, 97, 109, 108, 95, 103, \n101, 116, 95, 115, 101, 99, 116, 105, 111, 110, 95, 116, \n97, 98, 108, 101, 0, 99, 97, 109, 108, 95, 103, 114, \n101, 97, 116, 101, 114, 101, 113, 117, 97, 108, 0, 99, \n97, 109, 108, 95, 103, 114, 101, 97, 116, 101, 114, 116, \n104, 97, 110, 0, 99, 97, 109, 108, 95, 103, 116, 95, \n102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 104, \n97, 115, 104, 0, 99, 97, 109, 108, 95, 104, 97, 115, \n104, 95, 117, 110, 105, 118, 95, 112, 97, 114, 97, 109, \n0, 99, 97, 109, 108, 95, 104, 121, 112, 111, 116, 95, \n102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 105, \n110, 112, 117, 116, 95, 118, 97, 108, 117, 101, 0, 99, \n97, 109, 108, 95, 105, 110, 112, 117, 116, 95, 118, 97, \n108, 117, 101, 95, 102, 114, 111, 109, 95, 115, 116, 114, \n105, 110, 103, 0, 99, 97, 109, 108, 95, 105, 110, 115, \n116, 97, 108, 108, 95, 115, 105, 103, 110, 97, 108, 95, \n104, 97, 110, 100, 108, 101, 114, 0, 99, 97, 109, 108, \n95, 105, 110, 116, 51, 50, 95, 97, 100, 100, 0, 99, \n97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 97, 110, \n100, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, 50, \n95, 98, 105, 116, 115, 95, 111, 102, 95, 102, 108, 111, \n97, 116, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, \n50, 95, 98, 115, 119, 97, 112, 0, 99, 97, 109, 108, \n95, 105, 110, 116, 51, 50, 95, 99, 111, 109, 112, 97, \n114, 101, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, \n50, 95, 100, 105, 118, 0, 99, 97, 109, 108, 95, 105, \n110, 116, 51, 50, 95, 102, 108, 111, 97, 116, 95, 111, \n102, 95, 98, 105, 116, 115, 0, 99, 97, 109, 108, 95, \n105, 110, 116, 51, 50, 95, 102, 111, 114, 109, 97, 116, \n0, 99, 97, 109, 108, 95, 105, 110, 116, 51, 50, 95, \n109, 111, 100, 0, 99, 97, 109, 108, 95, 105, 110, 116, \n51, 50, 95, 109, 117, 108, 0, 99, 97, 109, 108, 95, \n105, 110, 116, 51, 50, 95, 110, 101, 103, 0, 99, 97, \n109, 108, 95, 105, 110, 116, 51, 50, 95, 111, 102, 95, \n102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 105, \n110, 116, 51, 50, 95, 111, 102, 95, 105, 110, 116, 0, \n99, 97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 111, \n102, 95, 115, 116, 114, 105, 110, 103, 0, 99, 97, 109, \n108, 95, 105, 110, 116, 51, 50, 95, 111, 114, 0, 99, \n97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 115, 104, \n105, 102, 116, 95, 108, 101, 102, 116, 0, 99, 97, 109, \n108, 95, 105, 110, 116, 51, 50, 95, 115, 104, 105, 102, \n116, 95, 114, 105, 103, 104, 116, 0, 99, 97, 109, 108, \n95, 105, 110, 116, 51, 50, 95, 115, 104, 105, 102, 116, \n95, 114, 105, 103, 104, 116, 95, 117, 110, 115, 105, 103, \n110, 101, 100, 0, 99, 97, 109, 108, 95, 105, 110, 116, \n51, 50, 95, 115, 117, 98, 0, 99, 97, 109, 108, 95, \n105, 110, 116, 51, 50, 95, 116, 111, 95, 102, 108, 111, \n97, 116, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, \n50, 95, 116, 111, 95, 105, 110, 116, 0, 99, 97, 109, \n108, 95, 105, 110, 116, 51, 50, 95, 120, 111, 114, 0, \n99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 97, \n100, 100, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, \n52, 95, 97, 110, 100, 0, 99, 97, 109, 108, 95, 105, \n110, 116, 54, 52, 95, 98, 105, 116, 115, 95, 111, 102, \n95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, \n105, 110, 116, 54, 52, 95, 98, 115, 119, 97, 112, 0, \n99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 99, \n111, 109, 112, 97, 114, 101, 0, 99, 97, 109, 108, 95, \n105, 110, 116, 54, 52, 95, 100, 105, 118, 0, 99, 97, \n109, 108, 95, 105, 110, 116, 54, 52, 95, 102, 108, 111, \n97, 116, 95, 111, 102, 95, 98, 105, 116, 115, 0, 99, \n97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 102, 111, \n114, 109, 97, 116, 0, 99, 97, 109, 108, 95, 105, 110, \n116, 54, 52, 95, 109, 111, 100, 0, 99, 97, 109, 108, \n95, 105, 110, 116, 54, 52, 95, 109, 117, 108, 0, 99, \n97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 110, 101, \n103, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, \n95, 111, 102, 95, 102, 108, 111, 97, 116, 0, 99, 97, \n109, 108, 95, 105, 110, 116, 54, 52, 95, 111, 102, 95, \n105, 110, 116, 0, 99, 97, 109, 108, 95, 105, 110, 116, \n54, 52, 95, 111, 102, 95, 105, 110, 116, 51, 50, 0, \n99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 111, \n102, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 0, \n99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 111, \n102, 95, 115, 116, 114, 105, 110, 103, 0, 99, 97, 109, \n108, 95, 105, 110, 116, 54, 52, 95, 111, 114, 0, 99, \n97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 115, 104, \n105, 102, 116, 95, 108, 101, 102, 116, 0, 99, 97, 109, \n108, 95, 105, 110, 116, 54, 52, 95, 115, 104, 105, 102, \n116, 95, 114, 105, 103, 104, 116, 0, 99, 97, 109, 108, \n95, 105, 110, 116, 54, 52, 95, 115, 104, 105, 102, 116, \n95, 114, 105, 103, 104, 116, 95, 117, 110, 115, 105, 103, \n110, 101, 100, 0, 99, 97, 109, 108, 95, 105, 110, 116, \n54, 52, 95, 115, 117, 98, 0, 99, 97, 109, 108, 95, \n105, 110, 116, 54, 52, 95, 116, 111, 95, 102, 108, 111, \n97, 116, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, \n52, 95, 116, 111, 95, 105, 110, 116, 0, 99, 97, 109, \n108, 95, 105, 110, 116, 54, 52, 95, 116, 111, 95, 105, \n110, 116, 51, 50, 0, 99, 97, 109, 108, 95, 105, 110, \n116, 54, 52, 95, 116, 111, 95, 110, 97, 116, 105, 118, \n101, 105, 110, 116, 0, 99, 97, 109, 108, 95, 105, 110, \n116, 54, 52, 95, 120, 111, 114, 0, 99, 97, 109, 108, \n95, 105, 110, 116, 95, 99, 111, 109, 112, 97, 114, 101, \n0, 99, 97, 109, 108, 95, 105, 110, 116, 95, 111, 102, \n95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, \n105, 110, 116, 95, 111, 102, 95, 115, 116, 114, 105, 110, \n103, 0, 99, 97, 109, 108, 95, 105, 110, 118, 111, 107, \n101, 95, 116, 114, 97, 99, 101, 100, 95, 102, 117, 110, \n99, 116, 105, 111, 110, 0, 99, 97, 109, 108, 95, 105, \n115, 95, 112, 114, 105, 110, 116, 97, 98, 108, 101, 0, \n99, 97, 109, 108, 95, 108, 97, 122, 121, 95, 102, 111, \n108, 108, 111, 119, 95, 102, 111, 114, 119, 97, 114, 100, \n0, 99, 97, 109, 108, 95, 108, 97, 122, 121, 95, 109, \n97, 107, 101, 95, 102, 111, 114, 119, 97, 114, 100, 0, \n99, 97, 109, 108, 95, 108, 100, 101, 120, 112, 95, 102, \n108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 108, 101, \n95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, \n108, 101, 115, 115, 101, 113, 117, 97, 108, 0, 99, 97, \n109, 108, 95, 108, 101, 115, 115, 116, 104, 97, 110, 0, \n99, 97, 109, 108, 95, 108, 101, 120, 95, 101, 110, 103, \n105, 110, 101, 0, 99, 97, 109, 108, 95, 108, 111, 103, \n49, 48, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, \n108, 95, 108, 111, 103, 49, 112, 95, 102, 108, 111, 97, \n116, 0, 99, 97, 109, 108, 95, 108, 111, 103, 95, 102, \n108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 108, 116, \n95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, \n109, 97, 107, 101, 95, 97, 114, 114, 97, 121, 0, 99, \n97, 109, 108, 95, 109, 97, 107, 101, 95, 118, 101, 99, \n116, 0, 99, 97, 109, 108, 95, 109, 97, 114, 115, 104, \n97, 108, 95, 100, 97, 116, 97, 95, 115, 105, 122, 101, \n0, 99, 97, 109, 108, 95, 109, 100, 53, 95, 99, 104, \n97, 110, 0, 99, 97, 109, 108, 95, 109, 100, 53, 95, \n115, 116, 114, 105, 110, 103, 0, 99, 97, 109, 108, 95, \n109, 108, 95, 99, 104, 97, 110, 110, 101, 108, 95, 115, \n105, 122, 101, 0, 99, 97, 109, 108, 95, 109, 108, 95, \n99, 104, 97, 110, 110, 101, 108, 95, 115, 105, 122, 101, \n95, 54, 52, 0, 99, 97, 109, 108, 95, 109, 108, 95, \n99, 108, 111, 115, 101, 95, 99, 104, 97, 110, 110, 101, \n108, 0, 99, 97, 109, 108, 95, 109, 108, 95, 102, 108, \n117, 115, 104, 0, 99, 97, 109, 108, 95, 109, 108, 95, \n102, 108, 117, 115, 104, 95, 112, 97, 114, 116, 105, 97, \n108, 0, 99, 97, 109, 108, 95, 109, 108, 95, 105, 110, \n112, 117, 116, 0, 99, 97, 109, 108, 95, 109, 108, 95, \n105, 110, 112, 117, 116, 95, 99, 104, 97, 114, 0, 99, \n97, 109, 108, 95, 109, 108, 95, 105, 110, 112, 117, 116, \n95, 105, 110, 116, 0, 99, 97, 109, 108, 95, 109, 108, \n95, 105, 110, 112, 117, 116, 95, 115, 99, 97, 110, 95, \n108, 105, 110, 101, 0, 99, 97, 109, 108, 95, 109, 108, \n95, 111, 112, 101, 110, 95, 100, 101, 115, 99, 114, 105, \n112, 116, 111, 114, 95, 105, 110, 0, 99, 97, 109, 108, \n95, 109, 108, 95, 111, 112, 101, 110, 95, 100, 101, 115, \n99, 114, 105, 112, 116, 111, 114, 95, 111, 117, 116, 0, \n99, 97, 109, 108, 95, 109, 108, 95, 111, 117, 116, 95, \n99, 104, 97, 110, 110, 101, 108, 115, 95, 108, 105, 115, \n116, 0, 99, 97, 109, 108, 95, 109, 108, 95, 111, 117, \n116, 112, 117, 116, 0, 99, 97, 109, 108, 95, 109, 108, \n95, 111, 117, 116, 112, 117, 116, 95, 99, 104, 97, 114, \n0, 99, 97, 109, 108, 95, 109, 108, 95, 111, 117, 116, \n112, 117, 116, 95, 105, 110, 116, 0, 99, 97, 109, 108, \n95, 109, 108, 95, 111, 117, 116, 112, 117, 116, 95, 112, \n97, 114, 116, 105, 97, 108, 0, 99, 97, 109, 108, 95, \n109, 108, 95, 112, 111, 115, 95, 105, 110, 0, 99, 97, \n109, 108, 95, 109, 108, 95, 112, 111, 115, 95, 105, 110, \n95, 54, 52, 0, 99, 97, 109, 108, 95, 109, 108, 95, \n112, 111, 115, 95, 111, 117, 116, 0, 99, 97, 109, 108, \n95, 109, 108, 95, 112, 111, 115, 95, 111, 117, 116, 95, \n54, 52, 0, 99, 97, 109, 108, 95, 109, 108, 95, 115, \n101, 101, 107, 95, 105, 110, 0, 99, 97, 109, 108, 95, \n109, 108, 95, 115, 101, 101, 107, 95, 105, 110, 95, 54, \n52, 0, 99, 97, 109, 108, 95, 109, 108, 95, 115, 101, \n101, 107, 95, 111, 117, 116, 0, 99, 97, 109, 108, 95, \n109, 108, 95, 115, 101, 101, 107, 95, 111, 117, 116, 95, \n54, 52, 0, 99, 97, 109, 108, 95, 109, 108, 95, 115, \n101, 116, 95, 98, 105, 110, 97, 114, 121, 95, 109, 111, \n100, 101, 0, 99, 97, 109, 108, 95, 109, 108, 95, 115, \n116, 114, 105, 110, 103, 95, 108, 101, 110, 103, 116, 104, \n0, 99, 97, 109, 108, 95, 109, 111, 100, 102, 95, 102, \n108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 109, 117, \n108, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, \n95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 97, \n100, 100, 0, 99, 97, 109, 108, 95, 110, 97, 116, 105, \n118, 101, 105, 110, 116, 95, 97, 110, 100, 0, 99, 97, \n109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, \n95, 98, 115, 119, 97, 112, 0, 99, 97, 109, 108, 95, \n110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 99, 111, \n109, 112, 97, 114, 101, 0, 99, 97, 109, 108, 95, 110, \n97, 116, 105, 118, 101, 105, 110, 116, 95, 100, 105, 118, \n0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, \n105, 110, 116, 95, 102, 111, 114, 109, 97, 116, 0, 99, \n97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, \n116, 95, 109, 111, 100, 0, 99, 97, 109, 108, 95, 110, \n97, 116, 105, 118, 101, 105, 110, 116, 95, 109, 117, 108, \n0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, \n105, 110, 116, 95, 110, 101, 103, 0, 99, 97, 109, 108, \n95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 111, \n102, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, \n95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 111, \n102, 95, 105, 110, 116, 0, 99, 97, 109, 108, 95, 110, \n97, 116, 105, 118, 101, 105, 110, 116, 95, 111, 102, 95, \n105, 110, 116, 51, 50, 0, 99, 97, 109, 108, 95, 110, \n97, 116, 105, 118, 101, 105, 110, 116, 95, 111, 102, 95, \n115, 116, 114, 105, 110, 103, 0, 99, 97, 109, 108, 95, \n110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 111, 114, \n0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, \n105, 110, 116, 95, 115, 104, 105, 102, 116, 95, 108, 101, \n102, 116, 0, 99, 97, 109, 108, 95, 110, 97, 116, 105, \n118, 101, 105, 110, 116, 95, 115, 104, 105, 102, 116, 95, \n114, 105, 103, 104, 116, 0, 99, 97, 109, 108, 95, 110, \n97, 116, 105, 118, 101, 105, 110, 116, 95, 115, 104, 105, \n102, 116, 95, 114, 105, 103, 104, 116, 95, 117, 110, 115, \n105, 103, 110, 101, 100, 0, 99, 97, 109, 108, 95, 110, \n97, 116, 105, 118, 101, 105, 110, 116, 95, 115, 117, 98, \n0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, \n105, 110, 116, 95, 116, 111, 95, 102, 108, 111, 97, 116, \n0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, \n105, 110, 116, 95, 116, 111, 95, 105, 110, 116, 0, 99, \n97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, \n116, 95, 116, 111, 95, 105, 110, 116, 51, 50, 0, 99, \n97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, \n116, 95, 120, 111, 114, 0, 99, 97, 109, 108, 95, 110, \n101, 103, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, \n108, 95, 110, 101, 113, 95, 102, 108, 111, 97, 116, 0, \n99, 97, 109, 108, 95, 110, 101, 119, 95, 108, 101, 120, \n95, 101, 110, 103, 105, 110, 101, 0, 99, 97, 109, 108, \n95, 110, 111, 116, 101, 113, 117, 97, 108, 0, 99, 97, \n109, 108, 95, 111, 98, 106, 95, 97, 100, 100, 95, 111, \n102, 102, 115, 101, 116, 0, 99, 97, 109, 108, 95, 111, \n98, 106, 95, 98, 108, 111, 99, 107, 0, 99, 97, 109, \n108, 95, 111, 98, 106, 95, 100, 117, 112, 0, 99, 97, \n109, 108, 95, 111, 98, 106, 95, 105, 115, 95, 98, 108, \n111, 99, 107, 0, 99, 97, 109, 108, 95, 111, 98, 106, \n95, 115, 101, 116, 95, 116, 97, 103, 0, 99, 97, 109, \n108, 95, 111, 98, 106, 95, 116, 97, 103, 0, 99, 97, \n109, 108, 95, 111, 98, 106, 95, 116, 114, 117, 110, 99, \n97, 116, 101, 0, 99, 97, 109, 108, 95, 111, 117, 116, \n112, 117, 116, 95, 118, 97, 108, 117, 101, 0, 99, 97, \n109, 108, 95, 111, 117, 116, 112, 117, 116, 95, 118, 97, \n108, 117, 101, 95, 116, 111, 95, 98, 117, 102, 102, 101, \n114, 0, 99, 97, 109, 108, 95, 111, 117, 116, 112, 117, \n116, 95, 118, 97, 108, 117, 101, 95, 116, 111, 95, 115, \n116, 114, 105, 110, 103, 0, 99, 97, 109, 108, 95, 112, \n97, 114, 115, 101, 95, 101, 110, 103, 105, 110, 101, 0, \n99, 97, 109, 108, 95, 112, 111, 119, 101, 114, 95, 102, \n108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 114, 101, \n97, 108, 108, 111, 99, 95, 103, 108, 111, 98, 97, 108, \n0, 99, 97, 109, 108, 95, 114, 101, 99, 111, 114, 100, \n95, 98, 97, 99, 107, 116, 114, 97, 99, 101, 0, 99, \n97, 109, 108, 95, 114, 101, 103, 105, 115, 116, 101, 114, \n95, 99, 111, 100, 101, 95, 102, 114, 97, 103, 109, 101, \n110, 116, 0, 99, 97, 109, 108, 95, 114, 101, 103, 105, \n115, 116, 101, 114, 95, 110, 97, 109, 101, 100, 95, 118, \n97, 108, 117, 101, 0, 99, 97, 109, 108, 95, 114, 101, \n105, 102, 121, 95, 98, 121, 116, 101, 99, 111, 100, 101, \n0, 99, 97, 109, 108, 95, 115, 101, 116, 95, 112, 97, \n114, 115, 101, 114, 95, 116, 114, 97, 99, 101, 0, 99, \n97, 109, 108, 95, 115, 105, 110, 95, 102, 108, 111, 97, \n116, 0, 99, 97, 109, 108, 95, 115, 105, 110, 104, 95, \n102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 115, \n113, 114, 116, 95, 102, 108, 111, 97, 116, 0, 99, 97, \n109, 108, 95, 115, 116, 97, 116, 105, 99, 95, 97, 108, \n108, 111, 99, 0, 99, 97, 109, 108, 95, 115, 116, 97, \n116, 105, 99, 95, 102, 114, 101, 101, 0, 99, 97, 109, \n108, 95, 115, 116, 97, 116, 105, 99, 95, 114, 101, 108, \n101, 97, 115, 101, 95, 98, 121, 116, 101, 99, 111, 100, \n101, 0, 99, 97, 109, 108, 95, 115, 116, 97, 116, 105, \n99, 95, 114, 101, 115, 105, 122, 101, 0, 99, 97, 109, \n108, 95, 115, 116, 114, 105, 110, 103, 95, 99, 111, 109, \n112, 97, 114, 101, 0, 99, 97, 109, 108, 95, 115, 116, \n114, 105, 110, 103, 95, 101, 113, 117, 97, 108, 0, 99, \n97, 109, 108, 95, 115, 116, 114, 105, 110, 103, 95, 103, \n101, 116, 0, 99, 97, 109, 108, 95, 115, 116, 114, 105, \n110, 103, 95, 103, 101, 116, 49, 54, 0, 99, 97, 109, \n108, 95, 115, 116, 114, 105, 110, 103, 95, 103, 101, 116, \n51, 50, 0, 99, 97, 109, 108, 95, 115, 116, 114, 105, \n110, 103, 95, 103, 101, 116, 54, 52, 0, 99, 97, 109, \n108, 95, 115, 116, 114, 105, 110, 103, 95, 103, 114, 101, \n97, 116, 101, 114, 101, 113, 117, 97, 108, 0, 99, 97, \n109, 108, 95, 115, 116, 114, 105, 110, 103, 95, 103, 114, \n101, 97, 116, 101, 114, 116, 104, 97, 110, 0, 99, 97, \n109, 108, 95, 115, 116, 114, 105, 110, 103, 95, 108, 101, \n115, 115, 101, 113, 117, 97, 108, 0, 99, 97, 109, 108, \n95, 115, 116, 114, 105, 110, 103, 95, 108, 101, 115, 115, \n116, 104, 97, 110, 0, 99, 97, 109, 108, 95, 115, 116, \n114, 105, 110, 103, 95, 110, 111, 116, 101, 113, 117, 97, \n108, 0, 99, 97, 109, 108, 95, 115, 116, 114, 105, 110, \n103, 95, 115, 101, 116, 0, 99, 97, 109, 108, 95, 115, \n116, 114, 105, 110, 103, 95, 115, 101, 116, 49, 54, 0, \n99, 97, 109, 108, 95, 115, 116, 114, 105, 110, 103, 95, \n115, 101, 116, 51, 50, 0, 99, 97, 109, 108, 95, 115, \n116, 114, 105, 110, 103, 95, 115, 101, 116, 54, 52, 0, \n99, 97, 109, 108, 95, 115, 117, 98, 95, 102, 108, 111, \n97, 116, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, \n99, 104, 100, 105, 114, 0, 99, 97, 109, 108, 95, 115, \n121, 115, 95, 99, 108, 111, 115, 101, 0, 99, 97, 109, \n108, 95, 115, 121, 115, 95, 99, 111, 110, 115, 116, 95, \n98, 105, 103, 95, 101, 110, 100, 105, 97, 110, 0, 99, \n97, 109, 108, 95, 115, 121, 115, 95, 99, 111, 110, 115, \n116, 95, 111, 115, 116, 121, 112, 101, 95, 99, 121, 103, \n119, 105, 110, 0, 99, 97, 109, 108, 95, 115, 121, 115, \n95, 99, 111, 110, 115, 116, 95, 111, 115, 116, 121, 112, \n101, 95, 117, 110, 105, 120, 0, 99, 97, 109, 108, 95, \n115, 121, 115, 95, 99, 111, 110, 115, 116, 95, 111, 115, \n116, 121, 112, 101, 95, 119, 105, 110, 51, 50, 0, 99, \n97, 109, 108, 95, 115, 121, 115, 95, 99, 111, 110, 115, \n116, 95, 119, 111, 114, 100, 95, 115, 105, 122, 101, 0, \n99, 97, 109, 108, 95, 115, 121, 115, 95, 101, 120, 105, \n116, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 102, \n105, 108, 101, 95, 101, 120, 105, 115, 116, 115, 0, 99, \n97, 109, 108, 95, 115, 121, 115, 95, 103, 101, 116, 95, \n97, 114, 103, 118, 0, 99, 97, 109, 108, 95, 115, 121, \n115, 95, 103, 101, 116, 95, 99, 111, 110, 102, 105, 103, \n0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 103, 101, \n116, 99, 119, 100, 0, 99, 97, 109, 108, 95, 115, 121, \n115, 95, 103, 101, 116, 101, 110, 118, 0, 99, 97, 109, \n108, 95, 115, 121, 115, 95, 105, 115, 95, 100, 105, 114, \n101, 99, 116, 111, 114, 121, 0, 99, 97, 109, 108, 95, \n115, 121, 115, 95, 111, 112, 101, 110, 0, 99, 97, 109, \n108, 95, 115, 121, 115, 95, 114, 97, 110, 100, 111, 109, \n95, 115, 101, 101, 100, 0, 99, 97, 109, 108, 95, 115, \n121, 115, 95, 114, 101, 97, 100, 95, 100, 105, 114, 101, \n99, 116, 111, 114, 121, 0, 99, 97, 109, 108, 95, 115, \n121, 115, 95, 114, 101, 109, 111, 118, 101, 0, 99, 97, \n109, 108, 95, 115, 121, 115, 95, 114, 101, 110, 97, 109, \n101, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 115, \n121, 115, 116, 101, 109, 95, 99, 111, 109, 109, 97, 110, \n100, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 116, \n105, 109, 101, 0, 99, 97, 109, 108, 95, 116, 97, 110, \n95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, \n116, 97, 110, 104, 95, 102, 108, 111, 97, 116, 0, 99, \n97, 109, 108, 95, 116, 101, 114, 109, 105, 110, 102, 111, \n95, 98, 97, 99, 107, 117, 112, 0, 99, 97, 109, 108, \n95, 116, 101, 114, 109, 105, 110, 102, 111, 95, 114, 101, \n115, 117, 109, 101, 0, 99, 97, 109, 108, 95, 116, 101, \n114, 109, 105, 110, 102, 111, 95, 115, 101, 116, 117, 112, \n0, 99, 97, 109, 108, 95, 116, 101, 114, 109, 105, 110, \n102, 111, 95, 115, 116, 97, 110, 100, 111, 117, 116, 0, \n99, 97, 109, 108, 95, 117, 112, 100, 97, 116, 101, 95, \n100, 117, 109, 109, 121, 0, 99, 97, 109, 108, 95, 119, \n101, 97, 107, 95, 98, 108, 105, 116, 0, 99, 97, 109, \n108, 95, 119, 101, 97, 107, 95, 99, 104, 101, 99, 107, \n0, 99, 97, 109, 108, 95, 119, 101, 97, 107, 95, 99, \n114, 101, 97, 116, 101, 0, 99, 97, 109, 108, 95, 119, \n101, 97, 107, 95, 103, 101, 116, 0, 99, 97, 109, 108, \n95, 119, 101, 97, 107, 95, 103, 101, 116, 95, 99, 111, \n112, 121, 0, 99, 97, 109, 108, 95, 119, 101, 97, 107, \n95, 115, 101, 116, 0, 160, 160, 36, 67, 82, 67, 83, \n160, 160, 4, 49, 48, 190, 163, 18, 101, 189, 28, 219, \n213, 174, 68, 31, 211, 31, 177, 196, 145, 160, 160, 4, \n49, 48, 18, 91, 100, 123, 73, 58, 159, 133, 115, 221, \n105, 87, 212, 43, 208, 18, 160, 160, 42, 80, 101, 114, \n118, 97, 115, 105, 118, 101, 115, 48, 54, 181, 188, 130, \n39, 220, 153, 20, 198, 217, 253, 155, 220, 250, 219, 69, \n64, 64, \n};\n\nextern value caml_abs_float();\nextern value caml_acos_float();\nextern value caml_add_float();\nextern value caml_alloc_dummy();\nextern value caml_alloc_dummy_float();\nextern value caml_array_append();\nextern value caml_array_blit();\nextern value caml_array_concat();\nextern value caml_array_get();\nextern value caml_array_get_addr();\nextern value caml_array_get_float();\nextern value caml_array_set();\nextern value caml_array_set_addr();\nextern value caml_array_set_float();\nextern value caml_array_sub();\nextern value caml_array_unsafe_get();\nextern value caml_array_unsafe_get_float();\nextern value caml_array_unsafe_set();\nextern value caml_array_unsafe_set_addr();\nextern value caml_array_unsafe_set_float();\nextern value caml_asin_float();\nextern value caml_atan2_float();\nextern value caml_atan_float();\nextern value caml_backtrace_status();\nextern value caml_bitvect_test();\nextern value caml_blit_string();\nextern value caml_bswap16();\nextern value caml_ceil_float();\nextern value caml_channel_descriptor();\nextern value caml_classify_float();\nextern value caml_compare();\nextern value caml_convert_raw_backtrace();\nextern value caml_copysign_float();\nextern value caml_cos_float();\nextern value caml_cosh_float();\nextern value caml_create_string();\nextern value caml_div_float();\nextern value caml_dynlink_add_primitive();\nextern value caml_dynlink_close_lib();\nextern value caml_dynlink_get_current_libs();\nextern value caml_dynlink_lookup_symbol();\nextern value caml_dynlink_open_lib();\nextern value caml_ensure_stack_capacity();\nextern value caml_eq_float();\nextern value caml_equal();\nextern value caml_exp_float();\nextern value caml_expm1_float();\nextern value caml_fill_string();\nextern value caml_final_register();\nextern value caml_final_release();\nextern value caml_float_compare();\nextern value caml_float_of_int();\nextern value caml_float_of_string();\nextern value caml_floor_float();\nextern value caml_fmod_float();\nextern value caml_format_float();\nextern value caml_format_int();\nextern value caml_frexp_float();\nextern value caml_gc_compaction();\nextern value caml_gc_counters();\nextern value caml_gc_full_major();\nextern value caml_gc_get();\nextern value caml_gc_major();\nextern value caml_gc_major_slice();\nextern value caml_gc_minor();\nextern value caml_gc_quick_stat();\nextern value caml_gc_set();\nextern value caml_gc_stat();\nextern value caml_ge_float();\nextern value caml_get_current_callstack();\nextern value caml_get_current_environment();\nextern value caml_get_exception_backtrace();\nextern value caml_get_exception_raw_backtrace();\nextern value caml_get_global_data();\nextern value caml_get_public_method();\nextern value caml_get_section_table();\nextern value caml_greaterequal();\nextern value caml_greaterthan();\nextern value caml_gt_float();\nextern value caml_hash();\nextern value caml_hash_univ_param();\nextern value caml_hypot_float();\nextern value caml_input_value();\nextern value caml_input_value_from_string();\nextern value caml_install_signal_handler();\nextern value caml_int32_add();\nextern value caml_int32_and();\nextern value caml_int32_bits_of_float();\nextern value caml_int32_bswap();\nextern value caml_int32_compare();\nextern value caml_int32_div();\nextern value caml_int32_float_of_bits();\nextern value caml_int32_format();\nextern value caml_int32_mod();\nextern value caml_int32_mul();\nextern value caml_int32_neg();\nextern value caml_int32_of_float();\nextern value caml_int32_of_int();\nextern value caml_int32_of_string();\nextern value caml_int32_or();\nextern value caml_int32_shift_left();\nextern value caml_int32_shift_right();\nextern value caml_int32_shift_right_unsigned();\nextern value caml_int32_sub();\nextern value caml_int32_to_float();\nextern value caml_int32_to_int();\nextern value caml_int32_xor();\nextern value caml_int64_add();\nextern value caml_int64_and();\nextern value caml_int64_bits_of_float();\nextern value caml_int64_bswap();\nextern value caml_int64_compare();\nextern value caml_int64_div();\nextern value caml_int64_float_of_bits();\nextern value caml_int64_format();\nextern value caml_int64_mod();\nextern value caml_int64_mul();\nextern value caml_int64_neg();\nextern value caml_int64_of_float();\nextern value caml_int64_of_int();\nextern value caml_int64_of_int32();\nextern value caml_int64_of_nativeint();\nextern value caml_int64_of_string();\nextern value caml_int64_or();\nextern value caml_int64_shift_left();\nextern value caml_int64_shift_right();\nextern value caml_int64_shift_right_unsigned();\nextern value caml_int64_sub();\nextern value caml_int64_to_float();\nextern value caml_int64_to_int();\nextern value caml_int64_to_int32();\nextern value caml_int64_to_nativeint();\nextern value caml_int64_xor();\nextern value caml_int_compare();\nextern value caml_int_of_float();\nextern value caml_int_of_string();\nextern value caml_invoke_traced_function();\nextern value caml_is_printable();\nextern value caml_lazy_follow_forward();\nextern value caml_lazy_make_forward();\nextern value caml_ldexp_float();\nextern value caml_le_float();\nextern value caml_lessequal();\nextern value caml_lessthan();\nextern value caml_lex_engine();\nextern value caml_log10_float();\nextern value caml_log1p_float();\nextern value caml_log_float();\nextern value caml_lt_float();\nextern value caml_make_array();\nextern value caml_make_vect();\nextern value caml_marshal_data_size();\nextern value caml_md5_chan();\nextern value caml_md5_string();\nextern value caml_ml_channel_size();\nextern value caml_ml_channel_size_64();\nextern value caml_ml_close_channel();\nextern value caml_ml_flush();\nextern value caml_ml_flush_partial();\nextern value caml_ml_input();\nextern value caml_ml_input_char();\nextern value caml_ml_input_int();\nextern value caml_ml_input_scan_line();\nextern value caml_ml_open_descriptor_in();\nextern value caml_ml_open_descriptor_out();\nextern value caml_ml_out_channels_list();\nextern value caml_ml_output();\nextern value caml_ml_output_char();\nextern value caml_ml_output_int();\nextern value caml_ml_output_partial();\nextern value caml_ml_pos_in();\nextern value caml_ml_pos_in_64();\nextern value caml_ml_pos_out();\nextern value caml_ml_pos_out_64();\nextern value caml_ml_seek_in();\nextern value caml_ml_seek_in_64();\nextern value caml_ml_seek_out();\nextern value caml_ml_seek_out_64();\nextern value caml_ml_set_binary_mode();\nextern value caml_ml_string_length();\nextern value caml_modf_float();\nextern value caml_mul_float();\nextern value caml_nativeint_add();\nextern value caml_nativeint_and();\nextern value caml_nativeint_bswap();\nextern value caml_nativeint_compare();\nextern value caml_nativeint_div();\nextern value caml_nativeint_format();\nextern value caml_nativeint_mod();\nextern value caml_nativeint_mul();\nextern value caml_nativeint_neg();\nextern value caml_nativeint_of_float();\nextern value caml_nativeint_of_int();\nextern value caml_nativeint_of_int32();\nextern value caml_nativeint_of_string();\nextern value caml_nativeint_or();\nextern value caml_nativeint_shift_left();\nextern value caml_nativeint_shift_right();\nextern value caml_nativeint_shift_right_unsigned();\nextern value caml_nativeint_sub();\nextern value caml_nativeint_to_float();\nextern value caml_nativeint_to_int();\nextern value caml_nativeint_to_int32();\nextern value caml_nativeint_xor();\nextern value caml_neg_float();\nextern value caml_neq_float();\nextern value caml_new_lex_engine();\nextern value caml_notequal();\nextern value caml_obj_add_offset();\nextern value caml_obj_block();\nextern value caml_obj_dup();\nextern value caml_obj_is_block();\nextern value caml_obj_set_tag();\nextern value caml_obj_tag();\nextern value caml_obj_truncate();\nextern value caml_output_value();\nextern value caml_output_value_to_buffer();\nextern value caml_output_value_to_string();\nextern value caml_parse_engine();\nextern value caml_power_float();\nextern value caml_realloc_global();\nextern value caml_record_backtrace();\nextern value caml_register_code_fragment();\nextern value caml_register_named_value();\nextern value caml_reify_bytecode();\nextern value caml_set_parser_trace();\nextern value caml_sin_float();\nextern value caml_sinh_float();\nextern value caml_sqrt_float();\nextern value caml_static_alloc();\nextern value caml_static_free();\nextern value caml_static_release_bytecode();\nextern value caml_static_resize();\nextern value caml_string_compare();\nextern value caml_string_equal();\nextern value caml_string_get();\nextern value caml_string_get16();\nextern value caml_string_get32();\nextern value caml_string_get64();\nextern value caml_string_greaterequal();\nextern value caml_string_greaterthan();\nextern value caml_string_lessequal();\nextern value caml_string_lessthan();\nextern value caml_string_notequal();\nextern value caml_string_set();\nextern value caml_string_set16();\nextern value caml_string_set32();\nextern value caml_string_set64();\nextern value caml_sub_float();\nextern value caml_sys_chdir();\nextern value caml_sys_close();\nextern value caml_sys_const_big_endian();\nextern value caml_sys_const_ostype_cygwin();\nextern value caml_sys_const_ostype_unix();\nextern value caml_sys_const_ostype_win32();\nextern value caml_sys_const_word_size();\nextern value caml_sys_exit();\nextern value caml_sys_file_exists();\nextern value caml_sys_get_argv();\nextern value caml_sys_get_config();\nextern value caml_sys_getcwd();\nextern value caml_sys_getenv();\nextern value caml_sys_is_directory();\nextern value caml_sys_open();\nextern value caml_sys_random_seed();\nextern value caml_sys_read_directory();\nextern value caml_sys_remove();\nextern value caml_sys_rename();\nextern value caml_sys_system_command();\nextern value caml_sys_time();\nextern value caml_tan_float();\nextern value caml_tanh_float();\nextern value caml_terminfo_backup();\nextern value caml_terminfo_resume();\nextern value caml_terminfo_setup();\nextern value caml_terminfo_standout();\nextern value caml_update_dummy();\nextern value caml_weak_blit();\nextern value caml_weak_check();\nextern value caml_weak_create();\nextern value caml_weak_get();\nextern value caml_weak_get_copy();\nextern value caml_weak_set();\ntypedef value (*primitive)();\nprimitive caml_builtin_cprim[] = {\n  caml_abs_float,\n  caml_acos_float,\n  caml_add_float,\n  caml_alloc_dummy,\n  caml_alloc_dummy_float,\n  caml_array_append,\n  caml_array_blit,\n  caml_array_concat,\n  caml_array_get,\n  caml_array_get_addr,\n  caml_array_get_float,\n  caml_array_set,\n  caml_array_set_addr,\n  caml_array_set_float,\n  caml_array_sub,\n  caml_array_unsafe_get,\n  caml_array_unsafe_get_float,\n  caml_array_unsafe_set,\n  caml_array_unsafe_set_addr,\n  caml_array_unsafe_set_float,\n  caml_asin_float,\n  caml_atan2_float,\n  caml_atan_float,\n  caml_backtrace_status,\n  caml_bitvect_test,\n  caml_blit_string,\n  caml_bswap16,\n  caml_ceil_float,\n  caml_channel_descriptor,\n  caml_classify_float,\n  caml_compare,\n  caml_convert_raw_backtrace,\n  caml_copysign_float,\n  caml_cos_float,\n  caml_cosh_float,\n  caml_create_string,\n  caml_div_float,\n  caml_dynlink_add_primitive,\n  caml_dynlink_close_lib,\n  caml_dynlink_get_current_libs,\n  caml_dynlink_lookup_symbol,\n  caml_dynlink_open_lib,\n  caml_ensure_stack_capacity,\n  caml_eq_float,\n  caml_equal,\n  caml_exp_float,\n  caml_expm1_float,\n  caml_fill_string,\n  caml_final_register,\n  caml_final_release,\n  caml_float_compare,\n  caml_float_of_int,\n  caml_float_of_string,\n  caml_floor_float,\n  caml_fmod_float,\n  caml_format_float,\n  caml_format_int,\n  caml_frexp_float,\n  caml_gc_compaction,\n  caml_gc_counters,\n  caml_gc_full_major,\n  caml_gc_get,\n  caml_gc_major,\n  caml_gc_major_slice,\n  caml_gc_minor,\n  caml_gc_quick_stat,\n  caml_gc_set,\n  caml_gc_stat,\n  caml_ge_float,\n  caml_get_current_callstack,\n  caml_get_current_environment,\n  caml_get_exception_backtrace,\n  caml_get_exception_raw_backtrace,\n  caml_get_global_data,\n  caml_get_public_method,\n  caml_get_section_table,\n  caml_greaterequal,\n  caml_greaterthan,\n  caml_gt_float,\n  caml_hash,\n  caml_hash_univ_param,\n  caml_hypot_float,\n  caml_input_value,\n  caml_input_value_from_string,\n  caml_install_signal_handler,\n  caml_int32_add,\n  caml_int32_and,\n  caml_int32_bits_of_float,\n  caml_int32_bswap,\n  caml_int32_compare,\n  caml_int32_div,\n  caml_int32_float_of_bits,\n  caml_int32_format,\n  caml_int32_mod,\n  caml_int32_mul,\n  caml_int32_neg,\n  caml_int32_of_float,\n  caml_int32_of_int,\n  caml_int32_of_string,\n  caml_int32_or,\n  caml_int32_shift_left,\n  caml_int32_shift_right,\n  caml_int32_shift_right_unsigned,\n  caml_int32_sub,\n  caml_int32_to_float,\n  caml_int32_to_int,\n  caml_int32_xor,\n  caml_int64_add,\n  caml_int64_and,\n  caml_int64_bits_of_float,\n  caml_int64_bswap,\n  caml_int64_compare,\n  caml_int64_div,\n  caml_int64_float_of_bits,\n  caml_int64_format,\n  caml_int64_mod,\n  caml_int64_mul,\n  caml_int64_neg,\n  caml_int64_of_float,\n  caml_int64_of_int,\n  caml_int64_of_int32,\n  caml_int64_of_nativeint,\n  caml_int64_of_string,\n  caml_int64_or,\n  caml_int64_shift_left,\n  caml_int64_shift_right,\n  caml_int64_shift_right_unsigned,\n  caml_int64_sub,\n  caml_int64_to_float,\n  caml_int64_to_int,\n  caml_int64_to_int32,\n  caml_int64_to_nativeint,\n  caml_int64_xor,\n  caml_int_compare,\n  caml_int_of_float,\n  caml_int_of_string,\n  caml_invoke_traced_function,\n  caml_is_printable,\n  caml_lazy_follow_forward,\n  caml_lazy_make_forward,\n  caml_ldexp_float,\n  caml_le_float,\n  caml_lessequal,\n  caml_lessthan,\n  caml_lex_engine,\n  caml_log10_float,\n  caml_log1p_float,\n  caml_log_float,\n  caml_lt_float,\n  caml_make_array,\n  caml_make_vect,\n  caml_marshal_data_size,\n  caml_md5_chan,\n  caml_md5_string,\n  caml_ml_channel_size,\n  caml_ml_channel_size_64,\n  caml_ml_close_channel,\n  caml_ml_flush,\n  caml_ml_flush_partial,\n  caml_ml_input,\n  caml_ml_input_char,\n  caml_ml_input_int,\n  caml_ml_input_scan_line,\n  caml_ml_open_descriptor_in,\n  caml_ml_open_descriptor_out,\n  caml_ml_out_channels_list,\n  caml_ml_output,\n  caml_ml_output_char,\n  caml_ml_output_int,\n  caml_ml_output_partial,\n  caml_ml_pos_in,\n  caml_ml_pos_in_64,\n  caml_ml_pos_out,\n  caml_ml_pos_out_64,\n  caml_ml_seek_in,\n  caml_ml_seek_in_64,\n  caml_ml_seek_out,\n  caml_ml_seek_out_64,\n  caml_ml_set_binary_mode,\n  caml_ml_string_length,\n  caml_modf_float,\n  caml_mul_float,\n  caml_nativeint_add,\n  caml_nativeint_and,\n  caml_nativeint_bswap,\n  caml_nativeint_compare,\n  caml_nativeint_div,\n  caml_nativeint_format,\n  caml_nativeint_mod,\n  caml_nativeint_mul,\n  caml_nativeint_neg,\n  caml_nativeint_of_float,\n  caml_nativeint_of_int,\n  caml_nativeint_of_int32,\n  caml_nativeint_of_string,\n  caml_nativeint_or,\n  caml_nativeint_shift_left,\n  caml_nativeint_shift_right,\n  caml_nativeint_shift_right_unsigned,\n  caml_nativeint_sub,\n  caml_nativeint_to_float,\n  caml_nativeint_to_int,\n  caml_nativeint_to_int32,\n  caml_nativeint_xor,\n  caml_neg_float,\n  caml_neq_float,\n  caml_new_lex_engine,\n  caml_notequal,\n  caml_obj_add_offset,\n  caml_obj_block,\n  caml_obj_dup,\n  caml_obj_is_block,\n  caml_obj_set_tag,\n  caml_obj_tag,\n  caml_obj_truncate,\n  caml_output_value,\n  caml_output_value_to_buffer,\n  caml_output_value_to_string,\n  caml_parse_engine,\n  caml_power_float,\n  caml_realloc_global,\n  caml_record_backtrace,\n  caml_register_code_fragment,\n  caml_register_named_value,\n  caml_reify_bytecode,\n  caml_set_parser_trace,\n  caml_sin_float,\n  caml_sinh_float,\n  caml_sqrt_float,\n  caml_static_alloc,\n  caml_static_free,\n  caml_static_release_bytecode,\n  caml_static_resize,\n  caml_string_compare,\n  caml_string_equal,\n  caml_string_get,\n  caml_string_get16,\n  caml_string_get32,\n  caml_string_get64,\n  caml_string_greaterequal,\n  caml_string_greaterthan,\n  caml_string_lessequal,\n  caml_string_lessthan,\n  caml_string_notequal,\n  caml_string_set,\n  caml_string_set16,\n  caml_string_set32,\n  caml_string_set64,\n  caml_sub_float,\n  caml_sys_chdir,\n  caml_sys_close,\n  caml_sys_const_big_endian,\n  caml_sys_const_ostype_cygwin,\n  caml_sys_const_ostype_unix,\n  caml_sys_const_ostype_win32,\n  caml_sys_const_word_size,\n  caml_sys_exit,\n  caml_sys_file_exists,\n  caml_sys_get_argv,\n  caml_sys_get_config,\n  caml_sys_getcwd,\n  caml_sys_getenv,\n  caml_sys_is_directory,\n  caml_sys_open,\n  caml_sys_random_seed,\n  caml_sys_read_directory,\n  caml_sys_remove,\n  caml_sys_rename,\n  caml_sys_system_command,\n  caml_sys_time,\n  caml_tan_float,\n  caml_tanh_float,\n  caml_terminfo_backup,\n  caml_terminfo_resume,\n  caml_terminfo_setup,\n  caml_terminfo_standout,\n  caml_update_dummy,\n  caml_weak_blit,\n  caml_weak_check,\n  caml_weak_create,\n  caml_weak_get,\n  caml_weak_get_copy,\n  caml_weak_set,\n  (primitive) 0 };\nconst char * caml_names_of_builtin_cprim[] = {\n  \"caml_abs_float\",\n  \"caml_acos_float\",\n  \"caml_add_float\",\n  \"caml_alloc_dummy\",\n  \"caml_alloc_dummy_float\",\n  \"caml_array_append\",\n  \"caml_array_blit\",\n  \"caml_array_concat\",\n  \"caml_array_get\",\n  \"caml_array_get_addr\",\n  \"caml_array_get_float\",\n  \"caml_array_set\",\n  \"caml_array_set_addr\",\n  \"caml_array_set_float\",\n  \"caml_array_sub\",\n  \"caml_array_unsafe_get\",\n  \"caml_array_unsafe_get_float\",\n  \"caml_array_unsafe_set\",\n  \"caml_array_unsafe_set_addr\",\n  \"caml_array_unsafe_set_float\",\n  \"caml_asin_float\",\n  \"caml_atan2_float\",\n  \"caml_atan_float\",\n  \"caml_backtrace_status\",\n  \"caml_bitvect_test\",\n  \"caml_blit_string\",\n  \"caml_bswap16\",\n  \"caml_ceil_float\",\n  \"caml_channel_descriptor\",\n  \"caml_classify_float\",\n  \"caml_compare\",\n  \"caml_convert_raw_backtrace\",\n  \"caml_copysign_float\",\n  \"caml_cos_float\",\n  \"caml_cosh_float\",\n  \"caml_create_string\",\n  \"caml_div_float\",\n  \"caml_dynlink_add_primitive\",\n  \"caml_dynlink_close_lib\",\n  \"caml_dynlink_get_current_libs\",\n  \"caml_dynlink_lookup_symbol\",\n  \"caml_dynlink_open_lib\",\n  \"caml_ensure_stack_capacity\",\n  \"caml_eq_float\",\n  \"caml_equal\",\n  \"caml_exp_float\",\n  \"caml_expm1_float\",\n  \"caml_fill_string\",\n  \"caml_final_register\",\n  \"caml_final_release\",\n  \"caml_float_compare\",\n  \"caml_float_of_int\",\n  \"caml_float_of_string\",\n  \"caml_floor_float\",\n  \"caml_fmod_float\",\n  \"caml_format_float\",\n  \"caml_format_int\",\n  \"caml_frexp_float\",\n  \"caml_gc_compaction\",\n  \"caml_gc_counters\",\n  \"caml_gc_full_major\",\n  \"caml_gc_get\",\n  \"caml_gc_major\",\n  \"caml_gc_major_slice\",\n  \"caml_gc_minor\",\n  \"caml_gc_quick_stat\",\n  \"caml_gc_set\",\n  \"caml_gc_stat\",\n  \"caml_ge_float\",\n  \"caml_get_current_callstack\",\n  \"caml_get_current_environment\",\n  \"caml_get_exception_backtrace\",\n  \"caml_get_exception_raw_backtrace\",\n  \"caml_get_global_data\",\n  \"caml_get_public_method\",\n  \"caml_get_section_table\",\n  \"caml_greaterequal\",\n  \"caml_greaterthan\",\n  \"caml_gt_float\",\n  \"caml_hash\",\n  \"caml_hash_univ_param\",\n  \"caml_hypot_float\",\n  \"caml_input_value\",\n  \"caml_input_value_from_string\",\n  \"caml_install_signal_handler\",\n  \"caml_int32_add\",\n  \"caml_int32_and\",\n  \"caml_int32_bits_of_float\",\n  \"caml_int32_bswap\",\n  \"caml_int32_compare\",\n  \"caml_int32_div\",\n  \"caml_int32_float_of_bits\",\n  \"caml_int32_format\",\n  \"caml_int32_mod\",\n  \"caml_int32_mul\",\n  \"caml_int32_neg\",\n  \"caml_int32_of_float\",\n  \"caml_int32_of_int\",\n  \"caml_int32_of_string\",\n  \"caml_int32_or\",\n  \"caml_int32_shift_left\",\n  \"caml_int32_shift_right\",\n  \"caml_int32_shift_right_unsigned\",\n  \"caml_int32_sub\",\n  \"caml_int32_to_float\",\n  \"caml_int32_to_int\",\n  \"caml_int32_xor\",\n  \"caml_int64_add\",\n  \"caml_int64_and\",\n  \"caml_int64_bits_of_float\",\n  \"caml_int64_bswap\",\n  \"caml_int64_compare\",\n  \"caml_int64_div\",\n  \"caml_int64_float_of_bits\",\n  \"caml_int64_format\",\n  \"caml_int64_mod\",\n  \"caml_int64_mul\",\n  \"caml_int64_neg\",\n  \"caml_int64_of_float\",\n  \"caml_int64_of_int\",\n  \"caml_int64_of_int32\",\n  \"caml_int64_of_nativeint\",\n  \"caml_int64_of_string\",\n  \"caml_int64_or\",\n  \"caml_int64_shift_left\",\n  \"caml_int64_shift_right\",\n  \"caml_int64_shift_right_unsigned\",\n  \"caml_int64_sub\",\n  \"caml_int64_to_float\",\n  \"caml_int64_to_int\",\n  \"caml_int64_to_int32\",\n  \"caml_int64_to_nativeint\",\n  \"caml_int64_xor\",\n  \"caml_int_compare\",\n  \"caml_int_of_float\",\n  \"caml_int_of_string\",\n  \"caml_invoke_traced_function\",\n  \"caml_is_printable\",\n  \"caml_lazy_follow_forward\",\n  \"caml_lazy_make_forward\",\n  \"caml_ldexp_float\",\n  \"caml_le_float\",\n  \"caml_lessequal\",\n  \"caml_lessthan\",\n  \"caml_lex_engine\",\n  \"caml_log10_float\",\n  \"caml_log1p_float\",\n  \"caml_log_float\",\n  \"caml_lt_float\",\n  \"caml_make_array\",\n  \"caml_make_vect\",\n  \"caml_marshal_data_size\",\n  \"caml_md5_chan\",\n  \"caml_md5_string\",\n  \"caml_ml_channel_size\",\n  \"caml_ml_channel_size_64\",\n  \"caml_ml_close_channel\",\n  \"caml_ml_flush\",\n  \"caml_ml_flush_partial\",\n  \"caml_ml_input\",\n  \"caml_ml_input_char\",\n  \"caml_ml_input_int\",\n  \"caml_ml_input_scan_line\",\n  \"caml_ml_open_descriptor_in\",\n  \"caml_ml_open_descriptor_out\",\n  \"caml_ml_out_channels_list\",\n  \"caml_ml_output\",\n  \"caml_ml_output_char\",\n  \"caml_ml_output_int\",\n  \"caml_ml_output_partial\",\n  \"caml_ml_pos_in\",\n  \"caml_ml_pos_in_64\",\n  \"caml_ml_pos_out\",\n  \"caml_ml_pos_out_64\",\n  \"caml_ml_seek_in\",\n  \"caml_ml_seek_in_64\",\n  \"caml_ml_seek_out\",\n  \"caml_ml_seek_out_64\",\n  \"caml_ml_set_binary_mode\",\n  \"caml_ml_string_length\",\n  \"caml_modf_float\",\n  \"caml_mul_float\",\n  \"caml_nativeint_add\",\n  \"caml_nativeint_and\",\n  \"caml_nativeint_bswap\",\n  \"caml_nativeint_compare\",\n  \"caml_nativeint_div\",\n  \"caml_nativeint_format\",\n  \"caml_nativeint_mod\",\n  \"caml_nativeint_mul\",\n  \"caml_nativeint_neg\",\n  \"caml_nativeint_of_float\",\n  \"caml_nativeint_of_int\",\n  \"caml_nativeint_of_int32\",\n  \"caml_nativeint_of_string\",\n  \"caml_nativeint_or\",\n  \"caml_nativeint_shift_left\",\n  \"caml_nativeint_shift_right\",\n  \"caml_nativeint_shift_right_unsigned\",\n  \"caml_nativeint_sub\",\n  \"caml_nativeint_to_float\",\n  \"caml_nativeint_to_int\",\n  \"caml_nativeint_to_int32\",\n  \"caml_nativeint_xor\",\n  \"caml_neg_float\",\n  \"caml_neq_float\",\n  \"caml_new_lex_engine\",\n  \"caml_notequal\",\n  \"caml_obj_add_offset\",\n  \"caml_obj_block\",\n  \"caml_obj_dup\",\n  \"caml_obj_is_block\",\n  \"caml_obj_set_tag\",\n  \"caml_obj_tag\",\n  \"caml_obj_truncate\",\n  \"caml_output_value\",\n  \"caml_output_value_to_buffer\",\n  \"caml_output_value_to_string\",\n  \"caml_parse_engine\",\n  \"caml_power_float\",\n  \"caml_realloc_global\",\n  \"caml_record_backtrace\",\n  \"caml_register_code_fragment\",\n  \"caml_register_named_value\",\n  \"caml_reify_bytecode\",\n  \"caml_set_parser_trace\",\n  \"caml_sin_float\",\n  \"caml_sinh_float\",\n  \"caml_sqrt_float\",\n  \"caml_static_alloc\",\n  \"caml_static_free\",\n  \"caml_static_release_bytecode\",\n  \"caml_static_resize\",\n  \"caml_string_compare\",\n  \"caml_string_equal\",\n  \"caml_string_get\",\n  \"caml_string_get16\",\n  \"caml_string_get32\",\n  \"caml_string_get64\",\n  \"caml_string_greaterequal\",\n  \"caml_string_greaterthan\",\n  \"caml_string_lessequal\",\n  \"caml_string_lessthan\",\n  \"caml_string_notequal\",\n  \"caml_string_set\",\n  \"caml_string_set16\",\n  \"caml_string_set32\",\n  \"caml_string_set64\",\n  \"caml_sub_float\",\n  \"caml_sys_chdir\",\n  \"caml_sys_close\",\n  \"caml_sys_const_big_endian\",\n  \"caml_sys_const_ostype_cygwin\",\n  \"caml_sys_const_ostype_unix\",\n  \"caml_sys_const_ostype_win32\",\n  \"caml_sys_const_word_size\",\n  \"caml_sys_exit\",\n  \"caml_sys_file_exists\",\n  \"caml_sys_get_argv\",\n  \"caml_sys_get_config\",\n  \"caml_sys_getcwd\",\n  \"caml_sys_getenv\",\n  \"caml_sys_is_directory\",\n  \"caml_sys_open\",\n  \"caml_sys_random_seed\",\n  \"caml_sys_read_directory\",\n  \"caml_sys_remove\",\n  \"caml_sys_rename\",\n  \"caml_sys_system_command\",\n  \"caml_sys_time\",\n  \"caml_tan_float\",\n  \"caml_tanh_float\",\n  \"caml_terminfo_backup\",\n  \"caml_terminfo_resume\",\n  \"caml_terminfo_setup\",\n  \"caml_terminfo_standout\",\n  \"caml_update_dummy\",\n  \"caml_weak_blit\",\n  \"caml_weak_check\",\n  \"caml_weak_create\",\n  \"caml_weak_get\",\n  \"caml_weak_get_copy\",\n  \"caml_weak_set\",\n  (char *) 0 };\n\nvoid caml_startup(char ** argv)\n{\n  caml_startup_code(caml_code, sizeof(caml_code),\n                    caml_data, sizeof(caml_data),\n                    caml_sections, sizeof(caml_sections),\n                    argv);\n}\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "code/back-end-embed/hello.ml",
    "content": "let () = print_endline \"Hello OCaml World!\"\n"
  },
  {
    "path": "code/back-end-embed/link_custom.rawsh",
    "content": "$ ocamlc -a -o mylib.cma -custom a.cmo b.cmo -cclib -lmylib\n"
  },
  {
    "path": "code/back-end-embed/link_dllib.rawsh",
    "content": "$ ocamlc -a -o mylib.cma a.cmo b.cmo -dllib -lmylib\n"
  },
  {
    "path": "code/back-end-embed/main.c",
    "content": "#include <stdio.h>\n#include <caml/alloc.h>\n#include <caml/mlvalues.h>\n#include <caml/memory.h>\n#include <caml/callback.h>\n\nint \nmain (int argc, char **argv)\n{\n  printf(\"Before calling OCaml\\n\");\n  fflush(stdout);\n  caml_startup (argv);\n  printf(\"After calling OCaml\\n\");\n  return 0;\n}\n"
  },
  {
    "path": "code/back-end-embed/run_debug_hello.sh",
    "content": "ocamlopt -runtime-variant d -verbose -o hello.native hello.ml\n./hello.native\n"
  },
  {
    "path": "code/back-end-embed/xbuild_embed_binary.sh",
    "content": "gcc -fPIC -Wall -I`ocamlc -where` -L`ocamlc -where` -ltermcap -lm -ldl -o finalbc.native main.c embed_out.o -lcamlrun\n./finalbc.native\n"
  },
  {
    "path": "code/back-end-embed/xbuild_embed_native.sh",
    "content": "ocamlopt -output-obj -o embed_native.o embed_me1.ml embed_me2.ml\ngcc -Wall -I `ocamlc -where` -o final.native embed_native.o main.c -L `ocamlc -where` -lasmrun -ltermcap -lm -ldl\n./final.native\n"
  },
  {
    "path": "code/classes/Iterator.java",
    "content": "// Java-style iterator, specified as an interface.\ninterface <T> iterator {\n  T Get();\n  boolean HasValue();\n  void Next();\n};\n"
  },
  {
    "path": "code/classes/binary.topscript",
    "content": "class square w = object(self : 'self) \n    method width = w\n    method area = Float.of_int (self#width * self#width)\n    method equals (other : 'self) = other#width = self#width\n  end ;;\nclass circle r = object(self : 'self)\n    method radius = r\n    method area = 3.14 *. (Float.of_int self#radius) ** 2.0\n    method equals (other : 'self) = other#radius = self#radius\n  end ;;\n#part 1\n(new square 5)#equals (new square 5) ;;\n(new circle 10)#equals (new circle 7) ;;\n#part 2\ntype shape = < equals : shape -> bool; area : float > ;;\n(new square 5 :> shape) ;;\n#part 3\n(object method area = 5 end) = (object method area = 5 end) ;;\n#part 4\ntype shape_repr =\n  | Square of int\n  | Circle of int ;;\ntype shape =\n  < repr : shape_repr; equals : shape -> bool; area : float > ;;\nclass square w = object(self) \n    method width = w\n    method area = Float.of_int (self#width * self#width)\n    method repr = Square self#width\n    method equals (other : shape) = other#repr = self#repr\n  end ;;\n\n"
  },
  {
    "path": "code/classes/binary_larger.ml",
    "content": "class square w = object(self) \n  method width = w\n  method area = Float.of_int (self#width * self#width)\n  method larger other = self#area > other#area\nend\n"
  },
  {
    "path": "code/classes/binary_module.ml",
    "content": "module Shapes : sig\n  type shape_repr\n  type shape =\n    < repr : shape_repr; equals : shape -> bool; area: float >\n\n  class square : int ->\n    object\n      method width : int\n      method area : float\n      method repr : shape_repr\n      method equals : shape -> bool\n    end\nend = struct\n  type shape_repr = \n  | Square of int \n  | Circle of int \n  ...\nend\n"
  },
  {
    "path": "code/classes/build_doc.sh",
    "content": "corebuild doc.native\n"
  },
  {
    "path": "code/classes/citerator.cpp",
    "content": "// Abstract class definition in C++.\ntemplate<typename T>\nclass Iterator {\n public:\n  virtual ~Iterator() {}\n  virtual T get() const = 0;\n  virtual bool has_value() const = 0;\n  virtual void next() = 0;\n};\n"
  },
  {
    "path": "code/classes/class_types_stack.ml",
    "content": "module Stack = struct\n  class ['a] stack init = object\n    ...    \n  end\n\n  type 'a t = 'a stack\n\n  let make init = new stack init\nend\n\n(* part 1 *)\nmodule AbstractStack : sig\n   type 'a t = < pop: 'a option; push: 'a -> unit >\n\n   val make : unit -> 'a t\nend = Stack\n\n(* part 2 *)\nmodule VisibleStack : sig\n  \n  type 'a t = < pop: 'a option; push: 'a -> unit >\n\n  class ['a] stack : object\n    val mutable v : 'a list\n    method pop : 'a option\n    method push : 'a -> unit\n  end\n\n  val make : unit -> 'a t\nend = Stack\n"
  },
  {
    "path": "code/classes/doc.ml",
    "content": "type doc =\n  | Heading of string\n  | Paragraph of text_item list\n  | Definition of string list_item list\n\nand text_item =\n  | Raw of string\n  | Bold of text_item list\n  | Enumerate of int list_item list\n  | Quote of doc\n\nand 'a list_item = \n  { tag: 'a;\n    text: text_item list }\n\n(* part 1 *)\nopen Core.Std\n\nclass ['a] folder = object(self)\n  method doc acc = function\n  | Heading _ -> acc\n  | Paragraph text -> List.fold ~f:self#text_item ~init:acc text\n  | Definition list -> List.fold ~f:self#list_item ~init:acc list\n\n  method list_item: 'b. 'a -> 'b list_item -> 'a = \n    fun acc {tag; text} ->\n      List.fold ~f:self#text_item ~init:acc text\n\n  method text_item acc = function\n  | Raw _ -> acc\n  | Bold text -> List.fold ~f:self#text_item ~init:acc text\n  | Enumerate list -> List.fold ~f:self#list_item ~init:acc list\n  | Quote doc -> self#doc acc doc\nend\n\n(* part 2 *)\nclass counter = object\n  inherit [int] folder as super\n\n  method list_item acc li = acc\n\n  method text_item acc ti =\n    let acc = super#text_item acc ti in\n    match ti with\n    | Bold _ -> acc + 1\n    | _ -> acc\nend\n\nlet count_doc = (new counter)#doc\n\n(* part 3 *)\nclass ['a] folder2 = object(self)\n  method doc acc = function\n  | Heading str -> self#heading acc str\n  | Paragraph text -> self#paragraph acc text\n  | Definition list -> self#definition acc list\n\n  method list_item: 'b. 'a -> 'b list_item -> 'a =\n    fun acc {tag; text} ->\n      List.fold ~f:self#text_item ~init:acc text\n\n  method text_item acc = function\n  | Raw str -> self#raw acc str\n  | Bold text -> self#bold acc text\n  | Enumerate list -> self#enumerate acc list\n  | Quote doc -> self#quote acc doc\n\n  method private heading acc str = acc\n  method private paragraph acc text =\n    List.fold ~f:self#text_item ~init:acc text\n  method private definition acc list =\n    List.fold ~f:self#list_item ~init:acc list\n\n  method private raw acc str = acc\n  method private bold acc text = \n    List.fold ~f:self#text_item ~init:acc text\n  method private enumerate acc list = \n    List.fold ~f:self#list_item ~init:acc list\n  method private quote acc doc = self#doc acc doc\nend\n\nlet f :\n  < doc : int -> doc -> int;\n    list_item : 'a . int -> 'a list_item -> int;\n    text_item : int -> text_item -> int >  = new folder2\n\n(* part 4 *)\nclass counter_with_private_method = object\n  inherit [int] folder2 as super\n\n  method list_item acc li = acc\n\n  method private bold acc txt = \n    let acc = super#bold acc txt in\n    acc + 1\nend\n\n(* part 5 *)\nclass counter_with_sig : object\n  method doc : int -> doc -> int\n  method list_item : int -> 'b list_item -> int\n  method text_item : int -> text_item -> int\nend = object\n  inherit [int] folder2 as super\n\n  method list_item acc li = acc\n\n  method private bold acc txt = \n    let acc = super#bold acc txt in\n    acc + 1\nend\n"
  },
  {
    "path": "code/classes/initializer.topscript",
    "content": "class obj x = \n    let () = printf \"Creating obj %d\\n\" x in\n    object \n      val field = printf \"Initializing field\\n\"; x\n    end ;;\nlet o = new obj 3 ;;\n"
  },
  {
    "path": "code/classes/istack.topscript",
    "content": "class istack = object\n    val mutable v = [0; 2]\n\n    method pop =\n      match v with\n      | hd :: tl ->\n          v <- tl;\n          Some hd\n      | [] -> None\n\n    method push hd =\n      v <- hd :: v\n  end ;;\n#part 1\nlet s = new istack ;;\ns#pop ;;\ns#push 5 ;;\ns#pop ;;\n- : int option = Some 5\n#part 2\ntype istack = < pop: int option; push: int -> unit > ;;\n"
  },
  {
    "path": "code/classes/iter.topscript",
    "content": "type 'a iterator = < get : 'a; has_value : bool; next : unit > ;;\n#part 1\nclass ['a] list_iterator init = object\n    val mutable current : 'a list = init\n\n    method has_value = current <> []\n\n    method get =\n      match current with\n      | hd :: tl -> hd\n      | [] -> raise (Invalid_argument \"no value\")\n\n    method next =\n      match current with\n      | hd :: tl -> current <- tl\n      | [] -> raise (Invalid_argument \"no value\")\n   end  ;;\n#part 2\nclass ['a] stack init = object\n    val mutable v : 'a list = init\n\n    method pop =\n      match v with\n      | hd :: tl ->\n        v <- tl;\n        Some hd\n      | [] -> None\n\n    method push hd =\n      v <- hd :: v\n\n    method iterator : 'a iterator =\n      new list_iterator v\n  end ;;\n#part 3\nlet s = new stack [] ;;\ns#push 5 ;;\ns#push 4 ;;\nlet it = s#iterator ;;\nit#get ;;\nit#next ;;\nit#get ;;\nit#next ;;\nit#has_value ;;\n#part 4\nclass ['a] stack init = object\n    val mutable v : 'a list = init\n\n    method pop =\n      match v with\n      | hd :: tl ->\n        v <- tl;\n        Some hd\n      | [] -> None\n\n    method push hd =\n      v <- hd :: v\n\n   method iter f = \n     List.iter ~f v \n  end ;;\n#part 5\nclass ['a] stack init = object\n    val mutable v : 'a list = init\n\n    method pop =\n      match v with\n      | hd :: tl ->\n        v <- tl;\n        Some hd\n      | [] -> None\n\n    method push hd =\n      v <- hd :: v\n\n    method fold : 'b. ('b -> 'a -> 'b) -> 'b -> 'b =\n     (fun f init -> List.fold ~f ~init v) \n  end ;;\n"
  },
  {
    "path": "code/classes/stack.topscript",
    "content": "class ['a] stack init = object\n    val mutable v : 'a list = init\n\n    method pop =\n      match v with\n      | hd :: tl ->\n        v <- tl;\n        Some hd\n      | [] -> None\n\n    method push hd =\n      v <- hd :: v\n  end ;;\n#part 1\nclass ['a] stack init = object\n      val mutable v = init\n    \n      method pop = \n        match v with\n        | hd :: tl -> \n          v <- tl;\n          Some hd\n        | [] -> None\n\n      method push hd = \n        v <- hd :: v\n  end ;;\n#part 2\nclass sstack init = object\n    inherit [string] stack init\n\n    method print =\n      List.iter ~f:print_string v\n  end ;;\n#part 3\nclass double_stack init = object\n    inherit [int] stack init as super\n\n    method push hd =\n      super#push (hd * 2)\n  end ;;\n"
  },
  {
    "path": "code/classes-async/build_shapes.sh",
    "content": "corebuild -pkg async_graphics shapes.native\n"
  },
  {
    "path": "code/classes-async/multiple_inheritance.ml",
    "content": "open Core.Std\nopen Async.Std\nopen Async_graphics\n\nclass virtual shape x y = object(self)\n  method virtual private contains: int -> int -> bool\n\n  val mutable x: int = x\n  method x = x\n\n  val mutable y: int = y\n  method y = y\n\n  method on_click ?start ?stop f =\n    on_click ?start ?stop\n      (fun {mouse_x;mouse_y} ->  \n         if self#contains mouse_x mouse_y then\n           f mouse_x mouse_y)\n\n  method on_mousedown ?start ?stop f =\n    on_mousedown ?start ?stop\n      (fun {mouse_x;mouse_y} ->\n         if self#contains mouse_x mouse_y then\n           f mouse_x mouse_y)\nend\n\nclass square w x y = object\n  inherit shape x y\n\n  val mutable width = w\n  method width = width\n\n  method draw = fill_rect x y width width\n\n  method private contains x' y' = \n    x <= x' && x' <= x + width &&\n    y <= y' && y' <= y + width \nend\n\n(* part 1 *)\nclass square_outline w x y = object\n  inherit square w x y\n  method draw = draw_rect x y width width\nend\n"
  },
  {
    "path": "code/classes-async/multiple_inheritance_wrong.ml",
    "content": "open Core.Std\nopen Async.Std\nopen Async_graphics\n\nclass virtual shape x y = object(self)\n  method virtual private contains: int -> int -> bool\n\n  val mutable x: int = x\n  method x = x\n\n  val mutable y: int = y\n  method y = y\n\n  method on_click ?start ?stop f =\n    on_click ?start ?stop\n      (fun {mouse_x;mouse_y} ->  \n         if self#contains mouse_x mouse_y then\n           f mouse_x mouse_y)\n\n  method on_mousedown ?start ?stop f =\n    on_mousedown ?start ?stop\n      (fun {mouse_x;mouse_y} ->\n         if self#contains mouse_x mouse_y then\n           f mouse_x mouse_y)\nend\n\nclass square w x y = object\n  inherit shape x y\n\n  val mutable width = w\n  method width = width\n\n  method draw = fill_rect x y width width\n\n  method private contains x' y' = \n    x <= x' && x' <= x + width &&\n    y <= y' && y' <= y + width \nend\n\n(* part 1 *)\nclass square_outline w x y = object\n  method draw = draw_rect x y w w\n  inherit square w x y\nend\n"
  },
  {
    "path": "code/classes-async/shapes.ml",
    "content": "open Core.Std\nopen Async.Std\nopen Async_graphics\n\ntype drawable = < draw: unit >\n\n(* part 1 *)\nclass virtual shape x y = object(self)\n  method virtual private contains: int -> int -> bool\n\n  val mutable x: int = x\n  method x = x\n\n  val mutable y: int = y\n  method y = y\n\n  method on_click ?start ?stop f =\n    on_click ?start ?stop\n      (fun ev ->  \n         if self#contains ev.mouse_x ev.mouse_y then\n           f ev.mouse_x ev.mouse_y)\n\n  method on_mousedown ?start ?stop f =\n    on_mousedown ?start ?stop\n      (fun ev ->\n         if self#contains ev.mouse_x ev.mouse_y then\n           f ev.mouse_x ev.mouse_y)\nend\n\n(* part 2 *)\nclass square w x y = object\n  inherit shape x y\n\n  val mutable width = w\n  method width = width\n\n  method draw = fill_rect x y width width\n\n  method private contains x' y' = \n    x <= x' && x' <= x + width &&\n    y <= y' && y' <= y + width \nend \n\nclass circle r x y = object\n  inherit shape x y\n\n  val mutable radius = r\n  method radius = radius\n\n  method draw = fill_circle x y radius\n\n  method private contains x' y' =\n    let dx = abs (x' - x) in\n    let dy = abs (y' - y) in\n    let dist = sqrt (Float.of_int ((dx * dx) + (dy * dy))) in\n    dist <= (Float.of_int radius)\nend\n\n(* part 3 *)\nclass growing_circle r x y = object(self)\n  inherit circle r x y\n\n  initializer\n    self#on_click (fun _x _y -> radius <- radius * 2)\nend\n\n(* part 4 *)\nclass virtual draggable = object(self)\n  method virtual on_mousedown: \n    ?start:unit Deferred.t -> \n    ?stop:unit Deferred.t -> \n    (int -> int -> unit) -> unit\n  val virtual mutable x: int  \n  val virtual mutable y: int  \n\n  val mutable dragging = false\n  method dragging = dragging\n\n  initializer \n    self#on_mousedown \n      (fun mouse_x mouse_y ->\n         let offset_x = x - mouse_x in\n         let offset_y = y - mouse_y in\n         let mouse_up = Ivar.create () in\n         let stop = Ivar.read mouse_up in\n         dragging <- true;\n         on_mouseup ~stop\n           (fun _ ->\n              Ivar.fill mouse_up ();\n              dragging <- false);\n         on_mousemove ~stop\n           (fun ev ->\n              x <- ev.mouse_x + offset_x;\n              y <- ev.mouse_y + offset_y))\nend\n\n(* part 5 *)\nclass small_square = object\n  inherit square 20 40 40\n  inherit draggable \nend\n\n(* part 6 *)\nclass virtual animated span = object(self)\n  method virtual on_click: \n    ?start:unit Deferred.t -> \n    ?stop:unit Deferred.t -> \n    (int -> int -> unit) -> unit\n  val mutable updates: (int -> unit) list = []\n  val mutable step = 0\n  val mutable running = false\n\n  method running = running\n\n  method animate =\n    step <- 0;\n    running <- true;\n    let stop =\n      Clock.after span\n      >>| fun () -> running <- false \n    in\n    Clock.every ~stop (Time.Span.of_sec (1.0 /. 24.0))\n      (fun () ->\n         step <- step + 1;\n         List.iter ~f:(fun f -> f step) updates\n      )\n\n  initializer\n    self#on_click (fun _x _y -> if not self#running then self#animate)\nend\n\n(* part 7 *)\nclass my_circle = object\n  inherit circle 20 50 50\n  inherit animated Time.Span.second\n  initializer updates <- [fun _ -> x <- x + 5]\nend\n\n(* part 8 *)\nclass virtual linear x' y' = object\n  val virtual mutable updates: (int -> unit) list\n  val virtual mutable x: int\n  val virtual mutable y: int\n\n  initializer\n    let update _ =\n      x <- x + x';\n      y <- y + y'\n    in\n    updates <- update :: updates\nend\n\nlet pi = (atan 1.0) *. 4.0\n\nclass virtual harmonic offset x' y' = object\n  val virtual mutable updates: (int -> unit) list\n  val virtual mutable x: int\n  val virtual mutable y: int\n\n  initializer\n    let update step =\n      let m = sin (offset +. ((Float.of_int step) *. (pi /. 64.))) in\n      let x' = Float.to_int (m *. Float.of_int x') in\n      let y' = Float.to_int (m *. Float.of_int y') in\n      x <- x + x';\n      y <- y + y'\n    in\n    updates <- update :: updates\nend\n\n(* part 9 *)\nclass my_square x y = object\n  inherit square 40 x y\n  inherit draggable\n  inherit animated (Time.Span.of_int_sec 5)\n  inherit linear 5 0\n  inherit harmonic 0.0 7 ~-10\nend\n\nlet my_circle = object\n  inherit circle 30 250 250\n  inherit animated (Time.Span.minute)\n  inherit harmonic 0.0 10 0\n  inherit harmonic (pi /. 2.0) 0 10\nend\n\n(* part 10 *)\n\nlet main () =\n  let shapes = [ \n     (my_circle :> drawable); \n     (new my_square 50 350 :> drawable); \n     (new my_square 50 200 :> drawable);\n     (new growing_circle 20 70 70 :> drawable);\n  ] in\n  let repaint () =\n    clear_graph ();\n    List.iter ~f:(fun s -> s#draw) shapes;\n    synchronize ()\n  in \n    open_graph \"\";\n    auto_synchronize false;\n    Clock.every (Time.Span.of_sec (1.0 /. 24.0)) repaint\n\nlet () = never_returns (Scheduler.go_main ~main ())\n  \n"
  },
  {
    "path": "code/classes-async/verbose_shapes.ml",
    "content": "open Core.Std\nopen Async.Std\nopen Async_graphics\n\n(* part 1 *)\nclass square w x y = object(self)\n  val mutable x: int = x\n  method x = x\n\n  val mutable y: int = y\n  method y = y\n\n  val mutable width = w\n  method width = width\n\n  method draw = fill_rect x y width width\n\n  method private contains x' y' =\n    x <= x' && x' <= x + width &&\n      y <= y' && y' <= y + width\n\n  method on_click ?start ?stop f =\n    on_click ?start ?stop\n      (fun ev ->\n         if self#contains ev.mouse_x ev.mouse_y then\n           f ev.mouse_x ev.mouse_y)\nend\n\n(* part 2 *)\nclass circle r x y = object(self)\n  val mutable x: int = x\n  method x = x\n\n  val mutable y: int = y\n  method y = y\n\n  val mutable radius = r\n  method radius = radius\n\n  method draw = fill_circle x y radius\n\n  method private contains x' y' =\n    let dx = abs (x' - x) in\n    let dy = abs (y' - y) in\n    let dist = sqrt (Float.of_int ((dx * dx) + (dy * dy))) in\n      dist <= (Float.of_int radius)\n\n  method on_click ?start ?stop f =\n    on_click ?start ?stop\n      (fun ev ->\n         if self#contains ev.mouse_x ev.mouse_y then\n           f ev.mouse_x ev.mouse_y)\nend\n"
  },
  {
    "path": "code/command-line-parsing/_tags",
    "content": "true: short_paths\n"
  },
  {
    "path": "code/command-line-parsing/basic.topscript",
    "content": "Command.basic ;;\n"
  },
  {
    "path": "code/command-line-parsing/basic_md5.ml",
    "content": "open Core.Std\n\nlet do_hash file =\n  In_channel.with_file file ~f:(fun ic ->\n    let open Cryptokit in\n    hash_channel (Hash.md5 ()) ic\n    |> transform_string (Hexa.encode ())\n    |> print_endline\n  )\n\n(* part 1 *)\nlet spec =\n  let open Command.Spec in\n  empty\n  +> anon (\"filename\" %: string)\n\n(* part 2 *)\nlet command =\n  Command.basic\n    ~summary:\"Generate an MD5 hash of the input data\"\n    ~readme:(fun () -> \"More detailed information\")\n    spec\n    (fun filename () -> do_hash filename)\n\n(* part 3 *)\nlet () =\n  Command.run ~version:\"1.0\" ~build_info:\"RWO\" command\n"
  },
  {
    "path": "code/command-line-parsing/basic_md5_as_filename.ml",
    "content": "open Core.Std\n\nlet do_hash file () =\n  In_channel.with_file file ~f:(\n    fun ic ->\n      let open Cryptokit in\n      hash_channel (Hash.md5 ()) ic\n      |> transform_string (Hexa.encode ())\n      |> print_endline\n  )\n\n(* part 1 *)\nlet command =\n  Command.basic\n    ~summary:\"Generate an MD5 hash of the input data\"\n    ~readme:(fun () -> \"More detailed information\")\n    Command.Spec.(empty +> anon (\"filename\" %: file))\n    do_hash\n\nlet () =\n  Command.run ~version:\"1.0\" ~build_info:\"RWO\" command\n"
  },
  {
    "path": "code/command-line-parsing/basic_md5_sequence.ml",
    "content": "open Core.Std\n\nlet do_hash filename ic =\n  let open Cryptokit in\n  hash_channel (Hash.md5 ()) ic\n  |> transform_string (Hexa.encode ())\n  |> fun md5 -> printf \"MD5 (%s) = %s\\n\" filename md5\n\nlet command =\n  Command.basic\n    ~summary:\"Generate an MD5 hash of the input data\"\n    ~readme:(fun () -> \"More detailed information\")\n    Command.Spec.(empty +> anon (sequence (\"filename\" %: file)))\n    (fun files () ->\n       match files with\n       | [] -> do_hash \"-\" In_channel.stdin\n       | _  ->\n         List.iter files ~f:(fun file ->\n           In_channel.with_file ~f:(do_hash file) file\n         )\n    )\n\nlet () =\n  Command.run ~version:\"1.0\" ~build_info:\"RWO\" command\n"
  },
  {
    "path": "code/command-line-parsing/basic_md5_succinct.ml",
    "content": "open Core.Std\n\nlet do_hash file () =\n  In_channel.with_file file ~f:(fun ic ->\n    let open Cryptokit in\n    hash_channel (Hash.md5 ()) ic\n    |> transform_string (Hexa.encode ())\n    |> print_endline\n  )\n\nlet command =\n  Command.basic\n    ~summary:\"Generate an MD5 hash of the input data\"\n    ~readme:(fun () -> \"More detailed information\")\n    Command.Spec.(empty +> anon (\"filename\" %: string))\n    do_hash\n\nlet () =\n  Command.run ~version:\"1.0\" ~build_info:\"RWO\" command\n"
  },
  {
    "path": "code/command-line-parsing/basic_md5_with_custom_arg.ml",
    "content": "open Core.Std\n\nlet do_hash file () =\n  In_channel.with_file file ~f:(fun ic ->\n    let open Cryptokit in\n    hash_channel (Hash.md5 ()) ic\n    |> transform_string (Hexa.encode ())\n    |> print_endline\n  )\n\nlet regular_file =\n  Command.Spec.Arg_type.create\n    (fun filename ->\n       match Sys.is_file filename with\n       | `Yes -> filename\n       | `No | `Unknown ->\n         eprintf \"'%s' is not a regular file.\\n%!\" filename;\n         exit 1\n    )\n\nlet command =\n  Command.basic\n    ~summary:\"Generate an MD5 hash of the input data\"\n    ~readme:(fun () -> \"More detailed information\")\n    Command.Spec.(empty +> anon (\"filename\" %: regular_file))\n    do_hash\n\nlet () =\n  Command.run ~version:\"1.0\" ~build_info:\"RWO\" command\n"
  },
  {
    "path": "code/command-line-parsing/basic_md5_with_default_file.ml",
    "content": "open Core.Std\n\nlet get_inchan = function\n  | \"-\"      -> In_channel.stdin\n  | filename -> In_channel.create ~binary:true filename\n\nlet do_hash filename () =\n  let open Cryptokit in\n  get_inchan filename\n  |> hash_channel (Hash.md5 ())\n  |> transform_string (Hexa.encode ())\n  |> print_endline\n\nlet command =\n  Command.basic\n    ~summary:\"Generate an MD5 hash of the input data\"\n    ~readme:(fun () -> \"More detailed information\")\n    Command.Spec.(\n      empty\n      +> anon (maybe_with_default \"-\" (\"filename\" %: file))\n    )\n    do_hash\n\nlet () =\n  Command.run ~version:\"1.0\" ~build_info:\"RWO\" command\n"
  },
  {
    "path": "code/command-line-parsing/basic_md5_with_flags.ml",
    "content": "open Core.Std\nopen Cryptokit\n\nlet checksum_from_string buf =\n  hash_string (Hash.md5 ()) buf\n  |> transform_string (Hexa.encode ())\n  |> print_endline\n\nlet checksum_from_file filename =\n  let ic = match filename with\n    | \"-\" -> In_channel.stdin\n    | _   -> In_channel.create ~binary:true filename\n  in\n  hash_channel (Hash.md5 ()) ic\n  |> transform_string (Hexa.encode ())\n  |> print_endline\n\nlet command =\n  Command.basic\n    ~summary:\"Generate an MD5 hash of the input data\"\n    Command.Spec.(\n      empty\n      +> flag \"-s\" (optional string) ~doc:\"string Checksum the given string\"\n      +> flag \"-t\" no_arg ~doc:\" run a built-in time trial\"\n      +> anon (maybe_with_default \"-\" (\"filename\" %: file))\n    )\n    (fun use_string trial filename () ->\n       match trial with\n       | true -> printf \"Running time trial\\n\"\n       | false -> begin\n           match use_string with\n           | Some buf -> checksum_from_string buf\n           | None -> checksum_from_file filename\n         end\n    )\n\nlet () = Command.run command\n"
  },
  {
    "path": "code/command-line-parsing/basic_md5_with_opt_flags.ml",
    "content": "open Core.Std\nopen Cryptokit\n\nlet checksum_from_string buf =\n  hash_string (Hash.md5 ()) buf\n  |> transform_string (Hexa.encode ())\n  |> print_endline\n\nlet checksum_from_file filename =\n  let ic = match filename with\n    | \"-\" -> In_channel.stdin\n    | _   -> In_channel.create ~binary:true filename\n  in\n  hash_channel (Hash.md5 ()) ic\n  |> transform_string (Hexa.encode ())\n  |> print_endline\n\nlet command =\n  Command.basic\n    ~summary:\"Generate an MD5 hash of the input data\"\n    Command.Spec.(\n      empty\n      +> flag \"-s\" (optional string)\n           ~doc:\"string Checksum the given string\"\n      +> flag \"-v\" (listed bool)\n           ~doc:\" verbosity level. Repeat multiple times for more info.\"\n      +> flag \"-t\" no_arg\n           ~doc:\" run a built-in time trial\"\n      +> flag \"-tlen\" (optional_with_default 5 int)\n           ~doc:\"seconds length of time trial\"\n      +> anon (maybe_with_default \"-\" (\"filename\" %: file))\n    )\n    (fun use_string verbosity trial trial_secs filename () ->\n       eprintf \"Verbosity level: %d\\n\" (List.length verbosity);\n       match trial with\n       | true -> printf \"Running time trial for %d seconds\\n\" trial_secs\n       | false -> begin\n           match use_string with\n           | Some buf -> checksum_from_string buf\n           | None -> checksum_from_file filename\n         end\n    )\n\nlet () = Command.run command\n"
  },
  {
    "path": "code/command-line-parsing/basic_md5_with_optional_file.ml",
    "content": "open Core.Std\n\nlet get_inchan = function\n  | None | Some \"-\" ->\n    In_channel.stdin\n  | Some filename ->\n    In_channel.create ~binary:true filename\n\nlet do_hash filename () =\n  let open Cryptokit in\n  get_inchan filename\n  |> hash_channel (Hash.md5 ())\n  |> transform_string (Hexa.encode ())\n  |> print_endline\n\nlet command =\n  Command.basic\n    ~summary:\"Generate an MD5 hash of the input data\"\n    ~readme:(fun () -> \"More detailed information\")\n    Command.Spec.(empty +> anon (maybe (\"filename\" %: file)))\n    do_hash\n\nlet () =\n  Command.run ~version:\"1.0\" ~build_info:\"RWO\" command\n"
  },
  {
    "path": "code/command-line-parsing/basic_md5_with_optional_file_broken.ml",
    "content": "open Core.Std\n\nlet do_hash file () =\n  In_channel.with_file file ~f:(\n    fun ic ->\n      let open Cryptokit in\n      hash_channel (Hash.md5 ()) ic\n      |> transform_string (Hexa.encode ())\n      |> print_endline\n  )\n\n(* part 1 *)\nlet command =\n  Command.basic\n    ~summary:\"Generate an MD5 hash of the input data\"\n    ~readme:(fun () -> \"More detailed information\")\n    Command.Spec.(empty +> anon (maybe (\"filename\" %: string)))\n    do_hash\n\nlet () =\n  Command.run ~version:\"1.0\" ~build_info:\"RWO\" command\n"
  },
  {
    "path": "code/command-line-parsing/build_and_run_cal_add_interactive.rawsh",
    "content": "$ ocamlbuild -use-ocamlfind -tag thread -pkg core cal_add_interactive.native\n$ ./cal_add_interactive.native 2013-12-01\nenter days:\n35\n2014-01-05\n"
  },
  {
    "path": "code/command-line-parsing/build_basic_md5.sh",
    "content": "corebuild -pkg cryptokit basic_md5.native\n"
  },
  {
    "path": "code/command-line-parsing/build_basic_md5_as_filename.sh",
    "content": "corebuild -pkg cryptokit basic_md5_as_filename.native\n"
  },
  {
    "path": "code/command-line-parsing/build_basic_md5_sequence.sh",
    "content": "corebuild -pkg cryptokit basic_md5_sequence.native\n"
  },
  {
    "path": "code/command-line-parsing/build_basic_md5_with_custom_arg.sh",
    "content": "corebuild -pkg cryptokit basic_md5_with_custom_arg.native\n"
  },
  {
    "path": "code/command-line-parsing/build_basic_md5_with_default_file.sh",
    "content": "corebuild -pkg cryptokit basic_md5_with_default_file.native\n"
  },
  {
    "path": "code/command-line-parsing/build_basic_md5_with_flags.sh",
    "content": "corebuild -pkg cryptokit basic_md5_with_flags.native\n"
  },
  {
    "path": "code/command-line-parsing/build_basic_md5_with_opt_flags.sh",
    "content": "corebuild -pkg cryptokit basic_md5_with_opt_flags.native\n"
  },
  {
    "path": "code/command-line-parsing/build_basic_md5_with_optional_file.sh",
    "content": "corebuild -pkg cryptokit basic_md5_with_optional_file.native\n"
  },
  {
    "path": "code/command-line-parsing/build_basic_md5_with_optional_file_broken.errsh",
    "content": "corebuild -pkg cryptokit basic_md5_with_optional_file_broken.native\n"
  },
  {
    "path": "code/command-line-parsing/build_cal_add_days.sh",
    "content": "corebuild cal_add_days.native\n"
  },
  {
    "path": "code/command-line-parsing/build_cal_add_sub_days.sh",
    "content": "corebuild cal_add_sub_days.native\n./cal_add_sub_days.native -help\n"
  },
  {
    "path": "code/command-line-parsing/build_cal_append.sh",
    "content": "corebuild cal_append.native\n"
  },
  {
    "path": "code/command-line-parsing/build_cal_append_broken.errsh",
    "content": "corebuild cal_append_broken.native\n"
  },
  {
    "path": "code/command-line-parsing/cal.cmd",
    "content": "function _jsautocom_96173 {\n  export COMP_CWORD\n  COMP_WORDS[0]=./cal_add_sub_days.native\n  COMPREPLY=($(\"${COMP_WORDS[@]}\"))\n}\ncomplete -F _jsautocom_96173 ./cal_add_sub_days.native\n"
  },
  {
    "path": "code/command-line-parsing/cal_add_days.ml",
    "content": "open Core.Std\n\nlet add =\n  Command.basic\n    ~summary:\"Add [days] to the [base] date and print day\"\n    Command.Spec.(\n      empty\n      +> anon (\"base\" %: date)\n      +> anon (\"days\" %: int)\n    )\n    (fun base span () ->\n       Date.add_days base span\n       |> Date.to_string\n       |> print_endline\n    )\n\nlet () = Command.run add\n"
  },
  {
    "path": "code/command-line-parsing/cal_add_interactive.ml",
    "content": "open Core.Std\n\nlet add_days base span () =\n  Date.add_days base span\n  |> Date.to_string\n  |> print_endline\n\nlet add =\n  Command.basic\n    ~summary:\"Add [days] to the [base] date and print day\"\n    Command.Spec.( \n      step \n        (fun m base days ->\n           match days with\n           | Some days ->\n             m base days\n           | None ->\n             print_endline \"enter days: \";\n             read_int ()\n             |> m base\n        )\n      +> anon (\"base\" %: date)\n      +> anon (maybe (\"days\" %: int))\n    )\n    add_days\n\nlet () = Command.run add\n"
  },
  {
    "path": "code/command-line-parsing/cal_add_labels.ml",
    "content": "open Core.Std\n\nlet add_days ~base_date ~num_days () =\n  Date.add_days base_date num_days\n  |> Date.to_string\n  |> print_endline\n\nlet add =\n  Command.basic\n    ~summary:\"Add [days] to the [base] date and print day\"\n    Command.Spec.( \n      step (fun m base days -> m ~base_date:base ~num_days:days)\n      +> anon (\"base\" %: date)\n      +> anon (\"days\" %: int)\n    )\n    add_days\n\nlet () = Command.run add\n"
  },
  {
    "path": "code/command-line-parsing/cal_add_sub_days.ml",
    "content": "open Core.Std\n\nlet add =\n  Command.basic ~summary:\"Add [days] to the [base] date\"\n    Command.Spec.(\n      empty\n      +> anon (\"base\" %: date)\n      +> anon (\"days\" %: int)\n    )\n    (fun base span () ->\n       Date.add_days base span\n       |> Date.to_string\n       |> print_endline\n    )\n\nlet diff =\n  Command.basic ~summary:\"Show days between [date1] and [date2]\"\n    Command.Spec.(\n      empty\n      +> anon (\"date1\" %: date)\n      +> anon (\"date2\" %: date)\n    )\n    (fun date1 date2 () ->\n       Date.diff date1 date2\n       |> printf \"%d days\\n\"\n    )\n\nlet command =\n  Command.group ~summary:\"Manipulate dates\"\n    [ \"add\", add; \"diff\", diff ]\n\nlet () = Command.run command\n"
  },
  {
    "path": "code/command-line-parsing/cal_append.ml",
    "content": "open Core.Std\n\nlet add ~common =\n  Command.basic ~summary:\"Add [days] to the [base] date\"\n    Command.Spec.(\n      empty\n      +> anon (\"base\" %: date)\n      +> anon (\"days\" %: int)\n      ++ common\n    )\n    (fun base span debug verbose () ->\n       Date.add_days base span\n       |> Date.to_string\n       |> print_endline\n    )\n\nlet diff ~common =\n  Command.basic ~summary:\"Show days between [date2] and [date1]\"\n    Command.Spec.(\n      empty\n      +> anon (\"date1\" %: date)\n      +> anon (\"date2\" %: date)\n      ++ common\n    )\n    (fun date1 date2 debug verbose () ->\n       Date.diff date1 date2\n       |> printf \"%d days\\n\"\n    )\n\n(* part 1 *)\nlet () =\n  let common =\n    Command.Spec.(\n      empty\n      +> flag \"-d\" (optional_with_default false bool) ~doc:\" Debug mode\"\n      +> flag \"-v\" (optional_with_default false bool) ~doc:\" Verbose output\"\n    )\n  in\n  List.map ~f:(fun (name, cmd) -> (name, cmd ~common))\n    [ \"add\", add; \"diff\", diff ]\n  |> Command.group ~summary:\"Manipulate dates\"\n  |> Command.run\n"
  },
  {
    "path": "code/command-line-parsing/cal_append_broken.ml",
    "content": "open Core.Std\n\nlet add ~common =\n  Command.basic ~summary:\"Add [days] to the [base] date\"\n    Command.Spec.(\n      empty\n      +> anon (\"base\" %: date)\n      +> anon (\"days\" %: int)\n      ++ common\n    )\n    (fun base span debug verbose () ->\n       Date.add_days base span\n       |> Date.to_string\n       |> print_endline\n    )\n\nlet diff ~common =\n  Command.basic ~summary:\"Show days between [date2] and [date1]\"\n    Command.Spec.(\n      empty\n      +> anon (\"date1\" %: date)\n      +> anon (\"date2\" %: date)\n      ++ common\n    )\n    (fun date1 date2 debug verbose () ->\n       Date.diff date1 date2\n       |> printf \"%d days\\n\"\n    )\n\n(* part 1 *)\nlet () =\n  let common =\n    Command.Spec.(\n      empty\n      +> flag \"-d\" (optional_with_default false bool) ~doc:\" Debug mode\"\n    )\n  in\n  List.map ~f:(fun (name, cmd) -> (name, cmd ~common))\n    [ \"add\", add; \"diff\", diff ]\n  |> Command.group ~summary:\"Manipulate dates\"\n  |> Command.run\n"
  },
  {
    "path": "code/command-line-parsing/cal_completion.rawsh",
    "content": "$ env COMMAND_OUTPUT_INSTALLATION_BASH=1 ./cal_add_sub_days.native > cal.cmd\n$ . cal.cmd\n$ ./cal_add_sub_days.native <tab>\nadd      diff     help     version\n"
  },
  {
    "path": "code/command-line-parsing/command_types.topscript",
    "content": "Command.Spec.empty ;;\nCommand.Spec.(empty +> anon (\"foo\" %: int)) ;;\n"
  },
  {
    "path": "code/command-line-parsing/get_basic_md5_help.errsh",
    "content": "./basic_md5.native\n"
  },
  {
    "path": "code/command-line-parsing/get_basic_md5_version.sh",
    "content": "./basic_md5.native -version\n./basic_md5.native -build-info\n"
  },
  {
    "path": "code/command-line-parsing/group.topscript",
    "content": "Command.basic ;;\nCommand.group ;;\n"
  },
  {
    "path": "code/command-line-parsing/md5_completion.sh",
    "content": "env COMMAND_OUTPUT_INSTALLATION_BASH=1 ./basic_md5_with_flags.native\n"
  },
  {
    "path": "code/command-line-parsing/opam.rawsh",
    "content": "$ opam config env\n$ opam remote list -k git\n$ opam install --help\n$ opam install cryptokit --verbose\n"
  },
  {
    "path": "code/command-line-parsing/run_basic_and_default_md5.sh",
    "content": "cat /etc/passwd | ./basic_md5_with_optional_file.native\ncat /etc/passwd | ./basic_md5_with_default_file.native\n"
  },
  {
    "path": "code/command-line-parsing/run_basic_md5.sh",
    "content": "./basic_md5.native ./basic_md5.native\n"
  },
  {
    "path": "code/command-line-parsing/run_basic_md5_as_filename.errsh",
    "content": "./basic_md5_as_filename.native nonexistent\n"
  },
  {
    "path": "code/command-line-parsing/run_basic_md5_flags_help.sh",
    "content": "./basic_md5_with_flags.native -help\n./basic_md5_with_flags.native -s \"ocaml rocks\"\n"
  },
  {
    "path": "code/command-line-parsing/run_basic_md5_with_custom_arg.errsh",
    "content": "./basic_md5_with_custom_arg.native /etc/passwd\n./basic_md5_with_custom_arg.native /dev/null\n"
  },
  {
    "path": "code/command-line-parsing/run_cal_add_sub_days.sh",
    "content": "./cal_add_sub_days.native add 2012-12-25 40\n./cal_add_sub_days.native diff 2012-12-25 2012-11-01\n"
  },
  {
    "path": "code/command-line-parsing/single_anon_filename.topscript",
    "content": "open Command.Spec ;;\nempty +> anon (\"filename\" %: string) ;;\n"
  },
  {
    "path": "code/command-line-parsing/step.topscript",
    "content": "open Command.Spec ;;\nstep (fun m (base:Date.t) days ->\n  match days with\n  | Some days -> m base days\n  | None ->\n     print_endline \"enter days: \";\n     m base (read_int ())) ;;\n"
  },
  {
    "path": "code/corebuild",
    "content": "#!/bin/sh\n\nocamlbuild \\\n    -use-ocamlfind \\\n    -classic-display \\\n    -syntax camlp4o \\\n    -pkg core,core_extended,async,textutils,core_bench  \\\n    -pkg sexplib.syntax,comparelib.syntax,fieldslib.syntax,variantslib.syntax \\\n    -pkg bin_prot.syntax \\\n    -tag thread \\\n    -tag debug \\\n    -cflags -short-paths \\\n    -cflags \"-w @A-4-33-41-42-43-34-44\" \\\n    -cflags -strict-sequence \\\n    -cflags -principal \\\n    $@\n"
  },
  {
    "path": "code/ctypes/ctypes.mli",
    "content": "type 'a typ\n\n(* part 1 *)\nval void      : unit typ\nval char      : char typ\nval schar     : int typ\nval short     : int typ\nval int       : int typ\nval long      : long typ\nval llong     : llong typ\nval nativeint : nativeint typ\n\nval int8_t    : int typ\nval int16_t   : int typ\nval int32_t   : int32 typ\nval int64_t   : int64 typ\nval uchar     : uchar typ\nval uchar     : uchar typ\nval uint8_t   : uint8 typ\nval uint16_t  : uint16 typ\nval uint32_t  : uint32 typ\nval uint64_t  : uint64 typ\nval size_t    : size_t typ\nval ushort    : ushort typ\nval uint      : uint typ\nval ulong     : ulong typ\nval ullong    : ullong typ\n\nval float     : float typ\nval double    : float typ\n\nval complex32 : Complex.t typ\nval complex64 : Complex.t typ\n\n(* part 2 *)\nval view :\n  read:('a -> 'b) ->\n  write:('b -> 'a) ->\n  'a typ -> 'b typ\n\n(* part 3 *)\nval string_of_char_ptr : char ptr -> string\nval char_ptr_of_string : string -> char ptr\n\n(* part 4 *)\nval string    : string.typ\n\n(* part 5 *)\nmodule Array : sig\n  type 'a t = 'a array\n\n  val get : 'a t -> int -> 'a\n  val set : 'a t -> int -> 'a -> unit\n  val of_list : 'a typ -> 'a list -> 'a t\n  val to_list : 'a t -> 'a list\n  val length : 'a t -> int\n  val start : 'a t -> 'a ptr\n  val from_ptr : 'a ptr -> int -> 'a t\n  val make : 'a typ -> ?initial:'a -> int -> 'a t\nend\n"
  },
  {
    "path": "code/ctypes/ctypes_impl.ml",
    "content": "let string = \n  view (char ptr)\n    ~read:string_of_char_ptr \n    ~write:char_ptr_of_string \n"
  },
  {
    "path": "code/error-handling/blow_up.ml",
    "content": "open Core.Std\nexception Empty_list\n\nlet list_max = function\n  | [] -> raise Empty_list\n  | hd :: tl -> List.fold tl ~init:hd ~f:(Int.max)\n\nlet () =\n  printf \"%d\\n\" (list_max [1;2;3]);\n  printf \"%d\\n\" (list_max [])\n"
  },
  {
    "path": "code/error-handling/build_blow_up.errsh",
    "content": "corebuild blow_up.byte\n./blow_up.byte\n"
  },
  {
    "path": "code/error-handling/build_blow_up_notrace.errsh",
    "content": "corebuild blow_up.byte\nOCAMLRUNPARAM= ./blow_up.byte\n"
  },
  {
    "path": "code/error-handling/exn_cost.ml",
    "content": "open Core.Std\nopen Core_bench.Std\n\nlet simple_computation () =\n  List.range 0 10\n  |> List.fold ~init:0 ~f:(fun sum x -> sum + x * x)\n  |> ignore\n\nlet simple_with_handler () =\n  try simple_computation () with Exit -> ()\n\nlet end_with_exn () =\n  try\n    simple_computation ();\n    raise Exit\n  with Exit -> ()\n\nlet () =\n  [ Bench.Test.create ~name:\"simple computation\"\n      (fun () -> simple_computation ());\n    Bench.Test.create ~name:\"simple computation w/handler\"\n      (fun () -> simple_with_handler ());\n    Bench.Test.create ~name:\"end with exn\"\n      (fun () -> end_with_exn ());\n  ]\n  |> Bench.make_command\n  |> Command.run\n"
  },
  {
    "path": "code/error-handling/main.topscript",
    "content": "List.find;;\n#part 1\nList.find [1;2;3] ~f:(fun x -> x >= 2) ;;\nList.find [1;2;3] ~f:(fun x -> x >= 10) ;;\n#part 2\nlet compute_bounds ~cmp list =\n    let sorted = List.sort ~cmp list in\n    match List.hd sorted, List.last sorted with\n    | None,_ | _, None -> None\n    | Some x, Some y -> Some (x,y)\n  ;;\n#part 3\nlet find_mismatches table1 table2 =\n     Hashtbl.fold table1 ~init:[] ~f:(fun ~key ~data mismatches ->\n        match Hashtbl.find table2 key with\n        | Some data' when data' <> data -> key :: mismatches\n        | _ -> mismatches\n     )\n ;;\n#part 4\n[ Ok 3; Error \"abject failure\"; Ok 4 ];;\n#part 5\nError.of_string \"something went wrong\";;\n#part 6\nError.of_thunk (fun () ->\n    sprintf \"something went wrong: %f\" 32.3343);;\n#part 7\nError.create \"Something failed a long time ago\" Time.epoch Time.sexp_of_t;;\n#part 8\nlet custom_to_sexp = <:sexp_of<float * string list * int>>;;\ncustom_to_sexp (3.5, [\"a\";\"b\";\"c\"], 6034);;\n#part 9\nError.create \"Something went terribly wrong\"\n    (3.5, [\"a\";\"b\";\"c\"], 6034)\n    <:sexp_of<float * string list * int>> ;;\n#part 10\nError.tag\n    (Error.of_list [ Error.of_string \"Your tires were slashed\";\n                     Error.of_string \"Your windshield was smashed\" ])\n    \"over the weekend\"\n  ;;\n#part 11\nlet bind option f =\n    match option with\n    | None -> None\n    | Some x -> f x\n  ;;\n#part 12\nlet compute_bounds ~cmp list =\n    let sorted = List.sort ~cmp list in\n    Option.bind (List.hd sorted) (fun first ->\n      Option.bind (List.last sorted) (fun last ->\n        Some (first,last)))\n  ;;\n#part 13\nlet compute_bounds ~cmp list =\n    let open Option.Monad_infix in\n    let sorted = List.sort ~cmp list in\n    List.hd sorted   >>= fun first ->\n    List.last sorted >>= fun last  ->\n    Some (first,last)\n  ;;\n#part 14\nlet compute_bounds ~cmp list =\n    let sorted = List.sort ~cmp list in\n    Option.both (List.hd sorted) (List.last sorted)\n  ;;\n#part 15\n3 / 0;;\n#part 16\nList.map ~f:(fun x -> 100 / x) [1;3;0;4];;\n#part 17\nList.map ~f:(fun x -> printf \"%d\\n%!\" x; 100 / x) [1;3;0;4];;\n#part 18\nexception Key_not_found of string;;\nraise (Key_not_found \"a\");;\n#part 19\nlet exceptions = [ Not_found; Division_by_zero; Key_not_found \"b\" ];;\nList.filter exceptions  ~f:(function\n    | Key_not_found _ | Not_found -> true\n    | _ -> false);;\n#part 20\nlet rec find_exn alist key = match alist with\n    | [] -> raise (Key_not_found key)\n    | (key',data) :: tl -> if key = key' then data else find_exn tl key\n  ;;\nlet alist = [(\"a\",1); (\"b\",2)];;\nfind_exn alist \"a\";;\nfind_exn alist \"c\";;\n#part 21\nraise;;\n#part 22\nlet rec forever () = forever ();;\n#part 23\nexception Wrong_date of Date.t;;\nWrong_date (Date.of_string \"2011-02-23\");;\n#part 24\nexception Wrong_date of Date.t with sexp;;\nWrong_date (Date.of_string \"2011-02-23\");;\n#part 25\nlet failwith msg = raise (Failure msg);;\n#part 26\nlet merge_lists xs ys ~f =\n    if List.length xs <> List.length ys then None\n    else\n      let rec loop xs ys =\n        match xs,ys with\n        | [],[] -> []\n        | x::xs, y::ys -> f x y :: loop xs ys\n        | _ -> assert false\n      in\n      Some (loop xs ys)\n   ;;\nmerge_lists [1;2;3] [-1;1;2] ~f:(+);;\nmerge_lists [1;2;3] [-1;1] ~f:(+);;\n#part 27\nlet merge_lists xs ys ~f =\n    let rec loop xs ys =\n      match xs,ys with\n      | [],[] -> []\n      | x::xs, y::ys -> f x y :: loop xs ys\n      | _ -> assert false\n    in\n    loop xs ys\n  ;;\nmerge_lists [1;2;3] [-1] ~f:(+);;\n#part 28\nlet reminders_of_sexp =\n    <:of_sexp<(Time.t * string) list>>\n  ;;\nlet load_reminders filename =\n    let inc = In_channel.create filename in\n    let reminders = reminders_of_sexp (Sexp.input_sexp inc) in\n    In_channel.close inc;\n    reminders\n  ;;\n#part 29\nlet load_reminders filename =\n    let inc = In_channel.create filename in\n    protect ~f:(fun () -> reminders_of_sexp (Sexp.input_sexp inc))\n      ~finally:(fun () -> In_channel.close inc)\n  ;;\n#part 30\nlet reminders_of_sexp filename =\n    In_channel.with_file filename ~f:(fun inc ->\n      reminders_of_sexp (Sexp.input_sexp inc))\n  ;;\n#part 31\nlet lookup_weight ~compute_weight alist key =\n    try\n      let data = List.Assoc.find_exn alist key in\n      compute_weight data\n    with\n      Not_found -> 0. ;;\n#part 32\nlookup_weight ~compute_weight:(fun _ -> raise Not_found)\n    [\"a\",3; \"b\",4] \"a\" ;;\n#part 33\nlet lookup_weight ~compute_weight alist key =\n    match\n      try Some (List.Assoc.find_exn alist key)\n      with _ -> None\n    with\n    | None -> 0.\n    | Some data -> compute_weight data ;;\n#part 34\nlet lookup_weight ~compute_weight alist key =\n    match List.Assoc.find alist key with\n    | None -> 0.\n    | Some data -> compute_weight data ;;\n#part 35\nlet find alist key =\n    Option.try_with (fun () -> find_exn alist key) ;;\nfind [\"a\",1; \"b\",2] \"c\";;\nfind [\"a\",1; \"b\",2] \"b\";;\n#part 36\nlet find alist key =\n    Or_error.try_with (fun () -> find_exn alist key) ;;\nfind [\"a\",1; \"b\",2] \"c\";;\n#part 37\nOr_error.ok_exn (find [\"a\",1; \"b\",2] \"b\");;\nOr_error.ok_exn (find [\"a\",1; \"b\",2] \"c\");;\n"
  },
  {
    "path": "code/error-handling/result.ml",
    "content": "module Result : sig\n   type ('a,'b) t = | Ok of 'a\n                    | Error of 'b\nend\n"
  },
  {
    "path": "code/error-handling/result.mli",
    "content": "module Result : sig\n   type ('a,'b) t = | Ok of 'a\n                    | Error of 'b\nend\n"
  },
  {
    "path": "code/error-handling/run_exn_cost.sh",
    "content": "corebuild -pkg core_bench exn_cost.native\n./exn_cost.native -ascii cycles\n"
  },
  {
    "path": "code/error-handling/run_exn_cost_notrace.sh",
    "content": "OCAMLRUNPARAM= ./exn_cost.native -ascii cycles\n"
  },
  {
    "path": "code/error-handling/sexpr.scm",
    "content": "(This (is an) (s expression))\n"
  },
  {
    "path": "code/error-handling/try_with.syntax",
    "content": "try <expr> with\n| <pat1> -> <expr1>\n| <pat2> -> <expr2>\n...\n"
  },
  {
    "path": "code/exec_script.sh",
    "content": "#!/usr/bin/env bash\ncd $(dirname $1)\nwhile IFS= read -r line ; do\n  echo \"$ $line\"\n  bash -c \"$line\"\ndone < $(basename $1)\n"
  },
  {
    "path": "code/exec_topscript.sh",
    "content": "#!/usr/bin/env bash\n\ntopscript=`pwd`/../scripts/_build/run_core_toplevel.byte\ncd $(dirname $1)\n$(topscript) $(basename $1)\n"
  },
  {
    "path": "code/fcm/build_query_handler.sh",
    "content": "corebuild query_handler.byte\n"
  },
  {
    "path": "code/fcm/build_query_handler_loader.sh",
    "content": "corebuild query_handler_loader.byte\n"
  },
  {
    "path": "code/fcm/fcm.syntax",
    "content": "(module <Module> : <Module_type>)\n"
  },
  {
    "path": "code/fcm/loader_cli1.rawsh",
    "content": "$ ./query_handler_loader.byte\n>>> (loader known_services)\n(ls unique)\n>>> (loader active_services)\n(loader)\n"
  },
  {
    "path": "code/fcm/loader_cli2.rawsh",
    "content": ">>> (ls .)\nCould not find matching handler: ls\n"
  },
  {
    "path": "code/fcm/loader_cli3.rawsh",
    "content": ">>> (loader (load ls /var))\n()\n>>> (ls /var)\n(agentx at audit backups db empty folders jabberd lib log mail msgs named\n netboot pgsql_socket_alt root rpc run rwho spool tmp vm yp)\n>>> (loader (unload ls))\n()\n>>> (ls /var)\nCould not find matching handler: ls\n"
  },
  {
    "path": "code/fcm/loader_cli4.rawsh",
    "content": ">>> (loader (unload loader))\nIt's unwise to unload yourself\n"
  },
  {
    "path": "code/fcm/main.topscript",
    "content": "module type X_int = sig val x : int end;;\n#part 1\nmodule Three : X_int = struct let x = 3 end;;\nThree.x;;\n#part 2\nlet three = (module Three : X_int);;\n#part 3\nmodule Four = struct let x = 4 end;;\nlet numbers = [ three; (module Four) ];;\n#part 4\nlet numbers = [three; (module struct let x = 4 end)];;\n#part 5\nmodule New_three = (val three : X_int) ;;\nNew_three.x;;\n#part 6\nmodule type Y_int = X_int;;\nlet five = (module struct let x = 5 end : Y_int);;\n[three; five];;\n#part 7\n[three; (module (val five))];;\n#part 8\nlet to_int m =\n    let module M = (val m : X_int) in\n    M.x\n  ;;\nlet plus m1 m2 =\n    (module struct\n       let x = to_int m1 + to_int m2\n     end : X_int)\n  ;;\n#part 9\nlet six = plus three three;;\nto_int (List.fold ~init:six ~f:plus [three;three]);;\n#part 10\nlet to_int (module M : X_int) = M.x ;;\n#part 11\nmodule type Bumpable = sig\n    type t\n    val bump : t -> t\n  end;;\n#part 12\nmodule Int_bumper = struct\n    type t = int\n    let bump n = n + 1\n  end;;\nmodule Float_bumper = struct\n     type t = float\n     let bump n = n +. 1.\n  end;;\n#part 13\nlet int_bumper = (module Int_bumper : Bumpable);;\n#part 14\nlet (module Bumpable) = int_bumper in Bumpable.bump 3;;\n#part 15\nlet int_bumper = (module Int_bumper : Bumpable with type t = int);;\nlet float_bumper = (module Float_bumper : Bumpable with type t = float);;\n#part 16\nlet (module Bumpable) = int_bumper in Bumpable.bump 3;;\nlet (module Bumpable) = float_bumper in Bumpable.bump 3.5;;\n#part 17\nlet bump_list\n       (type a)\n       (module B : Bumpable with type t = a)\n       (l: a list)\n    =\n    List.map ~f:B.bump l\n  ;;\n#part 18\nbump_list int_bumper [1;2;3];;\nbump_list float_bumper [1.5;2.5;3.5];;\n#part 19\nlet wrap_in_list (type a) (x:a) = [x];;\n#part 20\nlet wrap_int_in_list (type a) (x:a) = x + x;;\n#part 21\nmodule type Comparable = sig\n    type t\n    val compare : t -> t -> int\n  end ;;\nlet create_comparable (type a) compare =\n    (module struct\n       type t = a\n       let compare = compare\n     end : Comparable with type t = a)\n  ;;\ncreate_comparable Int.compare;;\ncreate_comparable Float.compare;;\n"
  },
  {
    "path": "code/fcm/pack.syntax",
    "content": "(module <Module> : <Module_type>)\n"
  },
  {
    "path": "code/fcm/query-syntax.scm",
    "content": "(query-name query)\n"
  },
  {
    "path": "code/fcm/query_example.rawscript",
    "content": "$ ./query_handler.byte \n>>> (unique ())\n0\n>>> (unique ())\n1\n>>> (ls .)\n(agentx at audit backups db empty folders jabberd lib log mail msgs named\n netboot pgsql_socket_alt root rpc run rwho spool tmp vm yp)\n>>> (ls vm)\n(sleepimage swapfile0 swapfile1 swapfile2 swapfile3 swapfile4 swapfile5\n swapfile6)\n"
  },
  {
    "path": "code/fcm/query_handler.ml",
    "content": "open Core.Std\nopen Query_handler_core\n\n(* part 1 *)\nlet () =\n  cli (build_dispatch_table [unique_instance; list_dir_instance])\n"
  },
  {
    "path": "code/fcm/query_handler.topscript",
    "content": "module type Query_handler = sig\n\n    (** Configuration for a query handler.  Note that this can be\n        converted to and from an s-expression *)\n    type config with sexp\n\n    (** The name of the query-handling service *)\n    val name : string\n\n    (** The state of the query handler *)\n    type t\n\n    (** Creates a new query handler from a config *)\n    val create : config -> t\n\n    (** Evaluate a given query, where both input and output are\n        s-expressions *)\n    val eval : t -> Sexp.t -> Sexp.t Or_error.t\n  end;;\n#part 1\nmodule type M = sig type t with sexp end;;\n#part 2\ntype u = { a: int; b: float } with sexp;;\nsexp_of_u {a=3;b=7.};;\nu_of_sexp (Sexp.of_string \"((a 43) (b 3.4))\");;\n#part 3\nmodule Unique = struct\n    type config = int with sexp\n    type t = { mutable next_id: int }\n\n    let name = \"unique\"\n    let create start_at = { next_id = start_at }\n\n    let eval t sexp =\n      match Or_error.try_with (fun () -> unit_of_sexp sexp) with\n      | Error _ as err -> err\n      | Ok () ->\n        let response = Ok (Int.sexp_of_t t.next_id) in\n        t.next_id <- t.next_id + 1;\n        response\n  end;;\n#part 4\nlet unique = Unique.create 0;;\nUnique.eval unique Sexp.unit;;\nUnique.eval unique Sexp.unit;;\n#part 5\nmodule List_dir = struct\n    type config = string with sexp\n    type t = { cwd: string }\n\n    (** [is_abs p] Returns true if [p] is an absolute path  *)\n    let is_abs p =\n      String.length p > 0 && p.[0] = '/'\n\n    let name = \"ls\"\n    let create cwd = { cwd }\n\n    let eval t sexp =\n      match Or_error.try_with (fun () -> string_of_sexp sexp) with\n      | Error _ as err -> err\n      | Ok dir ->\n        let dir =\n          if is_abs dir then dir\n          else Filename.concat t.cwd dir\n        in\n        Ok (Array.sexp_of_t String.sexp_of_t (Sys.readdir dir))\n  end;;\n#part 6\nlet list_dir = List_dir.create \"/var\";;\nList_dir.eval list_dir (sexp_of_string \".\");;\nList_dir.eval list_dir (sexp_of_string \"yp\");;\n#part 7\nmodule type Query_handler_instance = sig\n    module Query_handler : Query_handler\n    val this : Query_handler.t\n  end;;\n#part 8\nlet unique_instance =\n    (module struct\n       module Query_handler = Unique\n       let this = Unique.create 0\n     end : Query_handler_instance);;\n#part 9\nlet build_instance\n        (type a)\n        (module Q : Query_handler with type config = a)\n        config\n    =\n    (module struct\n       module Query_handler = Q\n       let this = Q.create config\n     end : Query_handler_instance)\n  ;;\n#part 10\nlet unique_instance = build_instance (module Unique) 0;;\nlet list_dir_instance = build_instance (module List_dir)  \"/var\";;\n#part 11\nlet build_dispatch_table handlers =\n    let table = String.Table.create () in\n    List.iter handlers\n      ~f:(fun ((module I : Query_handler_instance) as instance) ->\n        Hashtbl.replace table ~key:I.Query_handler.name ~data:instance);\n    table\n  ;;\n#part 12\nlet dispatch dispatch_table name_and_query =\n    match name_and_query with\n    | Sexp.List [Sexp.Atom name; query] ->\n      begin match Hashtbl.find dispatch_table name with\n      | None ->\n        Or_error.error \"Could not find matching handler\"\n          name String.sexp_of_t\n      | Some (module I : Query_handler_instance) ->\n        I.Query_handler.eval I.this query\n      end\n    | _ ->\n      Or_error.error_string \"malformed query\"\n  ;;\n#part 13\nlet rec cli dispatch_table =\n    printf \">>> %!\";\n    let result =\n      match In_channel.input_line stdin with\n      | None -> `Stop\n      | Some line ->\n        match Or_error.try_with (fun () -> Sexp.of_string line) with\n        | Error e -> `Continue (Error.to_string_hum e)\n        | Ok (Sexp.Atom \"quit\") -> `Stop\n        | Ok query ->\n          begin match dispatch dispatch_table query with\n          | Error e -> `Continue (Error.to_string_hum e)\n          | Ok s    -> `Continue (Sexp.to_string_hum s)\n          end;\n    in\n    match result with\n    | `Stop -> ()\n    | `Continue msg ->\n      printf \"%s\\n%!\" msg;\n      cli dispatch_table\n  ;;\n#part 14\ntype query_handler_instance = { name : string\n                                ; eval : Sexp.t -> Sexp.t Or_error.t\n                                }\n  type query_handler = Sexp.t -> query_handler_instance\n  ;;\n#part 15\nlet unique_handler config_sexp =\n    let config = Unique.config_of_sexp config_sexp in\n    let unique = Unique.create config in\n    { name = Unique.name\n    ; eval = (fun config -> Unique.eval unique config)\n    }\n  ;;\n"
  },
  {
    "path": "code/fcm/query_handler_core.ml",
    "content": "open Core.Std\n\nmodule type Query_handler = sig\n\n  (** Configuration for a query handler.  Note that this can be\n      converted to and from an s-expression *)\n  type config with sexp\n\n  (** The name of the query-handling service *)\n  val name : string\n\n  (** The state of the query handler *)\n  type t\n\n  (** Create a new query handler from a config *)\n  val create : config -> t\n\n  (** Evaluate a given query, where both input and output are\n      s-expressions *)\n  val eval : t -> Sexp.t -> Sexp.t Or_error.t\nend\n\nmodule Unique = struct\n  type config = int with sexp\n  type t = { mutable next_id: int }\n\n  let name = \"unique\"\n  let create start_at = { next_id = start_at }\n\n  let eval t sexp =\n    match Or_error.try_with (fun () -> unit_of_sexp sexp) with\n    | Error _ as err -> err\n    | Ok () ->\n      let response = Ok (Int.sexp_of_t t.next_id) in\n      t.next_id <- t.next_id + 1;\n      response\nend\n\nmodule List_dir = struct\n  type config = string with sexp\n  type t = { cwd: string }\n\n  (** [is_abs p] Returns true if [p] is an absolute path  *)\n  let is_abs p =\n    String.length p > 0 && p.[0] = '/'\n\n  let name = \"ls\"\n  let create cwd = { cwd }\n\n  let eval t sexp =\n    match Or_error.try_with (fun () -> string_of_sexp sexp) with\n    | Error _ as err -> err\n    | Ok dir ->\n      let dir =\n        if is_abs dir then dir\n        else Filename.concat t.cwd dir\n      in\n      Ok (Array.sexp_of_t String.sexp_of_t (Sys.readdir dir))\nend\n\nmodule type Query_handler_instance = sig\n  module Query_handler : Query_handler\n  val this : Query_handler.t\nend\n\nlet build_instance\n      (type a)\n      (module Q : Query_handler with type config = a)\n      config\n  =\n  (module struct\n     module Query_handler = Q\n     let this = Q.create config\n   end : Query_handler_instance)\n\nlet build_dispatch_table handlers =\n  let table = String.Table.create () in\n  List.iter handlers\n    ~f:(fun ((module I : Query_handler_instance) as instance) ->\n      Hashtbl.replace table ~key:I.Query_handler.name ~data:instance);\n  table\n\nlet dispatch dispatch_table name_and_query =\n  match name_and_query with\n  | Sexp.List [Sexp.Atom name; query] ->\n    begin match Hashtbl.find dispatch_table name with\n    | None ->\n      Or_error.error \"Could not find matching handler\"\n        name String.sexp_of_t\n    | Some (module I : Query_handler_instance) ->\n      I.Query_handler.eval I.this query\n    end\n  | _ ->\n    Or_error.error_string \"malformed query\"\n\nlet rec cli dispatch_table =\n  printf \">>> %!\";\n  let result =\n    match In_channel.input_line stdin with\n    | None -> `Stop\n    | Some line ->\n      match Or_error.try_with (fun () -> Sexp.of_string line) with\n      | Error e -> `Continue (Error.to_string_hum e)\n      | Ok (Sexp.Atom \"quit\") -> `Stop\n      | Ok query ->\n        begin match dispatch dispatch_table query with\n        | Error e -> `Continue (Error.to_string_hum e)\n        | Ok s    -> `Continue (Sexp.to_string_hum s)\n        end;\n  in\n  match result with\n  | `Stop -> ()\n  | `Continue msg ->\n    printf \"%s\\n%!\" msg;\n    cli dispatch_table\n\nlet unique_instance = build_instance (module Unique) 0;;\nlet list_dir_instance = build_instance (module List_dir)  \"/var\";;\n\n(* part 1 *)\nmodule Loader = struct\n  type config = (module Query_handler) list sexp_opaque\n  with sexp\n\n  type t = { known  : (module Query_handler)          String.Table.t\n           ; active : (module Query_handler_instance) String.Table.t\n           }\n\n  let name = \"loader\"\n(* part 2 *)\n  let create known_list =\n    let active = String.Table.create () in\n    let known  = String.Table.create () in\n    List.iter known_list\n      ~f:(fun ((module Q : Query_handler) as q) ->\n        Hashtbl.replace known ~key:Q.name ~data:q);\n    { known; active }\n(* part 3 *)\n  let load t handler_name config =\n    if Hashtbl.mem t.active handler_name then\n      Or_error.error \"Can't re-register an active handler\"\n        handler_name String.sexp_of_t\n    else\n      match Hashtbl.find t.known handler_name with\n      | None ->\n        Or_error.error \"Unknown handler\" handler_name String.sexp_of_t\n      | Some (module Q : Query_handler) ->\n        let instance =\n          (module struct\n             module Query_handler = Q\n             let this = Q.create (Q.config_of_sexp config)\n           end : Query_handler_instance)\n        in\n        Hashtbl.replace t.active ~key:handler_name ~data:instance;\n        Ok Sexp.unit\n(* part 4 *)\n  let unload t handler_name =\n    if not (Hashtbl.mem t.active handler_name) then\n      Or_error.error \"Handler not active\" handler_name String.sexp_of_t\n    else if handler_name = name then\n      Or_error.error_string \"It's unwise to unload yourself\"\n    else (\n      Hashtbl.remove t.active handler_name;\n      Ok Sexp.unit\n    )\n(* part 5 *)\n  type request =\n    | Load of string * Sexp.t\n    | Unload of string\n    | Known_services\n    | Active_services\n  with sexp\n(* part 6 *)\n  let eval t sexp =\n    match Or_error.try_with (fun () -> request_of_sexp sexp) with\n    | Error _ as err -> err\n    | Ok resp ->\n      match resp with\n      | Load (name,config) -> load   t name config\n      | Unload name        -> unload t name\n      | Known_services ->\n        Ok (<:sexp_of<string list>> (Hashtbl.keys t.known))\n      | Active_services ->\n        Ok (<:sexp_of<string list>> (Hashtbl.keys t.active))\nend\n"
  },
  {
    "path": "code/fcm/query_handler_loader.ml",
    "content": "open Core.Std\nopen Query_handler_core\n(* part 1 *)\nlet () =\n  let loader = Loader.create [(module Unique); (module List_dir)] in\n  let loader_instance =\n    (module struct\n       module Query_handler = Loader\n       let this = loader\n     end : Query_handler_instance)\n  in\n  Hashtbl.replace loader.Loader.active\n    ~key:Loader.name ~data:loader_instance;\n  cli loader.Loader.active\n\n"
  },
  {
    "path": "code/fcm/unpack.syntax",
    "content": "(val <first_class_module> : <Module_type>)\n"
  },
  {
    "path": "code/ffi/build_datetime.sh",
    "content": "corebuild -pkg ctypes.foreign datetime.native\n./datetime.native\n./datetime.native -a\n"
  },
  {
    "path": "code/ffi/build_hello.sh",
    "content": "corebuild -pkg ctypes.foreign -lflags -cclib,-lncurses hello.native \n"
  },
  {
    "path": "code/ffi/build_qsort.sh",
    "content": "corebuild -pkg ctypes.foreign qsort.native\ncat input.txt\n./qsort.native < input.txt\ncorebuild -pkg ctypes.foreign qsort.inferred.mli\ncp _build/qsort.inferred.mli qsort.mli\n"
  },
  {
    "path": "code/ffi/datetime.ml",
    "content": "open Core.Std\nopen Ctypes\nopen PosixTypes\nopen Foreign\n\nlet time     = foreign \"time\" (ptr time_t @-> returning time_t)\nlet difftime = foreign \"difftime\" (time_t @-> time_t @-> returning double)\nlet ctime    = foreign \"ctime\" (ptr time_t @-> returning string)\n\ntype timeval\nlet timeval : timeval structure typ = structure \"timeval\"\nlet tv_sec   = timeval *:* long\nlet tv_usec  = timeval *:* long\nlet ()       = seal timeval\n\ntype timezone\nlet timezone : timezone structure typ = structure \"timezone\"\n\nlet gettimeofday = foreign \"gettimeofday\" ~check_errno:true\n    (ptr timeval @-> ptr timezone @-> returning int)\n\nlet time' () = time (from_voidp time_t null)\n\nlet gettimeofday' () =\n  let tv = make timeval in\n  ignore(gettimeofday (addr tv) (from_voidp timezone null));\n  let secs = Signed.Long.(to_int (getf tv tv_sec)) in\n  let usecs = Signed.Long.(to_int (getf tv tv_usec)) in\n  Pervasives.(float secs +. float usecs /. 1_000_000.)\n\nlet float_time () = printf \"%f%!\\n\" (gettimeofday' ())\n\nlet ascii_time () =\n  let t_ptr = allocate time_t (time' ()) in\n  printf \"%s%!\" (ctime t_ptr)\n\nlet () =\n  let open Command in\n  basic ~summary:\"Display the current time in various formats\"\n    Spec.(empty +> flag \"-a\" no_arg ~doc:\" Human-readable output format\")\n    (fun human -> if human then ascii_time else float_time)\n  |> Command.run \n"
  },
  {
    "path": "code/ffi/hello.ml",
    "content": "open Ncurses\n\nlet () =\n  let main_window = initscr () in\n  ignore(cbreak ());\n  let small_window = newwin 10 10 5 5 in\n  mvwaddstr main_window 1 2 \"Hello\";\n  mvwaddstr small_window 2 2 \"World\";\n  box small_window '\\000' '\\000';\n  refresh ();\n  Unix.sleep 1;\n  wrefresh small_window;\n  Unix.sleep 5;\n  endwin ()\n"
  },
  {
    "path": "code/ffi/infer_ncurses.sh",
    "content": "corebuild -pkg ctypes.foreign ncurses.inferred.mli\ncp _build/ncurses.inferred.mli .\n"
  },
  {
    "path": "code/ffi/input.txt",
    "content": "5\n3\n2\n1\n4\n"
  },
  {
    "path": "code/ffi/install.rawsh",
    "content": "$ brew install libffi     # for MacOS X users\n$ opam install ctypes\n$ utop\n# require \"ctypes.foreign\" ;;\n"
  },
  {
    "path": "code/ffi/ncurses.h",
    "content": "typedef struct _win_st WINDOW;\ntypedef unsigned int chtype;\n\nWINDOW *initscr   (void);\nWINDOW *newwin    (int, int, int, int);\nvoid    endwin    (void);\nvoid    refresh   (void);\nvoid    wrefresh  (WINDOW *);\nvoid    addstr (const char *);\nint     mvwaddch  (WINDOW *, int, int, const chtype);\nvoid    mvwaddstr (WINDOW *, int, int, char *);\nvoid    box (WINDOW *, chtype, chtype);\nint     cbreak (void);\n"
  },
  {
    "path": "code/ffi/ncurses.inferred.mli",
    "content": "type window = unit Ctypes.ptr\nval window : window Ctypes.typ\nval initscr : unit -> window\nval endwin : unit -> unit\nval refresh : unit -> unit\nval wrefresh : window -> unit\nval newwin : int -> int -> int -> int -> window\nval mvwaddch : window -> int -> int -> char -> unit\nval addstr : string -> unit\nval mvwaddstr : window -> int -> int -> string -> unit\nval box : window -> int -> int -> unit\nval cbreak : unit -> unit\n"
  },
  {
    "path": "code/ffi/ncurses.ml",
    "content": "open Ctypes\n\ntype window = unit ptr\nlet window : window typ = ptr void\n\n(* part 1 *)\nopen Foreign\n\nlet initscr =\n  foreign \"initscr\" (void @-> returning window)\n\n(* part 2 *)\nlet newwin =\n  foreign \"newwin\" \n    (int @-> int @-> int @-> int @-> returning window)\n\nlet endwin =\n  foreign \"endwin\" (void @-> returning void)\n\nlet refresh =\n  foreign \"refresh\" (void @-> returning void)\n\nlet wrefresh =\n  foreign \"wrefresh\" (window @-> returning void)\n\nlet addstr =\n  foreign \"addstr\" (string @-> returning void)\n\nlet mvwaddch =\n  foreign \"mvwaddch\"\n    (window @-> int @-> int @-> char @-> returning void)\n\nlet mvwaddstr =\n  foreign \"mvwaddstr\"\n    (window @-> int @-> int @-> string @-> returning void)\n\nlet box =\n  foreign \"box\" (window @-> char @-> char @-> returning void)\n\nlet cbreak =\n  foreign \"cbreak\" (void @-> returning int)\n"
  },
  {
    "path": "code/ffi/ncurses.mli",
    "content": "type window\nval window : window Ctypes.typ\nval initscr : unit -> window\nval endwin : unit -> unit\nval refresh : unit -> unit\nval wrefresh : window -> unit\nval newwin : int -> int -> int -> int -> window\nval mvwaddch : window -> int -> int -> char -> unit\nval addstr : string -> unit\nval mvwaddstr : window -> int -> int -> string -> unit\nval box : window -> char -> char -> unit\nval cbreak : unit -> int\n"
  },
  {
    "path": "code/ffi/posix.topscript",
    "content": "#require \"ctypes.foreign\" ;;\n#require \"ctypes.top\" ;;\nopen Ctypes ;;\nopen PosixTypes ;;\nopen Foreign ;;\nlet time = foreign \"time\" (ptr time_t @-> returning time_t) ;;\n#part 1\nlet cur_time = time (from_voidp time_t null) ;;\n#part 2\nlet time' () = time (from_voidp time_t null) ;;\n#part 3\nlet difftime =\n    foreign \"difftime\" (time_t @-> time_t @-> returning double) ;;\nlet t1 =\n    time' () in\n    Unix.sleep 2;\n    let t2 = time' () in \n    difftime t2 t1 ;;\n#part 4\nlet ctime = foreign \"ctime\" (ptr time_t @-> returning string) ;;\n#part 5\nctime (time' ()) ;;\n#part 6\nlet t_ptr = allocate time_t (time' ()) ;;\n#part 7\nctime t_ptr ;;\n#part 8\ntype timeval ;;\nlet timeval : timeval structure typ = structure \"timeval\" ;;\n#part 9\nlet tv_sec  = field timeval \"tv_sec\" long ;;\nlet tv_usec = field timeval \"tv_usec\" long ;;\nseal timeval ;;\n#part 10\ntype timezone ;;\nlet timezone : timezone structure typ = structure \"timezone\" ;;\n#part 11\nlet gettimeofday = foreign \"gettimeofday\"\n    (ptr timeval @-> ptr timezone @-> returning_checking_errno int) ;;\n#part 12\nlet gettimeofday' () =\n  let tv = make timeval in\n  ignore(gettimeofday (addr tv) (from_voidp timezone null));\n  let secs = Signed.Long.(to_int (getf tv tv_sec)) in\n  let usecs = Signed.Long.(to_int (getf tv tv_usec)) in\n  Pervasives.(float secs +. float usecs /. 1000000.0) ;;\ngettimeofday' () ;;\n"
  },
  {
    "path": "code/ffi/posix_headers.h",
    "content": "time_t time(time_t *);\ndouble difftime(time_t, time_t);\nchar *ctime(const time_t *timep);\n"
  },
  {
    "path": "code/ffi/qsort.h",
    "content": "void qsort(void *base, size_t nmemb, size_t size,\n           int(*compar)(const void *, const void *));\n"
  },
  {
    "path": "code/ffi/qsort.ml",
    "content": "open Core.Std\nopen Ctypes\nopen PosixTypes\nopen Foreign\n\nlet compare_t = ptr void @-> ptr void @-> returning int\n\nlet qsort = foreign \"qsort\"\n    (ptr void @-> size_t @-> size_t @-> funptr compare_t @-> \n       returning void)\n\nlet qsort' cmp arr =\n  let open Unsigned.Size_t in\n  let ty = Array.element_type arr in\n  let len = of_int (Array.length arr) in\n  let elsize = of_int (sizeof ty) in\n  let start = to_voidp (Array.start arr) in\n  let compare l r = cmp (!@ (from_voidp ty l)) (!@ (from_voidp ty r)) in\n  qsort start len elsize compare;\n  arr\n\nlet sort_stdin () =\n  In_channel.input_lines stdin\n  |> List.map ~f:int_of_string\n  |> Array.of_list int\n  |> qsort' Int.compare\n  |> Array.to_list\n  |> List.iter ~f:(fun a -> printf \"%d\\n\" a)\n\nlet () =\n  Command.basic ~summary:\"Sort integers on standard input\"\n    Command.Spec.empty sort_stdin\n  |> Command.run\n"
  },
  {
    "path": "code/ffi/qsort.mli",
    "content": "val compare_t : (unit Ctypes.ptr -> unit Ctypes.ptr -> int) Ctypes.fn\nval qsort :\n  unit Ctypes.ptr ->\n  PosixTypes.size_t ->\n  PosixTypes.size_t -> (unit Ctypes.ptr -> unit Ctypes.ptr -> int) -> unit\nval qsort' : ('a -> 'a -> int) -> 'a Ctypes.array -> 'a Ctypes.array\nval sort_stdin : unit -> unit\n"
  },
  {
    "path": "code/ffi/qsort.topscript",
    "content": "#require \"ctypes.foreign\" ;;\nopen Ctypes ;;\nopen PosixTypes ;;\nopen Foreign ;;\nlet compare_t = ptr void @-> ptr void @-> returning int ;;\nlet qsort = foreign \"qsort\"\n   (ptr void @-> size_t @-> size_t @->\n    funptr compare_t @-> returning void) ;;\n"
  },
  {
    "path": "code/ffi/qsort_typedef.h",
    "content": "typedef int(compare_t)(const void *, const void *);\n\nvoid qsort(void *base, size_t nmemb, size_t size, compare_t *);\n"
  },
  {
    "path": "code/ffi/return_c_frag.c",
    "content": "uncurried_C(3, 4);\n"
  },
  {
    "path": "code/ffi/return_c_frag.h",
    "content": "int uncurried_C(int, int);\n"
  },
  {
    "path": "code/ffi/return_c_uncurried.c",
    "content": "/* A function that accepts an int, and returns a function\n   pointer that accepts a second int and returns an int. */\ntypedef int (function_t)(int);\nfunction_t *curried_C(int);\n\n/* supply both arguments */\ncurried_C(3)(4);\n\n/* supply one argument at a time */\nfunction_t *f = curried_C(3); f(4);\n"
  },
  {
    "path": "code/ffi/return_frag.ml",
    "content": "(* correct types *)\nval time: ptr time_t @-> returning time_t\nval difftime: time_t @-> time_t @-> returning double\n(* part 1 *)\n(* incorrect types *)\nval time: ptr time_t @-> time_t\nval difftime: time_t @-> time_t @-> double\n(* part 2 *)\nval curried : int -> int -> int\n(* part 3 *)\nval curried : int -> (int -> int)\n"
  },
  {
    "path": "code/ffi/timeval_headers.h",
    "content": "struct timeval {\n  long tv_sec;\n  long tv_usec;\n};\n\nint gettimeofday(struct timeval *, struct timezone *tv);\n"
  },
  {
    "path": "code/files-modules-and-programs/abstract_username.ml",
    "content": "open Core.Std\n\nmodule Username : sig\n  type t\n  val of_string : string -> t\n  val to_string : t -> string\nend = struct\n  type t = string\n  let of_string x = x\n  let to_string x = x\nend\n"
  },
  {
    "path": "code/files-modules-and-programs/build_session_info.errsh",
    "content": "corebuild session_info.native\n"
  },
  {
    "path": "code/files-modules-and-programs/common.ml",
    "content": "module List = Ext_list\n"
  },
  {
    "path": "code/files-modules-and-programs/confusing_username_and_host.ml",
    "content": "open Core.Std\n\nmodule type ID = sig\n  type t\n  val of_string : string -> t\n  val to_string : t -> string\nend\n\nmodule String_id = struct\n  type t = string\n  let of_string x = x\n  let to_string x = x\nend\n\nmodule Username : ID = String_id\nmodule Hostname : ID = String_id\n\ntype session_info = { user: Username.t;\n                      host: Hostname.t;\n                      when_started: Time.t;\n                    }\n\nlet sessions_have_same_user s1 s2 =\n  s1.user = s2.host\n"
  },
  {
    "path": "code/files-modules-and-programs/ext_list.ml",
    "content": "open Core.Std\n\n(* The new function we're going to add *)\nlet rec intersperse list el =\n  match list with\n  | [] | [ _ ]   -> list\n  | x :: y :: tl -> x :: el :: intersperse (y::tl) el\n\n(* The remainder of the list module *)\ninclude List\n"
  },
  {
    "path": "code/files-modules-and-programs/ext_list.mli",
    "content": "open Core.Std\n\n(* Include the interface of the list module from Core *)\ninclude (module type of List)\n\n(* Signature of function we're adding *)\nval intersperse : 'a list -> 'a -> 'a list\n"
  },
  {
    "path": "code/files-modules-and-programs/freq.ml",
    "content": "open Core.Std\n\nlet build_counts () =\n  In_channel.fold_lines stdin ~init:[] ~f:(fun counts line ->\n    let count =\n      match List.Assoc.find counts line with\n      | None -> 0\n      | Some x -> x\n    in\n    List.Assoc.add counts line (count + 1)\n  )\n\nlet () =\n  build_counts ()\n  |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y)\n  |> (fun l -> List.take l 10)\n  |> List.iter ~f:(fun (line,count) -> printf \"%3d: %s\\n\" count line)\n"
  },
  {
    "path": "code/files-modules-and-programs/intro.topscript",
    "content": "let assoc = [(\"one\", 1); (\"two\",2); (\"three\",3)] ;;\nList.Assoc.find assoc \"two\" ;;\nList.Assoc.add assoc \"four\" 4 (* add a new key *) ;;\nList.Assoc.add assoc \"two\"  4 (* overwrite an existing key *) ;;\n"
  },
  {
    "path": "code/files-modules-and-programs/main.topscript",
    "content": "module M = struct let foo = 3 end;;\nfoo;;\nopen M;;\nfoo;;\n#part 1\nlet average x y =\n    let open Int64 in\n    x + y / of_int 2;;\n#part 2\nlet average x y =\n    Int64.(x + y / of_int 2);;\n#part 3\nmodule Interval = struct\n    type t = | Interval of int * int\n             | Empty\n\n    let create low high =\n      if high < low then Empty else Interval (low,high)\n  end;;\n#part 4\nmodule Extended_interval = struct\n    include Interval\n\n    let contains t x =\n      match t with\n      | Empty -> false\n      | Interval (low,high) -> x >= low && x <= high\n  end;;\nExtended_interval.contains (Extended_interval.create 3 10) 4;;\n#part 5\nmodule Extended_interval = struct\n    open Interval\n\n    let contains t x =\n      match t with\n      | Empty -> false\n      | Interval (low,high) -> x >= low && x <= high\n  end;;\nExtended_interval.contains (Extended_interval.create 3 10) 4;;\n"
  },
  {
    "path": "code/files-modules-and-programs/module.syntax",
    "content": "module <name> : <signature> = <implementation>\n"
  },
  {
    "path": "code/files-modules-and-programs/session_info.ml",
    "content": "open Core.Std\n\nmodule type ID = sig\n  type t\n  val of_string : string -> t\n  val to_string : t -> string\nend\n\nmodule String_id = struct\n  type t = string\n  let of_string x = x\n  let to_string x = x\nend\n\nmodule Username : ID = String_id\nmodule Hostname : ID = String_id\n\ntype session_info = { user: Username.t;\n                      host: Hostname.t;\n                      when_started: Time.t;\n                    }\n\nlet sessions_have_same_user s1 s2 =\n  s1.user = s2.host\n"
  },
  {
    "path": "code/files-modules-and-programs/val.syntax",
    "content": "val <identifier> : <type>\n"
  },
  {
    "path": "code/files-modules-and-programs-freq/freq.ml",
    "content": "open Core.Std\n\nlet build_counts () =\n  In_channel.fold_lines stdin ~init:[] ~f:(fun counts line ->\n    let count =\n      match List.Assoc.find counts line with\n      | None -> 0\n      | Some x -> x\n    in\n    List.Assoc.add counts line (count + 1)\n  )\n\nlet () =\n  build_counts ()\n  |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y)\n  |> (fun l -> List.take l 10)\n  |> List.iter ~f:(fun (line,count) -> printf \"%3d: %s\\n\" count line)\n"
  },
  {
    "path": "code/files-modules-and-programs-freq/simple_build.sh",
    "content": "ocamlfind ocamlc -linkpkg -thread -package core freq.ml -o freq.byte\n"
  },
  {
    "path": "code/files-modules-and-programs-freq/simple_build_fail.errsh",
    "content": "ocamlc freq.ml -o freq.byte\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-cyclic1/build.errsh",
    "content": "corebuild freq.byte\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-cyclic1/counter.ml",
    "content": "open Core.Std\n\ntype t = int String.Map.t\n\nlet empty = String.Map.empty\n\nlet to_list t = Map.to_alist t\n\nlet touch t s =\n  let count =\n    match Map.find t s with\n    | None -> 0\n    | Some x -> x\n  in\n  Map.add t ~key:s ~data:(count + 1)\n\n(* part 1 *)\nlet singleton l = Counter.touch Counter.empty\n\n(* part 2 *)\ntype median = | Median of string\n              | Before_and_after of string * string\n\nlet median t =\n  let sorted_strings = List.sort (Map.to_alist t)\n                         ~cmp:(fun (_,x) (_,y) -> Int.descending x y)\n  in\n  let len = List.length sorted_strings in\n  if len = 0 then failwith \"median: empty frequency count\";\n  let nth n = fst (List.nth_exn sorted_strings n) in\n  if len mod 2 = 1\n  then Median (nth (len/2))\n  else Before_and_after (nth (len/2 - 1), nth (len/2));;\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-cyclic1/counter.mli",
    "content": "open Core.Std\n\n(** A collection of string frequency counts *)\ntype t\n\n(** The empty set of frequency counts  *)\nval empty : t\n\n(** Bump the frequency count for the given string. *)\nval touch : t -> string -> t\n\n(* Converts the set of frequency counts to an association list.  Every strings\n   in the list will show up at most once, and the integers will be at least\n   1. *)\nval to_list : t -> (string * int) list\n\n(** Represents the median computed from a set of strings.  In the case where\n    there is an even number of choices, the one before and after the median is\n    returned.  *)\ntype median = | Median of string\n              | Before_and_after of string * string\n\nval median : t -> median\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-cyclic1/freq.ml",
    "content": "open Core.Std\n\nlet build_counts () =\n  In_channel.fold_lines stdin ~init:Counter.empty ~f:Counter.touch\n\nlet () =\n  build_counts ()\n  |> Counter.to_list\n  |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y)\n  |> (fun counts -> List.take counts 10)\n  |> List.iter ~f:(fun (line,count) -> printf \"%3d: %s\\n\" count line)\n\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-cyclic2/build.errsh",
    "content": "corebuild freq.byte\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-cyclic2/counter.ml",
    "content": "open Core.Std\n\ntype t = int String.Map.t\n\nlet empty = String.Map.empty\n\nlet to_list t = Map.to_alist t\n\nlet touch t s =\n  let count =\n    match Map.find t s with\n    | None -> 0\n    | Some x -> x\n  in\n  Map.add t ~key:s ~data:(count + 1)\n\n(* part 1 *)\nlet _build_counts = Freq.build_counts\n\n(* part 2 *)\ntype median = | Median of string\n              | Before_and_after of string * string\n\nlet median t =\n  let sorted_strings = List.sort (Map.to_alist t)\n                         ~cmp:(fun (_,x) (_,y) -> Int.descending x y)\n  in\n  let len = List.length sorted_strings in\n  if len = 0 then failwith \"median: empty frequency count\";\n  let nth n = fst (List.nth_exn sorted_strings n) in\n  if len mod 2 = 1\n  then Median (nth (len/2))\n  else Before_and_after (nth (len/2 - 1), nth (len/2));;\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-cyclic2/counter.mli",
    "content": "open Core.Std\n\n(** A collection of string frequency counts *)\ntype t\n\n(** The empty set of frequency counts  *)\nval empty : t\n\n(** Bump the frequency count for the given string. *)\nval touch : t -> string -> t\n\n(* Converts the set of frequency counts to an association list.  Every strings\n   in the list will show up at most once, and the integers will be at least\n   1. *)\nval to_list : t -> (string * int) list\n\n(** Represents the median computed from a set of strings.  In the case where\n    there is an even number of choices, the one before and after the median is\n    returned.  *)\ntype median = | Median of string\n              | Before_and_after of string * string\n\nval median : t -> median\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-cyclic2/freq.ml",
    "content": "open Core.Std\n\nlet build_counts () =\n  In_channel.fold_lines stdin ~init:Counter.empty ~f:Counter.touch\n\nlet () =\n  build_counts ()\n  |> Counter.to_list\n  |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y)\n  |> (fun counts -> List.take counts 10)\n  |> List.iter ~f:(fun (line,count) -> printf \"%3d: %s\\n\" count line)\n\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-fast/build.sh",
    "content": "corebuild freq.byte\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-fast/counter.ml",
    "content": "open Core.Std\n\ntype t = int String.Map.t\n\nlet empty = String.Map.empty\n\nlet to_list t = Map.to_alist t\n\nlet touch t s =\n  let count =\n    match Map.find t s with\n    | None -> 0\n    | Some x -> x\n  in\n  Map.add t ~key:s ~data:(count + 1)\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-fast/counter.mli",
    "content": "open Core.Std\n\n(** A collection of string frequency counts *)\ntype t\n\n(** The empty set of frequency counts  *)\nval empty : t\n\n(** Bump the frequency count for the given string. *)\nval touch : t -> string -> t\n\n(* Converts the set of frequency counts to an association list.  Every strings\n   in the list will show up at most once, and the integers will be at least\n   1. *)\nval to_list : t -> (string * int) list\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-fast/freq.ml",
    "content": "open Core.Std\n\nlet build_counts () =\n  In_channel.fold_lines stdin ~init:Counter.empty ~f:Counter.touch\n\nlet () =\n  build_counts ()\n  |> Counter.to_list\n  |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y)\n  |> (fun counts -> List.take counts 10)\n  |> List.iter ~f:(fun (line,count) -> printf \"%3d: %s\\n\" count line)\n\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-median/build.sh",
    "content": "corebuild freq.byte\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-median/build_use_median.sh",
    "content": "../corebuild use_median_1.native\n../corebuild use_median_2.native\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-median/counter.ml",
    "content": "open Core.Std\n\ntype t = int String.Map.t\n\nlet empty = String.Map.empty\n\nlet to_list t = Map.to_alist t\n\nlet touch t s =\n  let count =\n    match Map.find t s with\n    | None -> 0\n    | Some x -> x\n  in\n  Map.add t ~key:s ~data:(count + 1)\n\n(* part 1 *)\ntype median = | Median of string\n              | Before_and_after of string * string\n\nlet median t =\n  let sorted_strings = List.sort (Map.to_alist t)\n                         ~cmp:(fun (_,x) (_,y) -> Int.descending x y)\n  in\n  let len = List.length sorted_strings in\n  if len = 0 then failwith \"median: empty frequency count\";\n  let nth n = fst (List.nth_exn sorted_strings n) in\n  if len mod 2 = 1\n  then Median (nth (len/2))\n  else Before_and_after (nth (len/2 - 1), nth (len/2));;\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-median/counter.mli",
    "content": "open Core.Std\n\n(** A collection of string frequency counts *)\ntype t\n\n(** The empty set of frequency counts  *)\nval empty : t\n\n(** Bump the frequency count for the given string. *)\nval touch : t -> string -> t\n\n(* Converts the set of frequency counts to an association list.  Every strings\n   in the list will show up at most once, and the integers will be at least\n   1. *)\nval to_list : t -> (string * int) list\n\n(* part 1 *)\n(** Represents the median computed from a set of strings.  In the case where\n    there is an even number of choices, the one before and after the median is\n    returned.  *)\ntype median = | Median of string\n              | Before_and_after of string * string\n\nval median : t -> median\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-median/freq.ml",
    "content": "open Core.Std\n\nlet build_counts () =\n  In_channel.fold_lines stdin ~init:Counter.empty ~f:Counter.touch\n\nlet () =\n  build_counts ()\n  |> Counter.to_list\n  |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y)\n  |> (fun counts -> List.take counts 10)\n  |> List.iter ~f:(fun (line,count) -> printf \"%3d: %s\\n\" count line)\n\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-median/use_median_1.ml",
    "content": "open Core.Std\n\n(* part 1 *)\nlet print_median m =\n  match m with\n  | Counter.Median string -> printf \"True median:\\n   %s\\n\" string\n  | Counter.Before_and_after (before, after) ->\n    printf \"Before and after median:\\n   %s\\n   %s\\n\" before after\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-median/use_median_2.ml",
    "content": "open Core.Std\n\n(* part 1 *)\nlet print_median m =\n  let module C = Counter in\n  match m with\n  | C.Median string -> printf \"True median:\\n   %s\\n\" string\n  | C.Before_and_after (before, after) ->\n    printf \"Before and after median:\\n   %s\\n   %s\\n\" before after\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-obuild/build.sh",
    "content": "corebuild freq.byte\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-obuild/test.sh",
    "content": "strings `which ocamlopt` | ./freq.byte\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-counter/build.sh",
    "content": "corebuild freq.byte\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-counter/counter.ml",
    "content": "open Core.Std\n\nlet touch t s =\n  let count =\n    match List.Assoc.find t s with\n    | None -> 0\n    | Some x -> x\n  in\n  List.Assoc.add t s (count + 1)\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-counter/freq.ml",
    "content": "open Core.Std\n\nlet build_counts () =\n  In_channel.fold_lines stdin ~init:[] ~f:Counter.touch\n\nlet () =\n  build_counts ()\n  |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y)\n  |> (fun l -> List.take l 10)\n  |> List.iter ~f:(fun (line,count) -> printf \"%3d: %s\\n\" count line)\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-counter/infer_mli.sh",
    "content": "corebuild counter.inferred.mli\ncat _build/counter.inferred.mli\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-missing-def/build.errsh",
    "content": "corebuild freq.byte\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-missing-def/counter.ml",
    "content": "open Core.Std\n\ntype t = int String.Map.t\n\nlet empty = String.Map.empty\n\nlet to_list t = Map.to_alist t\n\nlet touch t s =\n  let count =\n    match Map.find t s with\n    | None -> 0\n    | Some x -> x\n  in\n  Map.add t ~key:s ~data:(count + 1)\n\n(* part 1 *)\ntype median = | Median of string\n              | Before_and_after of string * string\n\nlet median t =\n  let sorted_strings = List.sort (Map.to_alist t)\n                         ~cmp:(fun (_,x) (_,y) -> Int.descending x y)\n  in\n  let len = List.length sorted_strings in\n  if len = 0 then failwith \"median: empty frequency count\";\n  let nth n = fst (List.nth_exn sorted_strings n) in\n  if len mod 2 = 1\n  then Median (nth (len/2))\n  else Before_and_after (nth (len/2 - 1), nth (len/2));;\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-missing-def/counter.mli",
    "content": "open Core.Std\n\n(** A collection of string frequency counts *)\ntype t\n\n(** The empty set of frequency counts  *)\nval empty : t\n\n(** Bump the frequency count for the given string. *)\nval touch : t -> string -> t\n\n(* Converts the set of frequency counts to an association list.  Every strings\n   in the list will show up at most once, and the integers will be at least\n   1. *)\nval to_list : t -> (string * int) list\n\n(* part 1 *)\nval count : t -> string -> int\n\n(* part 2 *)\n(** Represents the median computed from a set of strings.  In the case where\n    there is an even number of choices, the one before and after the median is\n    returned.  *)\ntype median = | Median of string\n              | Before_and_after of string * string\n\nval median : t -> median\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-missing-def/freq.ml",
    "content": "open Core.Std\n\nlet build_counts () =\n  In_channel.fold_lines stdin ~init:Counter.empty ~f:Counter.touch\n\nlet () =\n  build_counts ()\n  |> Counter.to_list\n  |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y)\n  |> (fun counts -> List.take counts 10)\n  |> List.iter ~f:(fun (line,count) -> printf \"%3d: %s\\n\" count line)\n\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-sig/build.sh",
    "content": "corebuild freq.byte\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-sig/counter.ml",
    "content": "open Core.Std\n\nlet touch t s =\n  let count =\n    match List.Assoc.find t s with\n    | None -> 0\n    | Some x -> x\n  in\n  List.Assoc.add t s (count + 1)\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-sig/counter.mli",
    "content": "open Core.Std\n\n(** Bump the frequency count for the given string. *)\nval touch : (string * int) list -> string -> (string * int) list\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-sig/freq.ml",
    "content": "open Core.Std\n\nlet build_counts () =\n  In_channel.fold_lines stdin ~init:[] ~f:Counter.touch\n\nlet () =\n  build_counts ()\n  |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y)\n  |> (fun l -> List.take l 10)\n  |> List.iter ~f:(fun (line,count) -> printf \"%3d: %s\\n\" count line)\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-sig-abstract/build.errsh",
    "content": "corebuild freq.byte\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-sig-abstract/counter.ml",
    "content": "open Core.Std\n\ntype t = (string * int) list\n\nlet empty = []\n\nlet to_list x = x\n\nlet touch t s =\n  let count =\n    match List.Assoc.find t s with\n    | None -> 0\n    | Some x -> x\n  in\n  List.Assoc.add t s (count + 1)\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-sig-abstract/counter.mli",
    "content": "open Core.Std\n\n(** A collection of string frequency counts *)\ntype t\n\n(** The empty set of frequency counts  *)\nval empty : t\n\n(** Bump the frequency count for the given string. *)\nval touch : t -> string -> t\n\n(** Converts the set of frequency counts to an association list.  A string shows\n    up at most once, and the counts are >= 1. *)\nval to_list : t -> (string * int) list\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-sig-abstract/freq.ml",
    "content": "open Core.Std\n\nlet build_counts () =\n  In_channel.fold_lines stdin ~init:[] ~f:Counter.touch\n\nlet () =\n  build_counts ()\n  |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y)\n  |> (fun l -> List.take l 10)\n  |> List.iter ~f:(fun (line,count) -> printf \"%3d: %s\\n\" count line)\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-sig-abstract-fixed/build.sh",
    "content": "corebuild freq.byte\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-sig-abstract-fixed/counter.ml",
    "content": "open Core.Std\n\ntype t = (string * int) list\n\nlet empty = []\n\nlet to_list x = x\n\nlet touch t s =\n  let count =\n    match List.Assoc.find t s with\n    | None -> 0\n    | Some x -> x\n  in\n  List.Assoc.add t s (count + 1)\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-sig-abstract-fixed/counter.mli",
    "content": "open Core.Std\n\n(** A collection of string frequency counts *)\ntype t\n\n(** The empty set of frequency counts  *)\nval empty : t\n\n(** Bump the frequency count for the given string. *)\nval touch : t -> string -> t\n\n(* Converts the set of frequency counts to an association list.  Every strings\n   in the list will show up at most once, and the integers will be at least\n   1. *)\nval to_list : t -> (string * int) list\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-sig-abstract-fixed/freq.ml",
    "content": "open Core.Std\n\nlet build_counts () =\n  In_channel.fold_lines stdin ~init:Counter.empty ~f:Counter.touch\n\nlet () =\n  build_counts ()\n  |> Counter.to_list\n  |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y)\n  |> (fun counts -> List.take counts 10)\n  |> List.iter ~f:(fun (line,count) -> printf \"%3d: %s\\n\" count line)\n\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-sig-mismatch/build.errsh",
    "content": "corebuild freq.byte\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-sig-mismatch/counter.ml",
    "content": "open Core.Std\n\ntype t = int String.Map.t\n\nlet empty = String.Map.empty\n\nlet to_list t = Map.to_alist t\n\nlet touch t s =\n  let count =\n    match Map.find t s with\n    | None -> 0\n    | Some x -> x\n  in\n  Map.add t ~key:s ~data:(count + 1)\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-sig-mismatch/counter.mli",
    "content": "open Core.Std\n\n(** A collection of string frequency counts *)\ntype t\n\n(** The empty set of frequency counts  *)\nval empty : t\n\n(* part 1 *)\n(** Bump the frequency count for the given string. *)\nval touch : string -> t -> t\n(* part 2 *)\n\n(* Converts the set of frequency counts to an association list.  Every strings\n   in the list will show up at most once, and the integers will be at least\n   1. *)\nval to_list : t -> (string * int) list\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-sig-mismatch/freq.ml",
    "content": "open Core.Std\n\nlet build_counts () =\n  In_channel.fold_lines stdin ~init:Counter.empty ~f:Counter.touch\n\nlet () =\n  build_counts ()\n  |> Counter.to_list\n  |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y)\n  |> (fun counts -> List.take counts 10)\n  |> List.iter ~f:(fun (line,count) -> printf \"%3d: %s\\n\" count line)\n\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-type-mismatch/build.errsh",
    "content": "corebuild freq.byte\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-type-mismatch/counter.ml",
    "content": "open Core.Std\n\ntype t = int String.Map.t\n\nlet empty = String.Map.empty\n\nlet to_list t = Map.to_alist t\n\nlet touch t s =\n  let count =\n    match Map.find t s with\n    | None -> 0\n    | Some x -> x\n  in\n  Map.add t ~key:s ~data:(count + 1)\n\n(* part 1 *)\ntype median = | Median of string\n              | Before_and_after of string * string\n\nlet median t =\n  let sorted_strings = List.sort (Map.to_alist t)\n                         ~cmp:(fun (_,x) (_,y) -> Int.descending x y)\n  in\n  let len = List.length sorted_strings in\n  if len = 0 then failwith \"median: empty frequency count\";\n  let nth n = fst (List.nth_exn sorted_strings n) in\n  if len mod 2 = 1\n  then Median (nth (len/2))\n  else Before_and_after (nth (len/2 - 1), nth (len/2));;\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-type-mismatch/counter.mli",
    "content": "open Core.Std\n\n(** A collection of string frequency counts *)\ntype t\n\n(** The empty set of frequency counts  *)\nval empty : t\n\n(** Bump the frequency count for the given string. *)\nval touch : t -> string -> t\n\n(* Converts the set of frequency counts to an association list.  Every strings\n   in the list will show up at most once, and the integers will be at least\n   1. *)\nval to_list : t -> (string * int) list\n\n(* part 1 *)\n(** Represents the median computed from a set of strings.  In the case where\n    there is an even number of choices, the one before and after the median is\n    returned.  *)\ntype median = | Before_and_after of string * string\n              | Median of string\n(* part 2 *)\nval median : t -> median\n"
  },
  {
    "path": "code/files-modules-and-programs-freq-with-type-mismatch/freq.ml",
    "content": "open Core.Std\n\nlet build_counts () =\n  In_channel.fold_lines stdin ~init:Counter.empty ~f:Counter.touch\n\nlet () =\n  build_counts ()\n  |> Counter.to_list\n  |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y)\n  |> (fun counts -> List.take counts 10)\n  |> List.iter ~f:(fun (line,count) -> printf \"%3d: %s\\n\" count line)\n\n"
  },
  {
    "path": "code/front-end/alice.ml",
    "content": "let friends = [ Bob.name ]\n"
  },
  {
    "path": "code/front-end/alice.mli",
    "content": "val friends : Bob.t list\n"
  },
  {
    "path": "code/front-end/alice_combined.ml",
    "content": "module Alice : sig\n  val friends : Bob.t list\nend = struct\n  let friends = [ Bob.name ]\nend\n"
  },
  {
    "path": "code/front-end/broken_module.ml",
    "content": "let () =\n  module MyString = String;\n  ()\n"
  },
  {
    "path": "code/front-end/broken_poly.ml",
    "content": "let rec algebra =\n  function\n  | `Add (x,y) -> (algebra x) + (algebra y)\n  | `Sub (x,y) -> (algebra x) - (algebra y)\n  | `Mul (x,y) -> (algebra x) * (algebra y)\n  | `Num x     -> x\n\nlet _ =\n  algebra (\n    `Add (\n      (`Num 0),\n      (`Sub (\n          (`Num 1),\n          (`Mul (\n              (`Nu 3),(`Num 2)\n            ))\n        ))\n    ))\n"
  },
  {
    "path": "code/front-end/broken_poly_with_annot.ml",
    "content": "type t = [\n  | `Add of t * t\n  | `Sub of t * t\n  | `Mul of t * t\n  | `Num of int\n]\n\nlet rec algebra (x:t) =\n  match x with\n  | `Add (x,y) -> (algebra x) + (algebra y)\n  | `Sub (x,y) -> (algebra x) - (algebra y)\n  | `Mul (x,y) -> (algebra x) * (algebra y)\n  | `Num x     -> x\n\nlet _ =\n  algebra (\n    `Add (\n      (`Num 0),\n      (`Sub (\n          (`Num 1),\n          (`Mul (\n              (`Nu 3),(`Num 2)\n            ))\n        ))\n    ))\n"
  },
  {
    "path": "code/front-end/build_broken_module.errsh",
    "content": "ocamlc -c broken_module.ml\n"
  },
  {
    "path": "code/front-end/build_broken_poly.errsh",
    "content": "ocamlc -c broken_poly.ml\n"
  },
  {
    "path": "code/front-end/build_broken_poly_with_annot.errsh",
    "content": "ocamlc -i broken_poly_with_annot.ml\n"
  },
  {
    "path": "code/front-end/build_follow_on_function.errsh",
    "content": "ocamlc -c follow_on_function.ml\n"
  },
  {
    "path": "code/front-end/build_non_principal.sh",
    "content": "ocamlc -i -principal non_principal.ml\n"
  },
  {
    "path": "code/front-end/build_ocamldoc.rawsh",
    "content": "$ mkdir -p html man/man3\n$ ocamldoc -html -d html doc.ml\n$ ocamldoc -man -d man/man3 doc.ml\n$ man -M man Doc\n"
  },
  {
    "path": "code/front-end/build_principal.sh",
    "content": "ocamlc -i -principal principal.ml\n"
  },
  {
    "path": "code/front-end/build_type_conv_with_camlp4.rawsh",
    "content": "$ ocamlfind ocamlc -c -syntax camlp4o -package sexplib.syntax \\\n    -package fieldslib.syntax type_conv_example.ml\n"
  },
  {
    "path": "code/front-end/build_type_conv_without_camlp4.errsh",
    "content": "ocamlfind ocamlc -c type_conv_example.ml\n"
  },
  {
    "path": "code/front-end/camlp4_dump.cmd",
    "content": "#!/bin/sh\n\nOCAMLFIND=\"ocamlfind query -predicates syntax,preprocessor -r\"\nINCLUDE=`$OCAMLFIND -i-format comparelib.syntax`\nARCHIVES=`$OCAMLFIND -a-format comparelib.syntax`\ncamlp4o -printer o $INCLUDE $ARCHIVES $1\n"
  },
  {
    "path": "code/front-end/camlp4_toplevel.topscript",
    "content": "#use \"topfind\" ;;\n#camlp4o ;;\n#part 1\n#require \"comparelib.syntax\" ;;\ntype t = { foo: string; bar : t } ;;\ntype t = { foo: string; bar: t } with compare ;;\n"
  },
  {
    "path": "code/front-end/comparelib_test.ml",
    "content": "type t = { \n  foo: string; \n  bar: t\n} with compare\n"
  },
  {
    "path": "code/front-end/comparelib_test.mli",
    "content": "type t = { \n  foo: string; \n  bar: t\n} with compare\n"
  },
  {
    "path": "code/front-end/conflicting_interfaces.errsh",
    "content": "echo type t = Foo > test.ml\necho type t = Bar > test.mli\nocamlc -c test.mli test.ml\n"
  },
  {
    "path": "code/front-end/doc.ml",
    "content": "(** example.ml: The first special comment of the file is the comment \n    associated with the whole module. *)\n\n(** Comment for exception My_exception. *)\nexception My_exception of (int -> int) * int\n\n(** Comment for type [weather]  *)\ntype weather =\n  | Rain of int (** The comment for construtor Rain *)\n  | Sun         (** The comment for constructor Sun *)\n\n(** Find the current weather for a country\n    @author Anil Madhavapeddy\n    @param location The country to get the weather for.\n*)\nlet what_is_the_weather_in location =\n  match location with\n  | `Cambridge  -> Rain 100\n  | `New_york   -> Rain 20\n  | `California -> Sun\n"
  },
  {
    "path": "code/front-end/fixed_module.ml",
    "content": "let () =\n  let module MyString = String in\n  ()\n"
  },
  {
    "path": "code/front-end/follow_on_function.ml",
    "content": "let concat_and_print x y =\n  let v = x ^ y in\n  print_endline v;\n  v;\n\nlet add_and_print x y =\n  let v = x + y in\n  print_endline (string_of_int v);\n  v\n\nlet () =\n  let _x = add_and_print 1 2 in\n  let _y = concat_and_print \"a\" \"b\" in\n  ()\n"
  },
  {
    "path": "code/front-end/follow_on_function_fixed.ml",
    "content": "let concat_and_print x y =\n  let v = x ^ y in\n  print_endline v;\n  v\n\nlet add_and_print x y =\n  let v = x + y in\n  print_endline (string_of_int v);\n  v\n\nlet () =\n  let _x = add_and_print 1 2 in\n  let _y = concat_and_print \"a\" \"b\" in\n  ()\n"
  },
  {
    "path": "code/front-end/html/Doc.html",
    "content": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n<meta content=\"text/html; charset=iso-8859-1\" http-equiv=\"Content-Type\">\n<link rel=\"Start\" href=\"index.html\">\n<link rel=\"Up\" href=\"index.html\">\n<link title=\"Index of types\" rel=Appendix href=\"index_types.html\">\n<link title=\"Index of exceptions\" rel=Appendix href=\"index_exceptions.html\">\n<link title=\"Index of values\" rel=Appendix href=\"index_values.html\">\n<link title=\"Index of modules\" rel=Appendix href=\"index_modules.html\">\n<link title=\"Doc\" rel=\"Chapter\" href=\"Doc.html\"><title>Doc</title>\n</head>\n<body>\n<div class=\"navbar\">&nbsp;<a class=\"up\" href=\"index.html\" title=\"Index\">Up</a>\n&nbsp;</div>\n<h1>Module <a href=\"type_Doc.html\">Doc</a></h1>\n<pre><span class=\"keyword\">module</span> Doc: <code class=\"code\">sig</code> <a href=\"Doc.html\">..</a> <code class=\"code\">end</code></pre><div class=\"info\">\nexample.ml: The first special comment of the file is the comment \n    associated with the whole module.<br>\n</div>\n<hr width=\"100%\">\n<pre><span id=\"EXCEPTIONMy_exception\"><span class=\"keyword\">exception</span> My_exception</span> <span class=\"keyword\">of</span> <code class=\"type\">(int -> int) * int</code></pre>\n<div class=\"info\">\nComment for exception My_exception.<br>\n</div>\n<pre><code><span id=\"TYPEweather\"><span class=\"keyword\">type</span> <code class=\"type\"></code>weather</span> = </code></pre><table class=\"typetable\">\n<tr>\n<td align=\"left\" valign=\"top\" >\n<code><span class=\"keyword\">|</span></code></td>\n<td align=\"left\" valign=\"top\" >\n<code><span id=\"TYPEELTweather.Rain\"><span class=\"constructor\">Rain</span></span> <span class=\"keyword\">of</span> <code class=\"type\">int</code></code></td>\n<td class=\"typefieldcomment\" align=\"left\" valign=\"top\" ><code>(*</code></td><td class=\"typefieldcomment\" align=\"left\" valign=\"top\" >The comment for construtor Rain</td><td class=\"typefieldcomment\" align=\"left\" valign=\"bottom\" ><code>*)</code></td>\n</tr>\n<tr>\n<td align=\"left\" valign=\"top\" >\n<code><span class=\"keyword\">|</span></code></td>\n<td align=\"left\" valign=\"top\" >\n<code><span id=\"TYPEELTweather.Sun\"><span class=\"constructor\">Sun</span></span></code></td>\n<td class=\"typefieldcomment\" align=\"left\" valign=\"top\" ><code>(*</code></td><td class=\"typefieldcomment\" align=\"left\" valign=\"top\" >The comment for constructor Sun</td><td class=\"typefieldcomment\" align=\"left\" valign=\"bottom\" ><code>*)</code></td>\n</tr></table>\n\n<div class=\"info\">\nComment for type <code class=\"code\">weather</code><br>\n</div>\n\n<pre><span id=\"VALwhat_is_the_weather_in\"><span class=\"keyword\">val</span> what_is_the_weather_in</span> : <code class=\"type\">[< `California | `Cambridge | `New_york ] -> <a href=\"Doc.html#TYPEweather\">weather</a></code></pre><div class=\"info\">\nFind the current weather for a country<br>\n<b>Author(s):</b> Anil Madhavapeddy<br>\n</div>\n<div class=\"param_info\"><code class=\"code\">location</code> : The country to get the weather for.</div>\n</body></html>"
  },
  {
    "path": "code/front-end/html/index.html",
    "content": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n<meta content=\"text/html; charset=iso-8859-1\" http-equiv=\"Content-Type\">\n<link rel=\"Start\" href=\"index.html\">\n<link title=\"Index of types\" rel=Appendix href=\"index_types.html\">\n<link title=\"Index of exceptions\" rel=Appendix href=\"index_exceptions.html\">\n<link title=\"Index of values\" rel=Appendix href=\"index_values.html\">\n<link title=\"Index of modules\" rel=Appendix href=\"index_modules.html\">\n<link title=\"Doc\" rel=\"Chapter\" href=\"Doc.html\"><title></title>\n</head>\n<body>\n<h1></h1>\n<ul class=\"indexlist\">\n<li><a href=\"index_types.html\">Index of types</a></li>\n<li><a href=\"index_exceptions.html\">Index of exceptions</a></li>\n<li><a href=\"index_values.html\">Index of values</a></li>\n<li><a href=\"index_modules.html\">Index of modules</a></li>\n</ul>\n<br/><br>\n<table class=\"indextable\">\n<tr><td class=\"module\"><a href=\"Doc.html\">Doc</a></td><td><div class=\"info\">\nexample.ml: The first special comment of the file is the comment \n    associated with the whole module.\n</div>\n</td></tr>\n</table>\n</body>\n</html>"
  },
  {
    "path": "code/front-end/html/index_attributes.html",
    "content": "<html>\n<head>\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n<meta content=\"text/html; charset=iso-8859-1\" http-equiv=\"Content-Type\">\n<link rel=\"Start\" href=\"index.html\">\n<link title=\"Index of types\" rel=Appendix href=\"index_types.html\">\n<link title=\"Index of exceptions\" rel=Appendix href=\"index_exceptions.html\">\n<link title=\"Index of values\" rel=Appendix href=\"index_values.html\">\n<link title=\"Index of modules\" rel=Appendix href=\"index_modules.html\">\n<link title=\"Doc\" rel=\"Chapter\" href=\"Doc.html\"><title>Index of class attributes</title>\n</head>\n<body>\n<div class=\"navbar\">&nbsp;<a class=\"up\" href=\"index.html\" title=\"Index\">Up</a>\n&nbsp;</div>\n<h1>Index of class attributes</h1>\n<table>\n</table>\n</body>\n</html>"
  },
  {
    "path": "code/front-end/html/index_class_types.html",
    "content": "<html>\n<head>\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n<meta content=\"text/html; charset=iso-8859-1\" http-equiv=\"Content-Type\">\n<link rel=\"Start\" href=\"index.html\">\n<link title=\"Index of types\" rel=Appendix href=\"index_types.html\">\n<link title=\"Index of exceptions\" rel=Appendix href=\"index_exceptions.html\">\n<link title=\"Index of values\" rel=Appendix href=\"index_values.html\">\n<link title=\"Index of modules\" rel=Appendix href=\"index_modules.html\">\n<link title=\"Doc\" rel=\"Chapter\" href=\"Doc.html\"><title>Index of class types</title>\n</head>\n<body>\n<div class=\"navbar\">&nbsp;<a class=\"up\" href=\"index.html\" title=\"Index\">Up</a>\n&nbsp;</div>\n<h1>Index of class types</h1>\n<table>\n</table>\n</body>\n</html>"
  },
  {
    "path": "code/front-end/html/index_classes.html",
    "content": "<html>\n<head>\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n<meta content=\"text/html; charset=iso-8859-1\" http-equiv=\"Content-Type\">\n<link rel=\"Start\" href=\"index.html\">\n<link title=\"Index of types\" rel=Appendix href=\"index_types.html\">\n<link title=\"Index of exceptions\" rel=Appendix href=\"index_exceptions.html\">\n<link title=\"Index of values\" rel=Appendix href=\"index_values.html\">\n<link title=\"Index of modules\" rel=Appendix href=\"index_modules.html\">\n<link title=\"Doc\" rel=\"Chapter\" href=\"Doc.html\"><title>Index of classes</title>\n</head>\n<body>\n<div class=\"navbar\">&nbsp;<a class=\"up\" href=\"index.html\" title=\"Index\">Up</a>\n&nbsp;</div>\n<h1>Index of classes</h1>\n<table>\n</table>\n</body>\n</html>"
  },
  {
    "path": "code/front-end/html/index_exceptions.html",
    "content": "<html>\n<head>\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n<meta content=\"text/html; charset=iso-8859-1\" http-equiv=\"Content-Type\">\n<link rel=\"Start\" href=\"index.html\">\n<link title=\"Index of types\" rel=Appendix href=\"index_types.html\">\n<link title=\"Index of exceptions\" rel=Appendix href=\"index_exceptions.html\">\n<link title=\"Index of values\" rel=Appendix href=\"index_values.html\">\n<link title=\"Index of modules\" rel=Appendix href=\"index_modules.html\">\n<link title=\"Doc\" rel=\"Chapter\" href=\"Doc.html\"><title>Index of exceptions</title>\n</head>\n<body>\n<div class=\"navbar\">&nbsp;<a class=\"up\" href=\"index.html\" title=\"Index\">Up</a>\n&nbsp;</div>\n<h1>Index of exceptions</h1>\n<table>\n<tr><td align=\"left\"><br>M</td></tr>\n<tr><td><a href=\"Doc.html#EXCEPTIONMy_exception\">My_exception</a> [<a href=\"Doc.html\">Doc</a>]</td>\n<td><div class=\"info\">\nComment for exception My_exception.\n</div>\n</td></tr>\n</table>\n</body>\n</html>"
  },
  {
    "path": "code/front-end/html/index_methods.html",
    "content": "<html>\n<head>\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n<meta content=\"text/html; charset=iso-8859-1\" http-equiv=\"Content-Type\">\n<link rel=\"Start\" href=\"index.html\">\n<link title=\"Index of types\" rel=Appendix href=\"index_types.html\">\n<link title=\"Index of exceptions\" rel=Appendix href=\"index_exceptions.html\">\n<link title=\"Index of values\" rel=Appendix href=\"index_values.html\">\n<link title=\"Index of modules\" rel=Appendix href=\"index_modules.html\">\n<link title=\"Doc\" rel=\"Chapter\" href=\"Doc.html\"><title>Index of class methods</title>\n</head>\n<body>\n<div class=\"navbar\">&nbsp;<a class=\"up\" href=\"index.html\" title=\"Index\">Up</a>\n&nbsp;</div>\n<h1>Index of class methods</h1>\n<table>\n</table>\n</body>\n</html>"
  },
  {
    "path": "code/front-end/html/index_module_types.html",
    "content": "<html>\n<head>\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n<meta content=\"text/html; charset=iso-8859-1\" http-equiv=\"Content-Type\">\n<link rel=\"Start\" href=\"index.html\">\n<link title=\"Index of types\" rel=Appendix href=\"index_types.html\">\n<link title=\"Index of exceptions\" rel=Appendix href=\"index_exceptions.html\">\n<link title=\"Index of values\" rel=Appendix href=\"index_values.html\">\n<link title=\"Index of modules\" rel=Appendix href=\"index_modules.html\">\n<link title=\"Doc\" rel=\"Chapter\" href=\"Doc.html\"><title>Index of module types</title>\n</head>\n<body>\n<div class=\"navbar\">&nbsp;<a class=\"up\" href=\"index.html\" title=\"Index\">Up</a>\n&nbsp;</div>\n<h1>Index of module types</h1>\n<table>\n</table>\n</body>\n</html>"
  },
  {
    "path": "code/front-end/html/index_modules.html",
    "content": "<html>\n<head>\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n<meta content=\"text/html; charset=iso-8859-1\" http-equiv=\"Content-Type\">\n<link rel=\"Start\" href=\"index.html\">\n<link title=\"Index of types\" rel=Appendix href=\"index_types.html\">\n<link title=\"Index of exceptions\" rel=Appendix href=\"index_exceptions.html\">\n<link title=\"Index of values\" rel=Appendix href=\"index_values.html\">\n<link title=\"Index of modules\" rel=Appendix href=\"index_modules.html\">\n<link title=\"Doc\" rel=\"Chapter\" href=\"Doc.html\"><title>Index of modules</title>\n</head>\n<body>\n<div class=\"navbar\">&nbsp;<a class=\"up\" href=\"index.html\" title=\"Index\">Up</a>\n&nbsp;</div>\n<h1>Index of modules</h1>\n<table>\n<tr><td align=\"left\"><br>D</td></tr>\n<tr><td><a href=\"Doc.html\">Doc</a> </td>\n<td><div class=\"info\">\nexample.ml: The first special comment of the file is the comment \n    associated with the whole module.\n</div>\n</td></tr>\n</table>\n</body>\n</html>"
  },
  {
    "path": "code/front-end/html/index_types.html",
    "content": "<html>\n<head>\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n<meta content=\"text/html; charset=iso-8859-1\" http-equiv=\"Content-Type\">\n<link rel=\"Start\" href=\"index.html\">\n<link title=\"Index of types\" rel=Appendix href=\"index_types.html\">\n<link title=\"Index of exceptions\" rel=Appendix href=\"index_exceptions.html\">\n<link title=\"Index of values\" rel=Appendix href=\"index_values.html\">\n<link title=\"Index of modules\" rel=Appendix href=\"index_modules.html\">\n<link title=\"Doc\" rel=\"Chapter\" href=\"Doc.html\"><title>Index of types</title>\n</head>\n<body>\n<div class=\"navbar\">&nbsp;<a class=\"up\" href=\"index.html\" title=\"Index\">Up</a>\n&nbsp;</div>\n<h1>Index of types</h1>\n<table>\n<tr><td align=\"left\"><br>W</td></tr>\n<tr><td><a href=\"Doc.html#TYPEweather\">weather</a> [<a href=\"Doc.html\">Doc</a>]</td>\n<td><div class=\"info\">\nComment for type <code class=\"code\">weather</code>\n</div>\n</td></tr>\n</table>\n</body>\n</html>"
  },
  {
    "path": "code/front-end/html/index_values.html",
    "content": "<html>\n<head>\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n<meta content=\"text/html; charset=iso-8859-1\" http-equiv=\"Content-Type\">\n<link rel=\"Start\" href=\"index.html\">\n<link title=\"Index of types\" rel=Appendix href=\"index_types.html\">\n<link title=\"Index of exceptions\" rel=Appendix href=\"index_exceptions.html\">\n<link title=\"Index of values\" rel=Appendix href=\"index_values.html\">\n<link title=\"Index of modules\" rel=Appendix href=\"index_modules.html\">\n<link title=\"Doc\" rel=\"Chapter\" href=\"Doc.html\"><title>Index of values</title>\n</head>\n<body>\n<div class=\"navbar\">&nbsp;<a class=\"up\" href=\"index.html\" title=\"Index\">Up</a>\n&nbsp;</div>\n<h1>Index of values</h1>\n<table>\n<tr><td align=\"left\"><br>W</td></tr>\n<tr><td><a href=\"Doc.html#VALwhat_is_the_weather_in\">what_is_the_weather_in</a> [<a href=\"Doc.html\">Doc</a>]</td>\n<td><div class=\"info\">\nFind the current weather for a country\n</div>\n</td></tr>\n</table>\n</body>\n</html>"
  },
  {
    "path": "code/front-end/html/style.css",
    "content": ".keyword { font-weight : bold ; color : Red }\n.keywordsign { color : #C04600 }\n.superscript { font-size : 4 }\n.subscript { font-size : 4 }\n.comment { color : Green }\n.constructor { color : Blue }\n.type { color : #5C6585 }\n.string { color : Maroon }\n.warning { color : Red ; font-weight : bold }\n.info { margin-left : 3em; margin-right: 3em }\n.param_info { margin-top: 4px; margin-left : 3em; margin-right : 3em }\n.code { color : #465F91 ; }\n.typetable { border-style : hidden }\n.paramstable { border-style : hidden ; padding: 5pt 5pt}\ntr { background-color : White }\ntd.typefieldcomment { background-color : #FFFFFF ; font-size: smaller ;}\ndiv.sig_block {margin-left: 2em}\n*:target { background: yellow; }\nbody {font: 13px sans-serif; color: black; text-align: left; padding: 5px; margin: 0}\nh1 { font-size : 20pt ; text-align: center; }\nh2 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90BDFF ;padding: 2px; }\nh3 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90DDFF ;padding: 2px; }\nh4 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90EDFF ;padding: 2px; }\nh5 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90FDFF ;padding: 2px; }\nh6 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90BDFF ; padding: 2px; }\ndiv.h7 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #E0FFFF ; padding: 2px; }\ndiv.h8 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #F0FFFF ; padding: 2px; }\ndiv.h9 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #FFFFFF ; padding: 2px; }\na {color: #416DFF; text-decoration: none}\na:hover {background-color: #ddd; text-decoration: underline}\npre { margin-bottom: 4px; font-family: monospace; }\npre.verbatim, pre.codepre { }\n.indextable {border: 1px #ddd solid; border-collapse: collapse}\n.indextable td, .indextable th {border: 1px #ddd solid; min-width: 80px}\n.indextable td.module {background-color: #eee ;  padding-left: 2px; padding-right: 2px}\n.indextable td.module a {color: 4E6272; text-decoration: none; display: block; width: 100%}\n.indextable td.module a:hover {text-decoration: underline; background-color: transparent}\n.deprecated {color: #888; font-style: italic}\n.indextable tr td div.info { margin-left: 2px; margin-right: 2px }\nul.indexlist { margin-left: 0; padding-left: 0;}\nul.indexlist li { list-style-type: none ; margin-left: 0; padding-left: 0; }"
  },
  {
    "path": "code/front-end/html/type_Doc.html",
    "content": "<html><head>\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n<meta content=\"text/html; charset=iso-8859-1\" http-equiv=\"Content-Type\">\n<link rel=\"Start\" href=\"index.html\">\n<link title=\"Index of types\" rel=Appendix href=\"index_types.html\">\n<link title=\"Index of exceptions\" rel=Appendix href=\"index_exceptions.html\">\n<link title=\"Index of values\" rel=Appendix href=\"index_values.html\">\n<link title=\"Index of modules\" rel=Appendix href=\"index_modules.html\">\n<link title=\"Doc\" rel=\"Chapter\" href=\"Doc.html\"><title>Doc</title>\n</head>\n<body>\n<code class=\"code\"><span class=\"keyword\">sig</span>&nbsp;&nbsp;<span class=\"keyword\">end</span></code></body></html>"
  },
  {
    "path": "code/front-end/inconsistent_compilation_units.rawsh",
    "content": "$ ocamlc -c foo.ml\nFile \"foo.ml\", line 1, characters 0-1:\nError: The files /home/build/bar.cmi\n       and /usr/lib/ocaml/map.cmi make inconsistent assumptions\n       over interface Map\n"
  },
  {
    "path": "code/front-end/indent_follow_on_function.sh",
    "content": "ocp-indent follow_on_function.ml\n"
  },
  {
    "path": "code/front-end/indent_follow_on_function_fixed.sh",
    "content": "ocp-indent follow_on_function_fixed.ml\n"
  },
  {
    "path": "code/front-end/infer_typedef.sh",
    "content": "ocamlc -i typedef.ml\n"
  },
  {
    "path": "code/front-end/install_ocp_index.rawsh",
    "content": "$ opam install ocp-index\n$ ocp-index\n"
  },
  {
    "path": "code/front-end/let_notunit.ml",
    "content": "let (_:some_type) = <expr>\nlet () = ignore (<expr> : some_type)\n)(* if the expression returns a unit Deferred.t *)\nlet () = don't_wait_for (<expr>\n"
  },
  {
    "path": "code/front-end/let_unit.syntax",
    "content": "let () = <expr>\n"
  },
  {
    "path": "code/front-end/man/man3/Doc.3o",
    "content": ".TH \"Doc\" 3 2013-07-23 OCamldoc \"\"\n.SH NAME\nDoc \\- example.ml: The first special comment of the file is the comment associated with the whole module.\n.SH Module\nModule   Doc\n.SH Documentation\n.sp\nModule\n.BI \"Doc\"\n : \n.B sig  end\n\n.sp\nexample\\&.ml: The first special comment of the file is the comment \nassociated with the whole module\\&.\n.sp\n\n.sp\n\n.sp\n.sp\n\n.I exception My_exception \n.B of \n.B (int -> int) * int\n\n.sp\nComment for exception My_exception\\&.\n.sp\n\n.sp\n.I type weather \n=\n | Rain\n.B of \n.B int\n.I \"  \"\n(* The comment for construtor Rain *)\n | Sun  (* The comment for constructor Sun *)\n \n.sp\nComment for type \n.B weather\n\n.sp\n\n.sp\n\n.I val what_is_the_weather_in \n: \n.B [< `California | `Cambridge | `New_york ] -> weather\n.sp\nFind the current weather for a country\n.sp\n.B \"Author(s)\"\n:\nAnil Madhavapeddy\n.sp\n\n.sp\n"
  },
  {
    "path": "code/front-end/man/man3/My_exception.3o",
    "content": ".TH \"My_exception\" 3 2013-07-23 OCamldoc \"\"\n.SH NAME\nMy_exception \\- all My_exception elements\n\n\n.SH Module Doc\n\n.I exception My_exception \n.B of \n.B (int -> int) * int\n\n.sp\nComment for exception My_exception\\&.\n.sp\n\n.sp\n"
  },
  {
    "path": "code/front-end/man/man3/Rain.3o",
    "content": ".TH \"Rain\" 3 2013-07-23 OCamldoc \"\"\n.SH NAME\nRain \\- all Rain elements\n\n"
  },
  {
    "path": "code/front-end/man/man3/Sun.3o",
    "content": ".TH \"Sun\" 3 2013-07-23 OCamldoc \"\"\n.SH NAME\nSun \\- all Sun elements\n\n"
  },
  {
    "path": "code/front-end/man/man3/weather.3o",
    "content": ".TH \"weather\" 3 2013-07-23 OCamldoc \"\"\n.SH NAME\nweather \\- all weather elements\n\n\n.SH Module Doc\n.I type weather \n=\n | Rain\n.B of \n.B int\n.I \"  \"\n(* The comment for construtor Rain *)\n | Sun  (* The comment for constructor Sun *)\n \n.sp\nComment for type \n.B weather\n\n.sp\n\n.sp\n"
  },
  {
    "path": "code/front-end/man/man3/what_is_the_weather_in.3o",
    "content": ".TH \"what_is_the_weather_in\" 3 2013-07-23 OCamldoc \"\"\n.SH NAME\nwhat_is_the_weather_in \\- all what_is_the_weather_in elements\n\n\n.SH Module Doc\n\n.I val what_is_the_weather_in \n: \n.B [< `California | `Cambridge | `New_york ] -> weather\n.sp\nFind the current weather for a country\n.sp\n.B \"Author(s)\"\n:\nAnil Madhavapeddy\n.sp\n\n.sp\n"
  },
  {
    "path": "code/front-end/non_principal.ml",
    "content": "type s = { foo: int; bar: unit }\ntype t = { foo: int }\n\nlet f x =\n  x.bar;\n  x.foo\n"
  },
  {
    "path": "code/front-end/parsetree_typedef.sh",
    "content": "ocamlc -dparsetree typedef.ml 2>&1\n"
  },
  {
    "path": "code/front-end/pipeline.ascii",
    "content": "    Source code\n        |\n        | parsing and preprocessing\n        |\n        | camlp4 syntax extensions\n        |\n        v\n    Parsetree (untyped AST)\n        |\n        | type inference and checking\n        v\n    Typedtree (type-annotated AST)\n        |\n        | pattern-matching compilation\n        | elimination of modules and classes\n        v\n     Lambda\n      /   \\\n     /     \\ closure conversion, inlining, uncurrying,\n    v       \\  data representation strategy\n Bytecode    \\\n    |         +-----+\n    |              Cmm\n    |ocamlrun       |\n    |               | code generation\n    |               | assembly & linking\n    v               v\n Interpreted    Compiled\n"
  },
  {
    "path": "code/front-end/principal.ml",
    "content": "type s = { foo: int; bar: unit }\ntype t = { foo: int }\n\nlet f (x:s) =\n  x.bar;\n  x.foo\n"
  },
  {
    "path": "code/front-end/process_comparelib_interface.sh",
    "content": "sh camlp4_dump.cmd comparelib_test.mli\n"
  },
  {
    "path": "code/front-end/process_comparelib_test.sh",
    "content": "sh camlp4_dump.cmd comparelib_test.ml\n"
  },
  {
    "path": "code/front-end/short_paths_1.rawsh",
    "content": "$ ocaml\n# List.map print_endline \"\" ;;\nError: This expression has type string but an expression was expected of type\n         string list\n"
  },
  {
    "path": "code/front-end/short_paths_2.rawsh",
    "content": "$ ocaml\n# open Core.Std ;;\n# List.map ~f:print_endline \"\" ;;\nError: This expression has type string but an expression was expected of type\n         'a Core.Std.List.t = 'a list\n"
  },
  {
    "path": "code/front-end/short_paths_3.rawsh",
    "content": "$ ocaml -short-paths\n# open Core.Std;;\n# List.map ~f:print_endline \"foo\";;\nError: This expression has type string but an expression was expected of type\n         'a list\n"
  },
  {
    "path": "code/front-end/test.ml",
    "content": "type t = Foo\n"
  },
  {
    "path": "code/front-end/test.mli",
    "content": "type t = Bar\n"
  },
  {
    "path": "code/front-end/type_conv_example.ml",
    "content": "open Sexplib.Std\n\ntype t = {\n  foo: int;\n  bar: string\n} with sexp, fields\n"
  },
  {
    "path": "code/front-end/typedef.ml",
    "content": "type t = Foo | Bar\nlet v = Foo\n"
  },
  {
    "path": "code/front-end/typedef_objinfo.sh",
    "content": "ocamlc -c typedef.ml\nocamlobjinfo typedef.cmi\n"
  },
  {
    "path": "code/front-end/typedtree_typedef.sh",
    "content": "ocamlc -dtypedtree typedef.ml 2>&1\n"
  },
  {
    "path": "code/front-end/unused_var.ml",
    "content": "let fn x y =\n  let _z = x + y in\n  ()\n"
  },
  {
    "path": "code/front-end/xbuild_type_conv_with_camlp4.sh",
    "content": "ocamlfind ocamlc -c -syntax camlp4o -package sexplib.syntax -package fieldslib.syntax type_conv_example.ml\n"
  },
  {
    "path": "code/functors/build_extended_fqueue.sh",
    "content": "corebuild extended_fqueue.cmo\n"
  },
  {
    "path": "code/functors/build_fqueue.sh",
    "content": "corebuild fqueue.cmo\n"
  },
  {
    "path": "code/functors/compare_example.ml",
    "content": "compare x y < 0     (* x < y *)\ncompare x y = 0     (* x = y *)\ncompare x y > 0     (* x > y *)\n"
  },
  {
    "path": "code/functors/destructive_sub.syntax",
    "content": "<Module_type> with type <type> := <type'>\n"
  },
  {
    "path": "code/functors/extended_fqueue.ml",
    "content": "include Fqueue\ninclude Foldable.Extend(Fqueue)\n"
  },
  {
    "path": "code/functors/extended_fqueue.mli",
    "content": "type 'a t\ninclude (module type of Fqueue) with type 'a t := 'a t\ninclude Foldable.Extension with type 'a t := 'a t\n"
  },
  {
    "path": "code/functors/foldable.ml",
    "content": "open Core.Std\n\nmodule type S = sig\n  type 'a t\n  val fold : 'a t -> init:'acc -> f:('acc -> 'a -> 'acc) -> 'acc\nend\n\nmodule type Extension = sig\n  type 'a t\n  val iter    : 'a t -> f:('a -> unit) -> unit\n  val length  : 'a t -> int\n  val count   : 'a t -> f:('a -> bool) -> int\n  val for_all : 'a t -> f:('a -> bool) -> bool\n  val exists  : 'a t -> f:('a -> bool) -> bool\nend\n\n(* For extending a Foldable module *)\nmodule Extend(Arg : S)\n  : (Extension with type 'a t := 'a Arg.t) =\nstruct\n  open Arg\n\n  let iter t ~f =\n    fold t ~init:() ~f:(fun () a -> f a)\n\n  let length t =\n    fold t ~init:0  ~f:(fun acc _ -> acc + 1)\n\n  let count t ~f =\n    fold t ~init:0  ~f:(fun count x -> count + if f x then 1 else 0)\n\n  exception Short_circuit\n\n  let for_all c ~f =\n    try iter c ~f:(fun x -> if not (f x) then raise Short_circuit); true\n    with Short_circuit -> false\n\n  let exists c ~f =\n    try iter c ~f:(fun x -> if f x then raise Short_circuit); false\n    with Short_circuit -> true\nend\n"
  },
  {
    "path": "code/functors/fqueue.ml",
    "content": "open Core.Std\n\ntype 'a t = 'a list * 'a list\n\nlet empty = ([],[])\n\nlet enqueue (in_list, out_list) x =\n  (x :: in_list,out_list)\n\nlet dequeue (in_list, out_list) =\n  match out_list with\n  | hd :: tl -> Some (hd, (in_list, tl))\n  | [] ->\n    match List.rev in_list with\n    | [] -> None\n    | hd :: tl -> Some (hd, ([], tl))\n\nlet fold (in_list, out_list) ~init ~f =\n  let after_out = List.fold ~init ~f out_list in\n  List.fold_right ~init:after_out ~f:(fun x acc -> f acc x) in_list\n"
  },
  {
    "path": "code/functors/fqueue.mli",
    "content": "type 'a t\n\nval empty : 'a t\n\n(** [enqueue el q] adds [el] to the back of [q] *)\nval enqueue : 'a t -> 'a -> 'a t\n\n(** [dequeue q] returns None if the [q] is empty, otherwise returns\n    the first element of the queue and the remainder of the queue *)\nval dequeue : 'a t -> ('a * 'a t) option\n\n(** Folds over the queue, from front to back *)\nval fold : 'a t -> init:'acc -> f:('acc -> 'a -> 'acc) -> 'acc\n"
  },
  {
    "path": "code/functors/main-15.rawscript",
    "content": "# module Make_interval(Endpoint : Comparable) : Interval_intf = struct\n    type endpoint = Endpoint.t\n    type t = | Interval of Endpoint.t * Endpoint.t\n             | Empty\n\n    ...\n\n  end ;;\n  module Make_interval : functor (Endpoint : Comparable) -> Interval_intf\n"
  },
  {
    "path": "code/functors/main-18.rawscript",
    "content": "# module Make_interval(Endpoint : Comparable)\n      : (Interval_intf with type endpoint = Endpoint.t)\n  = struct\n\n    type endpoint = Endpoint.t\n    type t = | Interval of Endpoint.t * Endpoint.t\n             | Empty\n\n    ...\n\n  end ;;\nmodule Make_interval :\n  functor (Endpoint : Comparable) ->\n    sig\n      type t\n      type endpoint = Endpoint.t\n      val create : endpoint -> endpoint -> t\n      val is_empty : t -> bool\n      val contains : t -> endpoint -> bool\n      val intersect : t -> t -> t\n    end\n"
  },
  {
    "path": "code/functors/main-21.rawscript",
    "content": "# module Make_interval(Endpoint : Comparable)\n    : Interval_intf with type endpoint := Endpoint.t =\n  struct\n\n    type t = | Interval of Endpoint.t * Endpoint.t\n             | Empty\n\n    ...\n\n  end ;;\n  module Make_interval :\n    functor (Endpoint : Comparable) ->\n    sig\n      type t\n      val create : Endpoint.t -> Endpoint.t -> t\n      val is_empty : t -> bool\n      val contains : t -> Endpoint.t -> bool\n      val intersect : t -> t -> t\n    end\n"
  },
  {
    "path": "code/functors/main-25.rawscript",
    "content": "# module Make_interval(Endpoint : Comparable)\n    : (Interval_intf with type endpoint := Endpoint.t) = struct\n\n    type t = | Interval of Endpoint.t * Endpoint.t\n             | Empty\n    with sexp\n\n    ...\n\n  end ;;\n  Characters 136-146:\n    Error: Unbound value Endpoint.t_of_sexp\n"
  },
  {
    "path": "code/functors/main.topscript",
    "content": "module type X_int = sig val x : int end;;\n#part 1\nmodule Increment (M : X_int) : X_int = struct\n    let x = M.x + 1\n  end;;\n#part 2\nmodule Increment (M : X_int) = struct\n    let x = M.x + 1\n  end;;\n#part 3\nmodule Three = struct let x = 3 end;;\nmodule Four = Increment(Three);;\nFour.x - Three.x;;\n#part 4\nmodule Three_and_more = struct\n    let x = 3\n    let y = \"three\"\n  end;;\nmodule Four = Increment(Three_and_more);;\n#part 5\nmodule type Comparable = sig\n    type t\n    val compare : t -> t -> int\n  end ;;\n#part 6\nmodule Make_interval(Endpoint : Comparable) = struct\n\n    type t = | Interval of Endpoint.t * Endpoint.t\n             | Empty\n\n    (** [create low high] creates a new interval from [low] to\n        [high].  If [low > high], then the interval is empty *)\n    let create low high =\n      if Endpoint.compare low high > 0 then Empty\n      else Interval (low,high)\n\n    (** Returns true iff the interval is empty *)\n    let is_empty = function\n      | Empty -> true\n      | Interval _ -> false\n\n    (** [contains t x] returns true iff [x] is contained in the\n        interval [t] *)\n    let contains t x =\n      match t with\n      | Empty -> false\n      | Interval (l,h) ->\n        Endpoint.compare x l >= 0 && Endpoint.compare x h <= 0\n\n    (** [intersect t1 t2] returns the intersection of the two input\n        intervals *)\n    let intersect t1 t2 =\n      let min x y = if Endpoint.compare x y <= 0 then x else y in\n      let max x y = if Endpoint.compare x y >= 0 then x else y in\n      match t1,t2 with\n      | Empty, _ | _, Empty -> Empty\n      | Interval (l1,h1), Interval (l2,h2) ->\n        create (max l1 l2) (min h1 h2)\n\n  end ;;\n#part 7\nmodule Int_interval =\n    Make_interval(struct\n      type t = int\n      let compare = Int.compare\n    end);;\n#part 8\nmodule Int_interval = Make_interval(Int) ;;\nmodule String_interval = Make_interval(String) ;;\n#part 9\nlet i1 = Int_interval.create 3 8;;\nlet i2 = Int_interval.create 4 10;;\nInt_interval.intersect i1 i2;;\n#part 10\nmodule Rev_int_interval =\n    Make_interval(struct\n      type t = int\n      let compare x y = Int.compare y x\n    end);;\n#part 11\nlet interval = Int_interval.create 4 3;;\nlet rev_interval = Rev_int_interval.create 4 3;;\n#part 12\nInt_interval.contains rev_interval 3;;\n#part 13\nInt_interval.is_empty (* going through create *)\n    (Int_interval.create 4 3) ;;\nInt_interval.is_empty (* bypassing create *)\n    (Int_interval.Interval (4,3)) ;;\n#part 14\nmodule type Interval_intf = sig\n   type t\n   type endpoint\n   val create : endpoint -> endpoint -> t\n   val is_empty : t -> bool\n   val contains : t -> endpoint -> bool\n   val intersect : t -> t -> t\n  end;;\n#part 15\nmodule Make_interval(Endpoint : Comparable) : Interval_intf = struct\n\n    type endpoint = Endpoint.t\n    type t = | Interval of Endpoint.t * Endpoint.t\n             | Empty\n\n    (** [create low high] creates a new interval from [low] to\n        [high].  If [low > high], then the interval is empty *)\n    let create low high =\n      if Endpoint.compare low high > 0 then Empty\n      else Interval (low,high)\n\n    (** Returns true iff the interval is empty *)\n    let is_empty = function\n      | Empty -> true\n      | Interval _ -> false\n\n    (** [contains t x] returns true iff [x] is contained in the\n        interval [t] *)\n    let contains t x =\n      match t with\n      | Empty -> false\n      | Interval (l,h) ->\n        Endpoint.compare x l >= 0 && Endpoint.compare x h <= 0\n\n    (** [intersect t1 t2] returns the intersection of the two input\n        intervals *)\n    let intersect t1 t2 =\n      let min x y = if Endpoint.compare x y <= 0 then x else y in\n      let max x y = if Endpoint.compare x y >= 0 then x else y in\n      match t1,t2 with\n      | Empty, _ | _, Empty -> Empty\n      | Interval (l1,h1), Interval (l2,h2) ->\n        create (max l1 l2) (min h1 h2)\n\n  end ;;\n#part 16\nmodule Int_interval = Make_interval(Int);;\nInt_interval.create 3 4;;\n#part 17\nmodule type Int_interval_intf =\n    Interval_intf with type endpoint = int;;\n#part 18\nmodule Make_interval(Endpoint : Comparable)\n      : (Interval_intf with type endpoint = Endpoint.t)\n  = struct\n\n    type endpoint = Endpoint.t\n    type t = | Interval of Endpoint.t * Endpoint.t\n             | Empty\n\n    (** [create low high] creates a new interval from [low] to\n        [high].  If [low > high], then the interval is empty *)\n    let create low high =\n      if Endpoint.compare low high > 0 then Empty\n      else Interval (low,high)\n\n    (** Returns true iff the interval is empty *)\n    let is_empty = function\n      | Empty -> true\n      | Interval _ -> false\n\n    (** [contains t x] returns true iff [x] is contained in the\n        interval [t] *)\n    let contains t x =\n      match t with\n      | Empty -> false\n      | Interval (l,h) ->\n        Endpoint.compare x l >= 0 && Endpoint.compare x h <= 0\n\n    (** [intersect t1 t2] returns the intersection of the two input\n        intervals *)\n    let intersect t1 t2 =\n      let min x y = if Endpoint.compare x y <= 0 then x else y in\n      let max x y = if Endpoint.compare x y >= 0 then x else y in\n      match t1,t2 with\n      | Empty, _ | _, Empty -> Empty\n      | Interval (l1,h1), Interval (l2,h2) ->\n        create (max l1 l2) (min h1 h2)\n  end ;;\n#part 19\nmodule Int_interval = Make_interval(Int);;\nlet i = Int_interval.create 3 4;;\nInt_interval.contains i 5;;\n#part 20\nmodule type Int_interval_intf =\n    Interval_intf with type endpoint := int;;\n#part 21\nmodule Make_interval(Endpoint : Comparable)\n    : Interval_intf with type endpoint := Endpoint.t =\n  struct\n\n    type t = | Interval of Endpoint.t * Endpoint.t\n             | Empty\n\n    (** [create low high] creates a new interval from [low] to\n        [high].  If [low > high], then the interval is empty *)\n    let create low high =\n      if Endpoint.compare low high > 0 then Empty\n      else Interval (low,high)\n\n    (** Returns true iff the interval is empty *)\n    let is_empty = function\n      | Empty -> true\n      | Interval _ -> false\n\n    (** [contains t x] returns true iff [x] is contained in the\n        interval [t] *)\n    let contains t x =\n      match t with\n      | Empty -> false\n      | Interval (l,h) ->\n        Endpoint.compare x l >= 0 && Endpoint.compare x h <= 0\n\n    (** [intersect t1 t2] returns the intersection of the two input\n        intervals *)\n    let intersect t1 t2 =\n      let min x y = if Endpoint.compare x y <= 0 then x else y in\n      let max x y = if Endpoint.compare x y >= 0 then x else y in\n      match t1,t2 with\n      | Empty, _ | _, Empty -> Empty\n      | Interval (l1,h1), Interval (l2,h2) ->\n        create (max l1 l2) (min h1 h2)\n\n\n  end ;;\n#part 22\nmodule Int_interval = Make_interval(Int);;\nInt_interval.is_empty\n    (Int_interval.create 3 4);;\nInt_interval.is_empty\n    (Int_interval.Interval (4,3));;\n#part 23\nSexp.of_string \"(This is (an s-expression))\";;\n#part 24\ntype some_type = int * string list with sexp;;\nsexp_of_some_type (33, [\"one\"; \"two\"]);;\nSexp.of_string \"(44 (five six))\" |> some_type_of_sexp;;\n#part 25\nmodule Make_interval(Endpoint : Comparable)\n    : (Interval_intf with type endpoint := Endpoint.t) = struct\n\n    type t = | Interval of Endpoint.t * Endpoint.t\n             | Empty\n    with sexp\n\n    (** [create low high] creates a new interval from [low] to\n        [high].  If [low > high], then the interval is empty *)\n    let create low high =\n      if Endpoint.compare low high > 0 then Empty\n      else Interval (low,high)\n\n    (** Returns true iff the interval is empty *)\n    let is_empty = function\n      | Empty -> true\n      | Interval _ -> false\n\n    (** [contains t x] returns true iff [x] is contained in the\n        interval [t] *)\n    let contains t x =\n      match t with\n      | Empty -> false\n      | Interval (l,h) ->\n        Endpoint.compare x l >= 0 && Endpoint.compare x h <= 0\n\n    (** [intersect t1 t2] returns the intersection of the two input\n        intervals *)\n    let intersect t1 t2 =\n      let min x y = if Endpoint.compare x y <= 0 then x else y in\n      let max x y = if Endpoint.compare x y >= 0 then x else y in\n      match t1,t2 with\n      | Empty, _ | _, Empty -> Empty\n      | Interval (l1,h1), Interval (l2,h2) ->\n        create (max l1 l2) (min h1 h2)\n\n  end ;;\n#part 26\nmodule type Interval_intf_with_sexp = sig\n   include Interval_intf\n   include Sexpable with type t := t\n  end;;\n#part 27\nmodule type Interval_intf_with_sexp = sig\n   type t\n   include Interval_intf with type t := t\n   include Sexpable      with type t := t\n  end;;\n#part 28\nmodule Make_interval(Endpoint : sig\n                         type t\n                         include Comparable with type t := t\n                         include Sexpable   with type t := t\n                       end)\n    : (Interval_intf_with_sexp with type endpoint := Endpoint.t)\n  = struct\n\n    type t = | Interval of Endpoint.t * Endpoint.t\n             | Empty\n    with sexp\n\n    (** [create low high] creates a new interval from [low] to\n        [high].  If [low > high], then the interval is empty *)\n    let create low high =\n      if Endpoint.compare low high > 0 then Empty\n      else Interval (low,high)\n\n    (* put a wrapper around the autogenerated [t_of_sexp] to enforce\n       the invariants of the data structure *)\n    let t_of_sexp sexp =\n      match t_of_sexp sexp with\n      | Empty -> Empty\n      | Interval (x,y) -> create x y\n\n    (** Returns true iff the interval is empty *)\n    let is_empty = function\n      | Empty -> true\n      | Interval _ -> false\n\n    (** [contains t x] returns true iff [x] is contained in the\n        interval [t] *)\n    let contains t x =\n      match t with\n      | Empty -> false\n      | Interval (l,h) ->\n        Endpoint.compare x l >= 0 && Endpoint.compare x h <= 0\n\n    (** [intersect t1 t2] returns the intersection of the two input\n        intervals *)\n    let intersect t1 t2 =\n      let min x y = if Endpoint.compare x y <= 0 then x else y in\n      let max x y = if Endpoint.compare x y >= 0 then x else y in\n      match t1,t2 with\n      | Empty, _ | _, Empty -> Empty\n      | Interval (l1,h1), Interval (l2,h2) ->\n        create (max l1 l2) (min h1 h2)\n  end;;\n#part 29\nmodule Int_interval = Make_interval(Int) ;;\nInt_interval.sexp_of_t (Int_interval.create 3 4);;\nInt_interval.sexp_of_t (Int_interval.create 4 3);;\n#part 30\n#part 31\n#part 32\n#part 33\n#part 34\n#part 35\n#part 36\n#part 37\n#part 38\n#part 39\n#part 40\n#part 41\n#part 42\n#part 43\n#part 44\n#part 45\n#part 46\n#part 47\n#part 48\n#part 49\n#part 50\n#part 51\n#part 52\n#part 53\n#part 54\n#part 55\n#part 56\n#part 57\n#part 58\n#part 59\n#part 60\n#part 61\n#part 62\n#part 63\n#part 64\n#part 65\n#part 66\n#part 67\n#part 68\n#part 69\n#part 70\n#part 71\n#part 72\n#part 73\n#part 74\n#part 75\n#part 76\n#part 77\n#part 78\n#part 79\n#part 80\n#part 81\n#part 82\n#part 83\n#part 84\n#part 85\n#part 86\n#part 87\n#part 88\n#part 89\n#part 90\n#part 91\n#part 92\n#part 93\n#part 94\n#part 95\n#part 96\n#part 97\n#part 98\n#part 99\n#part 100\n"
  },
  {
    "path": "code/functors/multi_sharing_constraint.syntax",
    "content": "<Module_type> with type <type1> = <type1'> and <type2> = <type2'>\n"
  },
  {
    "path": "code/functors/sexpable.ml",
    "content": "module type Sexpable = sig\n  type t\n  val sexp_of_t : t -> Sexp.t\n  val t_of_sexp : Sexp.t -> t\nend\n"
  },
  {
    "path": "code/functors/sharing_constraint.syntax",
    "content": "<Module_type> with type <type> = <type'>\n"
  },
  {
    "path": "code/gc/barrier_bench.ml",
    "content": "open Core.Std\nopen Core_bench.Std\n\ntype t1 = { mutable iters1: int; mutable count1: float }\ntype t2 = { iters2: int; count2: float }\n\nlet rec test_mutable t1 =\n  match t1.iters1 with\n  |0 -> ()\n  |_ ->\n    t1.iters1 <- t1.iters1 - 1;\n    t1.count1 <- t1.count1 +. 1.0;\n    test_mutable t1\n\nlet rec test_immutable t2 =\n  match t2.iters2 with\n  |0 -> ()\n  |n ->\n    let iters2 = n - 1 in\n    let count2 = t2.count2 +. 1.0 in\n    test_immutable { iters2; count2 }\n\nlet () =\n  let iters = 1000000 in\n  let tests = [\n    Bench.Test.create ~name:\"mutable\" \n      (fun () -> test_mutable { iters1=iters; count1=0.0 });\n    Bench.Test.create ~name:\"immutable\"\n      (fun () -> test_immutable { iters2=iters; count2=0.0 })\n  ] in\n  Bench.make_command tests |> Command.run\n"
  },
  {
    "path": "code/gc/finalizer.ml",
    "content": "open Core.Std\nopen Async.Std\n\nlet attach_finalizer n v =\n  match Heap_block.create v with\n  | None -> printf \"%20s: FAIL\\n%!\" n\n  | Some hb ->\n    let final _ = printf \"%20s: OK\\n%!\" n in\n    Gc.add_finalizer hb final\n\ntype t = { foo: bool }\n\nlet main () =\n  let alloced_float = Unix.gettimeofday () in\n  let alloced_bool = alloced_float > 0.0 in\n  let alloced_string = String.create 4 in\n  attach_finalizer \"immediate int\" 1;\n  attach_finalizer \"immediate float\" 1.0;\n  attach_finalizer \"immediate variant\" (`Foo \"hello\");\n  attach_finalizer \"immediate string\" \"hello world\";\n  attach_finalizer \"immediate record\" { foo=false };\n  attach_finalizer \"allocated float\" alloced_float;\n  attach_finalizer \"allocated bool\" alloced_bool;\n  attach_finalizer \"allocated variant\" (`Foo alloced_bool);\n  attach_finalizer \"allocated string\" alloced_string;\n  attach_finalizer \"allocated record\" { foo=alloced_bool };\n  Gc.compact ();\n  return ()\n\nlet () =\n  Command.async_basic ~summary:\"Testing finalizers\"\n    Command.Spec.empty main\n  |> Command.run\n"
  },
  {
    "path": "code/gc/minor_heap.ascii",
    "content": "                <---- size ---->\n base --- start ---------------- end\n          limit      ptr <------\n                          blocks\n"
  },
  {
    "path": "code/gc/run_barrier_bench.sh",
    "content": "corebuild -pkg core_bench barrier_bench.native\n./barrier_bench.native -ascii alloc\n"
  },
  {
    "path": "code/gc/run_finalizer.sh",
    "content": "corebuild -pkg async finalizer.native\n./finalizer.native\n"
  },
  {
    "path": "code/gc/show_barrier_bench_help.sh",
    "content": "./barrier_bench.native -help\n"
  },
  {
    "path": "code/gc/tune.topscript",
    "content": "let c = Gc.get () ;;\nGc.tune ~minor_heap_size:(262144 * 2) () ;;\n#part 1\nGc.tune ~major_heap_increment:(1000448 * 4) () ;;\n#part 2\nGc.major_slice 0 ;;\nGc.full_major () ;;\n#part 3\nGc.tune ~max_overhead:0 () ;;\n"
  },
  {
    "path": "code/guided-tour/build_sum.sh",
    "content": "corebuild sum.native\n"
  },
  {
    "path": "code/guided-tour/local_let.topscript",
    "content": "let x = 7 in\n  x + x\n  ;;\n#part 1\nx;;\n#part 2\nlet x = 7 in\n  let y = x * x in\n  x + y\n  ;;\n"
  },
  {
    "path": "code/guided-tour/main.topscript",
    "content": "open Core.Std;;\n#part 1\n3 + 4;;\n8 / 3;;\n3.5 +. 6.;;\n30_000_000 / 300_000;;\nsqrt 9.;;\n#part 2\nlet x = 3 + 4;;\nlet y = x + x;;\n#part 3\nlet x7 = 3 + 4;;\nlet x_plus_y = x + y;;\nlet x' = x + 1;;\nlet _x' = x' + x';;\n_x';;\n#part 4\nlet Seven = 3 + 4;;\nlet 7x = 7;;\nlet x-plus-y = x + y;;\n#part 5\nlet square x = x * x ;;\nsquare 2;;\nsquare (square 2);;\n#part 6\nlet ratio x y =\n     Float.of_int x /. Float.of_int y\n  ;;\nratio 4 7;;\n#part 7\nlet sum_if_true test first second =\n    (if test first then first else 0)\n    + (if test second then second else 0)\n  ;;\n#part 8\nlet even x =\n    x mod 2 = 0 ;;\nsum_if_true even 3 4;;\nsum_if_true even 2 4;;\n#part 9\nlet sum_if_true (test : int -> bool) (x : int) (y : int) : int =\n     (if test x then x else 0)\n     + (if test y then y else 0)\n  ;;\n#part 10\nlet first_if_true test x y =\n    if test x then x else y\n  ;;\n#part 11\nlet long_string s = String.length s > 6;;\nfirst_if_true long_string \"short\" \"loooooong\";;\n#part 12\nlet big_number x = x > 3;;\nfirst_if_true big_number 4 3;;\n#part 13\nfirst_if_true big_number \"short\" \"loooooong\";;\n#part 14\nlet add_potato x =\n     x + \"potato\";;\n#part 15\nlet is_a_multiple x y =\n     x mod y = 0 ;;\nis_a_multiple 8 2;;\nis_a_multiple 8 0;;\n#part 16\nlet a_tuple = (3,\"three\");;\nlet another_tuple = (3,\"four\",5.);;\n#part 17\nlet (x,y) = a_tuple;;\n#part 18\nx + String.length y;;\n#part 19\nlet distance (x1,y1) (x2,y2) =\n    sqrt ((x1 -. x2) ** 2. +. (y1 -. y2) ** 2.)\n  ;;\n#part 20\nlet languages = [\"OCaml\";\"Perl\";\"C\"];;\n#part 21\nlet numbers = [3;\"four\";5];;\n#part 22\nList.length languages;;\n#part 23\nList.map languages ~f:String.length;;\n#part 24\nList.map ~f:String.length languages;;\n#part 25\n\"French\" :: \"Spanish\" :: languages;;\n#part 26\nlanguages;;\n#part 27\n[\"OCaml\", \"Perl\", \"C\"];;\n#part 28\n1,2,3;;\n#part 29\n[1; 2; 3];;\n1 :: (2 :: (3 :: []));;\n1 :: 2 :: 3 :: [];;\n#part 30\n[1;2;3] @ [4;5;6];;\n#part 31\nlet my_favorite_language (my_favorite :: the_rest) =\n     my_favorite\n  ;;\n#part 32\nmy_favorite_language [\"English\";\"Spanish\";\"French\"];;\nmy_favorite_language [];;\n#part 33\nlet my_favorite_language languages =\n    match languages with\n    | first :: the_rest -> first\n    | [] -> \"OCaml\" (* A good default! *)\n ;;\nmy_favorite_language [\"English\";\"Spanish\";\"French\"];;\nmy_favorite_language [];;\n#part 34\nlet rec sum l =\n    match l with\n    | [] -> 0                   (* base case *)\n    | hd :: tl -> hd + sum tl   (* inductive case *)\n  ;;\nsum [1;2;3];;\n#part 35\nlet rec destutter list =\n    match list with\n    | [] -> []\n    | hd1 :: hd2 :: tl ->\n      if hd1 = hd2 then destutter (hd2 :: tl)\n      else hd1 :: destutter (hd2 :: tl)\n  ;;\n#part 36\nlet rec destutter list =\n    match list with\n    | [] -> []\n    | [hd] -> [hd]\n    | hd1 :: hd2 :: tl ->\n      if hd1 = hd2 then destutter (hd2 :: tl)\n      else hd1 :: destutter (hd2 :: tl)\n  ;;\ndestutter [\"hey\";\"hey\";\"hey\";\"man!\"];;\n#part 37\nlet divide x y =\n    if y = 0 then None else Some (x/y) ;;\n#part 38\nlet log_entry maybe_time message =\n    let time =\n      match maybe_time with\n      | Some x -> x\n      | None -> Time.now ()\n    in\n    Time.to_sec_string time ^ \" -- \" ^ message\n  ;;\nlog_entry (Some Time.epoch) \"A long long time ago\";;\nlog_entry None \"Up to the minute\";;\n#part 39\nlet x = 7 in\n  x + x\n  ;;\n#part 40\nlet x = 7 in\n  let y = x * x in\n  x + y\n  ;;\n#part 41\ntype point2d = { x : float; y : float };;\n#part 42\nlet p = { x = 3.; y = -4. };;\n#part 43\nlet magnitude { x = x_pos; y = y_pos } =\n    sqrt (x_pos ** 2. +. y_pos ** 2.);;\n#part 44\nlet magnitude { x; y } = sqrt (x ** 2. +. y ** 2.);;\n#part 45\nlet distance v1 v2 =\n     magnitude { x = v1.x -. v2.x; y = v1.y -. v2.y };;\n#part 46\ntype circle_desc  = { center: point2d; radius: float }\n  type rect_desc    = { lower_left: point2d; width: float; height: float }\n  type segment_desc = { endpoint1: point2d; endpoint2: point2d } ;;\n#part 47\ntype scene_element =\n    | Circle  of circle_desc\n    | Rect    of rect_desc\n    | Segment of segment_desc\n  ;;\n#part 48\nlet is_inside_scene_element point scene_element =\n     match scene_element with\n     | Circle { center; radius } ->\n       distance center point < radius\n     | Rect { lower_left; width; height } ->\n       point.x    > lower_left.x && point.x < lower_left.x +. width\n       && point.y > lower_left.y && point.y < lower_left.y +. height\n     | Segment { endpoint1; endpoint2 } -> false\n  ;;\nlet is_inside_scene point scene =\n     List.exists scene\n       ~f:(fun el -> is_inside_scene_element point el)\n   ;;\nis_inside_scene {x=3.;y=7.}\n    [ Circle {center = {x=4.;y= 4.}; radius = 0.5 } ];;\nis_inside_scene {x=3.;y=7.}\n    [ Circle {center = {x=4.;y= 4.}; radius = 5.0 } ];;\n#part 49\nlet numbers = [| 1; 2; 3; 4 |];;\nnumbers.(2) <- 4;;\nnumbers;;\n#part 50\ntype running_sum =\n   { mutable sum: float;\n     mutable sum_sq: float; (* sum of squares *)\n     mutable samples: int;\n   }\n  ;;\n#part 51\nlet mean rsum = rsum.sum /. float rsum.samples\n  let stdev rsum =\n     sqrt (rsum.sum_sq /. float rsum.samples\n           -. (rsum.sum /. float rsum.samples) ** 2.) ;;\n#part 52\nlet create () = { sum = 0.; sum_sq = 0.; samples = 0 }\n  let update rsum x =\n     rsum.samples <- rsum.samples + 1;\n     rsum.sum     <- rsum.sum     +. x;\n     rsum.sum_sq  <- rsum.sum_sq  +. x *. x\n  ;;\n#part 53\nlet rsum = create ();;\nList.iter [1.;3.;2.;-7.;4.;5.] ~f:(fun x -> update rsum x);;\nmean rsum;;\nstdev rsum;;\n#part 54\nlet x = { contents = 0 };;\nx.contents <- x.contents + 1;;\nx;;\n#part 55\nlet x = ref 0  (* create a ref, i.e., { contents = 0 } *) ;;\n!x             (* get the contents of a ref, i.e., x.contents *) ;;\nx := !x + 1    (* assignment, i.e., x.contents <- ... *) ;;\n!x ;;\n#part 56\ntype 'a ref = { mutable contents : 'a }\n\n  let ref x = { contents = x }\n  let (!) r = r.contents\n  let (:=) r x = r.contents <- x\n  ;;\n#part 57\nlet sum list =\n    let sum = ref 0 in\n    List.iter list ~f:(fun x -> sum := !sum + x);\n    !sum\n  ;;\n#part 58\nlet permute array =\n    let length = Array.length array in\n    for i = 0 to length - 2 do\n       (* pick a j that is after i and before the end of the array *)\n       let j = i + 1 + Random.int (length - i - 1) in\n       (* Swap i and j *)\n       let tmp = array.(i) in\n       array.(i) <- array.(j);\n       array.(j) <- tmp\n    done\n  ;;\n#part 59\nlet ar = Array.init 20 ~f:(fun i -> i);;\npermute ar;;\nar;;\n#part 60\nlet find_first_negative_entry array =\n     let pos = ref 0 in\n     while !pos < Array.length array && array.(!pos) >= 0 do\n       pos := !pos + 1\n     done;\n     if !pos = Array.length array then None else Some !pos\n  ;;\nfind_first_negative_entry [|1;2;0;3|];;\nfind_first_negative_entry [|1;-2;0;3|];;\n#part 61\nlet find_first_negative_entry array =\n     let pos = ref 0 in\n     while\n       let pos_is_good = !pos < Array.length array in\n       let element_is_non_negative = array.(!pos) >= 0 in\n       pos_is_good && element_is_non_negative\n     do\n       pos := !pos + 1\n     done;\n     if !pos = Array.length array then None else Some !pos\n  ;;\nfind_first_negative_entry [|1;2;0;3|];;\n#part 62\n#part 63\n\n"
  },
  {
    "path": "code/guided-tour/recursion.ml",
    "content": "  sum [1;2;3]\n= 1 + sum [2;3]\n= 1 + (2 + sum [3])\n= 1 + (2 + (3 + sum []))\n= 1 + (2 + (3 + 0))\n= 1 + (2 + 3)\n= 1 + 5\n= 6\n"
  },
  {
    "path": "code/guided-tour/run_sum.sh",
    "content": "./sum.native\n"
  },
  {
    "path": "code/guided-tour/sum.ml",
    "content": "open Core.Std\n\nlet rec read_and_accumulate accum =\n  let line = In_channel.input_line In_channel.stdin in\n  match line with\n  | None -> accum\n  | Some x -> read_and_accumulate (accum +. Float.of_string x)\n\nlet () =\n  printf \"Total: %F\\n\" (read_and_accumulate 0.)\n"
  },
  {
    "path": "code/guided-tour/sum.rawsh",
    "content": "$ ./sum.native\n1\n2\n3\n94.5\nTotal: 100.5\n"
  },
  {
    "path": "code/imperative-programming/.gitignore",
    "content": "numbers.txt\n"
  },
  {
    "path": "code/imperative-programming/array-get.syntax",
    "content": "<array_expr>.(<index_expr>)\n"
  },
  {
    "path": "code/imperative-programming/array-set.syntax",
    "content": "<array_expr>.(<index_expr>) <- <value_expr>\n"
  },
  {
    "path": "code/imperative-programming/bigarray.syntax",
    "content": "<bigarray_expr>.{<index_expr>}\n<bigarray_expr>.{<index_expr>} <- <value_expr>\n"
  },
  {
    "path": "code/imperative-programming/build_all.sh",
    "content": "corebuild dictionary.cmo\ncorebuild dlist.cmo\ncorebuild time_converter.byte\ncorebuild time_converter2.byte\n"
  },
  {
    "path": "code/imperative-programming/dictionary.ml",
    "content": "(* part 1 *)\n(* file: dictionary.ml *)\nopen Core.Std\n\ntype ('a, 'b) t = { mutable length: int;\n                    buckets: ('a * 'b) list array;\n                  }\n\n(* part 2 *)\nlet num_buckets = 17\n\nlet hash_bucket key = (Hashtbl.hash key) mod num_buckets\n\nlet create () =\n  { length = 0;\n    buckets = Array.create ~len:num_buckets [];\n  }\n\nlet length t = t.length\n\nlet find t key =\n  List.find_map t.buckets.(hash_bucket key)\n    ~f:(fun (key',data) -> if key' = key then Some data else None)\n\n(* part 3 *)\nlet iter t ~f =\n  for i = 0 to Array.length t.buckets - 1 do\n    List.iter t.buckets.(i) ~f:(fun (key, data) -> f ~key ~data)\n  done\n\n(* part 4 *)\nlet bucket_has_key t i key =\n  List.exists t.buckets.(i) ~f:(fun (key',_) -> key' = key)\n\nlet add t ~key ~data =\n  let i = hash_bucket key in\n  let replace = bucket_has_key t i key in\n  let filtered_bucket =\n    if replace then\n      List.filter t.buckets.(i) ~f:(fun (key',_) -> key' <> key)\n    else\n      t.buckets.(i)\n  in\n  t.buckets.(i) <- (key, data) :: filtered_bucket;\n  if not replace then t.length <- t.length + 1\n\nlet remove t key =\n  let i = hash_bucket key in\n  if bucket_has_key t i key then (\n    let filtered_bucket =\n      List.filter t.buckets.(i) ~f:(fun (key',_) -> key' <> key)\n    in\n    t.buckets.(i) <- filtered_bucket;\n    t.length <- t.length - 1\n  )\n"
  },
  {
    "path": "code/imperative-programming/dictionary.mli",
    "content": "(* part 1 *)\n(* file: dictionary.mli *)\nopen Core.Std\n\ntype ('a, 'b) t\n\nval create : unit -> ('a, 'b) t\nval length : ('a, 'b) t -> int\nval add    : ('a, 'b) t -> key:'a -> data:'b -> unit\nval find   : ('a, 'b) t -> 'a -> 'b option\nval iter   : ('a, 'b) t -> f:(key:'a -> data:'b -> unit) -> unit\nval remove : ('a, 'b) t -> 'a -> unit\n"
  },
  {
    "path": "code/imperative-programming/dictionary2.ml",
    "content": "open Core.Std\n\ntype ('a, 'b) t = { mutable length: int;\n                    buckets: ('a * 'b) list array;\n                  }\n\nlet num_buckets = 17\n\nlet hash_bucket key = (Hashtbl.hash key) mod num_buckets\n\nlet create () =\n  { length = 0;\n    buckets = Array.create ~len:num_buckets [];\n  }\n\nlet length t = t.length\n\nlet find t key =\n  List.find_map t.buckets.(hash_bucket key)\n    ~f:(fun (key',data) -> if key' = key then Some data else None)\n\nlet iter t ~f =\n  for i = 0 to Array.length t.buckets - 1 do\n    List.iter t.buckets.(i) ~f:(fun (key, data) -> f ~key ~data)\n  done\n\nlet bucket_has_key t i key =\n  List.exists t.buckets.(i) ~f:(fun (key',_) -> key' = key)\n\nlet add t ~key ~data =\n  let i = hash_bucket key in\n  let replace = bucket_has_key t i key in\n  let filtered_bucket =\n    if replace then\n      List.filter t.buckets.(i) ~f:(fun (key',_) -> key' <> key)\n    else\n      t.buckets.(i)\n  in\n  (* part 1 *)\n  let () = t.buckets.(i) <- (key, data) :: filtered_bucket in\n  if not replace then t.length <- t.length + 1\n(* part 2 *)\nlet remove t key =\n  let i = hash_bucket key in\n  if bucket_has_key t i key then (\n    let filtered_bucket =\n      List.filter t.buckets.(i) ~f:(fun (key',_) -> key' <> key)\n    in\n    t.buckets.(i) <- filtered_bucket;\n    t.length <- t.length - 1\n  )\n"
  },
  {
    "path": "code/imperative-programming/dlist.ml",
    "content": "(* part 1 *)\n(* file: dlist.ml *)\nopen Core.Std\n\ntype 'a element =\n  { value : 'a;\n    mutable next : 'a element option;\n    mutable prev : 'a element option\n  }\n\ntype 'a t = 'a element option ref\n\n(* part 2 *)\nlet create () = ref None\nlet is_empty t = !t = None\n\nlet value elt = elt.value\n\nlet first t = !t\nlet next elt = elt.next\nlet prev elt = elt.prev\n\n(* part 3 *)\nlet insert_first t value =\n  let new_elt = { prev = None; next = !t; value } in\n  begin match !t with\n  | Some old_first -> old_first.prev <- Some new_elt\n  | None -> ()\n  end;\n  t := Some new_elt;\n  new_elt\n\n(* part 4 *)\nlet insert_after elt value =\n  let new_elt = { value; prev = Some elt; next = elt.next } in\n  begin match elt.next with\n  | Some old_next -> old_next.prev <- Some new_elt\n  | None -> ()\n  end;\n  elt.next <- Some new_elt;\n  new_elt\n\n(* part 5 *)\nlet remove t elt =\n  let { prev; next; _ } = elt in\n  begin match prev with\n  | Some prev -> prev.next <- next\n  | None -> t := next\n  end;\n  begin match next with\n  | Some next -> next.prev <- prev;\n  | None -> ()\n  end;\n  elt.prev <- None;\n  elt.next <- None\n\n(* part 6 *)\nlet iter t ~f =\n  let rec loop = function\n    | None -> ()\n    | Some el -> f (value el); loop (next el)\n  in\n  loop !t\n\nlet find_el t ~f =\n  let rec loop = function\n    | None -> None\n    | Some elt ->\n      if f (value elt) then Some elt\n      else loop (next elt)\n  in\n  loop !t\n"
  },
  {
    "path": "code/imperative-programming/dlist.mli",
    "content": "(* file: dlist.mli *)\nopen Core.Std\n\ntype 'a t\ntype 'a element\n\n(** Basic list operations  *)\nval create   : unit -> 'a t\nval is_empty : 'a t -> bool\n\n(** Navigation using [element]s *)\nval first : 'a t -> 'a element option\nval next  : 'a element -> 'a element option\nval prev  : 'a element -> 'a element option\nval value : 'a element -> 'a\n\n(** Whole-data-structure iteration *)\nval iter    : 'a t -> f:('a -> unit) -> unit\nval find_el : 'a t -> f:('a -> bool) -> 'a element option\n\n(** Mutation *)\nval insert_first : 'a t -> 'a -> 'a element\nval insert_after : 'a element -> 'a -> 'a element\nval remove : 'a t -> 'a element -> unit\n"
  },
  {
    "path": "code/imperative-programming/edit_distance.ascii",
    "content": "edit_distance \"OCam\" \"ocaml\"\nedit_distance \"OCaml\" \"ocam\"\nedit_distance \"OCam\" \"ocam\"\n"
  },
  {
    "path": "code/imperative-programming/edit_distance2.ascii",
    "content": "edit_distance \"OCam\" \"ocaml\"\n   edit_distance \"OCa\" \"ocaml\"\n   edit_distance \"OCam\" \"ocam\"\n   edit_distance \"OCa\" \"ocam\"\nedit_distance \"OCaml\" \"ocam\"\n   edit_distance \"OCam\" \"ocam\"\n   edit_distance \"OCaml\" \"oca\"\n   edit_distance \"OCam\" \"oca\"\nedit_distance \"OCam\" \"ocam\"\n   edit_distance \"OCa\" \"ocam\"\n   edit_distance \"OCam\" \"oca\"\n   edit_distance \"OCa\" \"oca\"\n"
  },
  {
    "path": "code/imperative-programming/examples.topscript",
    "content": "1;;\n#part 1\nList.find_map;;\n#part 2\nlet rec endless_loop = 1 :: 2 :: 3 :: endless_loop;;\n"
  },
  {
    "path": "code/imperative-programming/fib.topscript",
    "content": "let time f =\n    let start = Time.now () in\n    let x = f () in\n    let stop = Time.now () in\n    printf \"Time: %s\\n\" (Time.Span.to_string (Time.diff stop start));\n    x ;;\nlet memoize f =\n    let table = Hashtbl.Poly.create () in\n    (fun x ->\n      match Hashtbl.find table x with\n      | Some y -> y\n      | None ->\n        let y = f x in\n        Hashtbl.add_exn table ~key:x ~data:y;\n        y\n    );;\n#part 1\nlet rec fib i =\n    if i <= 1 then 1 else fib (i - 1) + fib (i - 2);;\n#part 2\ntime (fun () -> fib 20);;\ntime (fun () -> fib 40);;\n#part 3\nlet fib = memoize fib;;\ntime (fun () -> fib 40);;\ntime (fun () -> fib 40);;\n#part 4\nlet fib_norec fib i =\n    if i <= 1 then i\n    else fib (i - 1) + fib (i - 2) ;;\n#part 5\nlet rec fib i = fib_norec fib i;;\nfib 20;;\n#part 6\nlet make_rec f_norec =\n    let rec f x = f_norec f x in\n    f\n  ;;\nlet fib = make_rec fib_norec;;\nfib 20;;\n#part 7\nlet memo_rec f_norec x =\n    let fref = ref (fun _ -> assert false) in\n    let f = memoize (fun x -> f_norec !fref x) in\n    fref := f;\n    f x\n  ;;\n#part 8\nlet fib = memo_rec fib_norec;;\ntime (fun () -> fib 40);;\n#part 9\nlet fib = memo_rec (fun fib i ->\n    if i <= 1 then 1 else fib (i - 1) + fib (i - 2));;\n"
  },
  {
    "path": "code/imperative-programming/file.topscript",
    "content": "1;;\n#part 1\nlet create_number_file filename numbers =\n    let outc = Out_channel.create filename in\n    List.iter numbers ~f:(fun x -> fprintf outc \"%d\\n\" x);\n    Out_channel.close outc\n  ;;\nlet sum_file filename =\n     let file = In_channel.create filename in\n     let numbers = List.map ~f:Int.of_string (In_channel.input_lines file) in\n     let sum = List.fold ~init:0 ~f:(+) numbers in\n     In_channel.close file;\n     sum\n  ;;\ncreate_number_file \"numbers.txt\" [1;2;3;4;5];;\nsum_file \"numbers.txt\";;\n#part 2\nsum_file \"/etc/hosts\";;\n#part 3\nfor i = 1 to 10000 do try ignore (sum_file \"/etc/hosts\") with _ -> () done;;\nsum_file \"numbers.txt\";;\n"
  },
  {
    "path": "code/imperative-programming/file2.topscript",
    "content": "1;;\n#part 1\nlet sum_file filename =\n    let file = In_channel.create filename in\n    protect ~f:(fun () ->\n        let numbers = List.map ~f:Int.of_string (In_channel.input_lines file) in\n        List.fold ~init:0 ~f:(+) numbers)\n      ~finally:(fun () -> In_channel.close file)\n  ;;\n#part 2\nfor i = 1 to 10000 do try ignore (sum_file \"/etc/hosts\") with _ -> () done;;\nsum_file \"numbers.txt\";;\n#part 3\nlet sum_file filename =\n    In_channel.with_file filename ~f:(fun file ->\n      let numbers = List.map ~f:Int.of_string (In_channel.input_lines file) in\n      List.fold ~init:0 ~f:(+) numbers)\n  ;;\n#part 4\nlet sum_file filename =\n    In_channel.with_file filename ~f:(fun file ->\n      In_channel.fold_lines file ~init:0 ~f:(fun sum line ->\n        sum + Int.of_string line))\n  ;;\n"
  },
  {
    "path": "code/imperative-programming/for.topscript",
    "content": "1;;\n#part 1\nfor i = 0 to 3 do printf \"i = %d\\n\" i done;;\n#part 2\nfor i = 3 downto 0 do printf \"i = %d\\n\" i done;;\n#part 3\nlet rev_inplace ar =\n    let i = ref 0 in\n    let j = ref (Array.length ar - 1) in\n    (* terminate when the upper and lower indices meet *)\n    while !i < !j do\n      (* swap the two elements *)\n      let tmp = ar.(!i) in\n      ar.(!i) <- ar.(!j);\n      ar.(!j) <- tmp;\n      (* bump the indices *)\n      incr i;\n      decr j\n    done\n  ;;\nlet nums = [|1;2;3;4;5|];;\nrev_inplace nums;;\nnums;;\n"
  },
  {
    "path": "code/imperative-programming/lazy.topscript",
    "content": "1;;\n#part 1\nlet v = lazy (print_string \"performing lazy computation\\n\"; sqrt 16.);;\nLazy.force v;;\nLazy.force v;;\n#part 2\ntype 'a lazy_state =\n    | Delayed of (unit -> 'a)\n    | Value of 'a\n    | Exn of exn\n  ;;\n#part 3\nlet create_lazy f = ref (Delayed f);;\nlet v = create_lazy\n    (fun () -> print_string \"performing lazy computation\\n\"; sqrt 16.);;\n#part 4\nlet force v =\n    match !v with\n    | Value x -> x\n    | Exn e -> raise e\n    | Delayed f ->\n      try\n        let x = f () in\n        v := Value x;\n        x\n      with exn ->\n        v := Exn exn;\n        raise exn\n     ;;\n#part 5\nforce v;;\nforce v;;\n\n\n"
  },
  {
    "path": "code/imperative-programming/let-unit.syntax",
    "content": "let () = <expr1> in\nlet () = <expr2> in\n...\n<exprN>\n"
  },
  {
    "path": "code/imperative-programming/let_rec.ml",
    "content": "let rec x = x + 1\n"
  },
  {
    "path": "code/imperative-programming/letrec.topscript",
    "content": "let time f =\n    let start = Time.now () in\n    let x = f () in\n    let stop = Time.now () in\n    printf \"Time: %s\\n\" (Time.Span.to_string (Time.diff stop start));\n    x ;;\nlet memoize f =\n    let table = Hashtbl.Poly.create () in\n    (fun x ->\n       match Hashtbl.find table x with\n       | Some y -> y\n       | None ->\n         let y = f x in\n         Hashtbl.add_exn table ~key:x ~data:y;\n         y\n    );;\n#part 1\nlet memo_rec f_norec =\n    let rec f = memoize (fun x -> f_norec f x) in\n    f\n  ;;\n#part 2\nlet rec x = lazy (Lazy.force x + 1);;\n#part 3\nLazy.force x;;\n#part 4\nlet fib_norec fib i =\n    if i <= 1 then i\n    else fib (i - 1) + fib (i - 2) ;;\n#part 5\nlet lazy_memo_rec f_norec x =\n    let rec f = lazy (memoize (fun x -> f_norec (Lazy.force f) x)) in\n    (Lazy.force f) x\n  ;;\ntime (fun () -> lazy_memo_rec fib_norec 40);;\n\n\n\n"
  },
  {
    "path": "code/imperative-programming/memo.topscript",
    "content": "1;;\n#part 1\nlet memoize f =\n    let table = Hashtbl.Poly.create () in\n    (fun x ->\n      match Hashtbl.find table x with\n      | Some y -> y\n      | None ->\n        let y = f x in\n        Hashtbl.add_exn table ~key:x ~data:y;\n        y\n    );;\n#part 2\nlet rec edit_distance s t =\n    match String.length s, String.length t with\n    | (0,x) | (x,0) -> x\n    | (len_s,len_t) ->\n      let s' = String.drop_suffix s 1 in\n      let t' = String.drop_suffix t 1 in\n      let cost_to_drop_both =\n        if s.[len_s - 1] = t.[len_t - 1] then 0 else 1\n      in\n      List.reduce_exn ~f:Int.min\n        [ edit_distance s' t  + 1\n        ; edit_distance s  t' + 1\n        ; edit_distance s' t' + cost_to_drop_both\n        ]\n  ;;\nedit_distance \"OCaml\" \"ocaml\";;\n#part 3\nlet time f =\n    let start = Time.now () in\n    let x = f () in\n    let stop = Time.now () in\n    printf \"Time: %s\\n\" (Time.Span.to_string (Time.diff stop start));\n    x ;;\n#part 4\ntime (fun () -> edit_distance \"OCaml\" \"ocaml\");;\ntime (fun () -> edit_distance \"OCaml 4.01\" \"ocaml 4.01\");;\n#part 5\nlet memo_rec f_norec x =\n    let fref = ref (fun _ -> assert false) in\n    let f = memoize (fun x -> f_norec !fref x) in\n    fref := f;\n    f x\n;;\n#part 6\nlet edit_distance = memo_rec (fun edit_distance (s,t) ->\n    match String.length s, String.length t with\n    | (0,x) | (x,0) -> x\n    | (len_s,len_t) ->\n      let s' = String.drop_suffix s 1 in\n      let t' = String.drop_suffix t 1 in\n      let cost_to_drop_both =\n        if s.[len_s - 1] = t.[len_t - 1] then 0 else 1\n      in\n      List.reduce_exn ~f:Int.min\n        [ edit_distance (s',t ) + 1\n        ; edit_distance (s ,t') + 1\n        ; edit_distance (s',t') + cost_to_drop_both\n        ]) ;;\n#part 7\ntime (fun () -> edit_distance (\"OCaml 4.01\",\"ocaml 4.01\"));;\n\n\n"
  },
  {
    "path": "code/imperative-programming/order.topscript",
    "content": "1;;\n#part 1\nlet x = sin 120. in\n  let y = sin 75.  in\n  let z = sin 128. in\n  List.exists ~f:(fun x -> x < 0.) [x;y;z]\n  ;;\n#part 2\nlet x = lazy (sin 120.) in\n  let y = lazy (sin 75.)  in\n  let z = lazy (sin 128.) in\n  List.exists ~f:(fun x -> Lazy.force x < 0.) [x;y;z]\n  ;;\n#part 3\nlet x = lazy (printf \"1\\n\"; sin 120.) in\n  let y = lazy (printf \"2\\n\"; sin 75.)  in\n  let z = lazy (printf \"3\\n\"; sin 128.) in\n  List.exists ~f:(fun x -> Lazy.force x < 0.) [x;y;z]\n  ;;\n#part 4\nList.exists ~f:(fun x -> x < 0.)\n  [ (printf \"1\\n\"; sin 120.);\n    (printf \"2\\n\"; sin 75.);\n    (printf \"3\\n\"; sin 128.); ]\n  ;;\n"
  },
  {
    "path": "code/imperative-programming/printf.topscript",
    "content": "open Printf\n1;;\n#part 1\nprintf \"%i is an integer, %F is a float, \\\"%s\\\" is a string\\n\"\n    3 4.5 \"five\";;\n#part 2\nprintf \"An integer: %i\\n\" 4.5;;\n#part 3\nlet fmt = \"%i is an integer, %F is a float, \\\"%s\\\" is a string\\n\";;\n  printf fmt 3 4.5 \"five\";;\n#part 4\nlet fmt : ('a, 'b, 'c) format =\n    \"%i is an integer, %F is a float, \\\"%s\\\" is a string\\n\";;\n#part 5\nprintf fmt 3 4.5 \"five\";;\n\n"
  },
  {
    "path": "code/imperative-programming/ref.topscript",
    "content": "1;;\n#part 1\ntype 'a ref = { mutable contents : 'a };;\n#part 2\nlet ref x = { contents = x };;\n  let (!) r = r.contents;;\n  let (:=) r x = r.contents <- x;;\n#part 3\nlet x = ref 1;;\n  !x;;\n  x := !x + 1;;\n  !x;;\n"
  },
  {
    "path": "code/imperative-programming/remember_type.ml",
    "content": "val remember : '_a -> '_a = <fun>\n"
  },
  {
    "path": "code/imperative-programming/semicolon-syntax.syntax",
    "content": "<expr1>;\n<expr2>;\n...\n<exprN>\n"
  },
  {
    "path": "code/imperative-programming/semicolon.syntax",
    "content": "<expr1>;\n<expr2>;\n...\n<exprN>\n"
  },
  {
    "path": "code/imperative-programming/string.syntax",
    "content": "<string_expr>.[<index_expr>]\n<string_expr>.[<index_expr>] <- <char_expr>\n"
  },
  {
    "path": "code/imperative-programming/time_converter.ml",
    "content": "open Core.Std\n\nlet () =\n  Out_channel.output_string stdout \"Pick a timezone: \";\n  Out_channel.flush stdout;\n  match In_channel.input_line stdin with\n  | None -> failwith \"No timezone provided\"\n  | Some zone_string ->\n    let zone = Zone.find_exn zone_string in\n    let time_string = Time.to_string_abs (Time.now ()) ~zone in\n    Out_channel.output_string stdout\n      (String.concat\n         [\"The time in \";Zone.to_string zone;\" is \";time_string;\".\\n\"]);\n    Out_channel.flush stdout\n\n"
  },
  {
    "path": "code/imperative-programming/time_converter.rawsh",
    "content": "$ corebuild time_converter.byte\n$ ./time_converter.byte\nPick a timezone:\n"
  },
  {
    "path": "code/imperative-programming/time_converter2.ml",
    "content": "open Core.Std\n\nlet () =\n  printf \"Pick a timezone: %!\";\n  match In_channel.input_line stdin with\n  | None -> failwith \"No timezone provided\"\n  | Some zone_string ->\n    let zone = Time.Zone.find_exn zone_string in\n    let time_string = Time.to_string_abs (Time.now ()) ~zone in\n    printf \"The time in %s is %s.\\n%!\" (Time.Zone.to_string zone) time_string\n"
  },
  {
    "path": "code/imperative-programming/time_converter2.rawsh",
    "content": "Pick a timezone: Europe/London\nThe time in Europe/London is 2013-08-15 00:03:10.666220+01:00.\n"
  },
  {
    "path": "code/imperative-programming/value_restriction-13.rawscript",
    "content": "# module Concat_list : sig\n    type 'a t\n    val empty : 'a t\n    val singleton : 'a -> 'a t\n    val concat  : 'a t -> 'a t -> 'a t  (* constant time *)\n    val to_list : 'a t -> 'a list       (* linear time   *)\n  end = struct\n\n    type 'a t = Empty | Singleton of 'a | Concat of 'a t * 'a t\n\n    ...\n\n  end;;\n module Concat_list :\n  sig\n    type 'a t\n    val empty : 'a t\n    val singleton : 'a -> 'a t\n    val concat : 'a t -> 'a t -> 'a t\n    val to_list : 'a t -> 'a list\n  end\n"
  },
  {
    "path": "code/imperative-programming/value_restriction.topscript",
    "content": "let identity x = x;;\nlet time f =\n    let start = Time.now () in\n    let x = f () in\n    let stop = Time.now () in\n    printf \"Time: %s\\n\" (Time.Span.to_string (Time.diff stop start));\n    x ;;\nlet memoize f =\n    let table = Hashtbl.Poly.create () in\n    (fun x ->\n       match Hashtbl.find table x with\n       | Some y -> y\n       | None ->\n         let y = f x in\n         Hashtbl.add_exn table ~key:x ~data:y;\n         y\n    );;\n#part 1\n(fun x -> [x;x]);;\n#part 2\nmemoize (fun x -> [x;x]);;\n#part 3\nidentity (fun x -> [x;x]);;\n#part 4\nlet f () = ref None;;\n#part 5\nList.init;;\nList.init 10 ~f:Int.to_string;;\n#part 6\nlet list_init_10 = List.init 10;;\n#part 7\nlet list_init_10 ~f = List.init 10 ~f;;\n#part 8\nidentity (fun x -> [x;x]);;\n#part 9\nidentity [];;\n#part 10\n[||];;\nidentity [||];;\n#part 11\nmodule Concat_list : sig\n    type 'a t\n    val empty : 'a t\n    val singleton : 'a -> 'a t\n    val concat  : 'a t -> 'a t -> 'a t  (* constant time *)\n    val to_list : 'a t -> 'a list       (* linear time   *)\n  end = struct\n\n    type 'a t = Empty | Singleton of 'a | Concat of 'a t * 'a t\n\n    let empty = Empty\n    let singleton x = Singleton x\n    let concat x y = Concat (x,y)\n\n    let rec to_list_with_tail t tail =\n      match t with\n      | Empty -> tail\n      | Singleton x -> x :: tail\n      | Concat (x,y) -> to_list_with_tail x (to_list_with_tail y tail)\n\n    let to_list t =\n      to_list_with_tail t []\n\n  end;;\n#part 12\nConcat_list.empty;;\nidentity Concat_list.empty;;\n#part 13\nmodule Concat_list : sig\n    type +'a t\n    val empty : 'a t\n    val singleton : 'a -> 'a t\n    val concat  : 'a t -> 'a t -> 'a t (* constant time *)\n    val to_list : 'a t -> 'a list       (* linear time   *)\n  end = struct\n\n    type 'a t = Empty | Singleton of 'a | Concat of 'a t * 'a t\n\n    let empty = Empty\n    let singleton x = Singleton x\n    let concat x y = Concat (x,y)\n\n    let rec to_list_with_tail t tail =\n      match t with\n      | Empty -> tail\n      | Singleton x -> x :: tail\n      | Concat (x,y) -> to_list_with_tail x (to_list_with_tail y tail)\n\n    let to_list t =\n      to_list_with_tail t []\n\n  end;;\n#part 14\nidentity Concat_list.empty;;\n"
  },
  {
    "path": "code/imperative-programming/weak.topscript",
    "content": "1;;\n#part 1\nlet remember =\n    let cache = ref None in\n    (fun x ->\n       match !cache with\n       | Some y -> y\n       | None -> cache := Some x; x)\n  ;;\n#part 2\nlet identity x = x;;\nidentity 3;;\nidentity \"five\";;\n#part 3\nlet remember_three () = remember 3;;\nremember;;\nremember \"avocado\";;\n"
  },
  {
    "path": "code/installation/arch_install.rawsh",
    "content": "# pacman -Sy ocaml\n"
  },
  {
    "path": "code/installation/arch_opam.rawsh",
    "content": "$ sudo pacman -Sy base-devel\n$ wget https://aur.archlinux.org/packages/op/opam/opam.tar.gz\n$ tar -xvf opam.tar.gz && cd opam\n$ makepkg\n$ sudo pacman -U opam-<version>.tar.gz\n"
  },
  {
    "path": "code/installation/brew_install.rawsh",
    "content": "$ brew update\n$ brew install ocaml\n$ brew install pcre\n"
  },
  {
    "path": "code/installation/brew_opam_install.rawsh",
    "content": "$ brew update\n$ brew install opam\n"
  },
  {
    "path": "code/installation/debian_apt.rawsh",
    "content": "# apt-get install \\\n  ocaml ocaml-native-compilers camlp4-extra \\\n  git libpcre3-dev curl build-essential m4\n"
  },
  {
    "path": "code/installation/debian_apt_opam.rawsh",
    "content": "# apt-get update\n# apt-get -t unstable install opam\n"
  },
  {
    "path": "code/installation/emacsrc.scm",
    "content": "(autoload 'utop \"utop\" \"Toplevel for OCaml\" t)\n"
  },
  {
    "path": "code/installation/fedora_install.rawsh",
    "content": "# yum install ocaml\n# yum install ocaml-camlp4-devel\n# yum install pcre-devel\n"
  },
  {
    "path": "code/installation/macports_install.rawsh",
    "content": "$ sudo port install ocaml\n$ sudo port install ocaml-pcre\n"
  },
  {
    "path": "code/installation/macports_opam_install.rawsh",
    "content": "$ sudo port install opam\n"
  },
  {
    "path": "code/installation/ocaml_src_install.rawsh",
    "content": "$ curl -OL https://github.com/ocaml/ocaml/archive/4.01.tar.gz\n$ tar -zxvf 4.01.tar.gz\n$ cd ocaml-4.01\n$ ./configure\n$ make world world.opt\n$ sudo make install\n"
  },
  {
    "path": "code/installation/ocaml_user_conf.rawsh",
    "content": "$ ./configure -prefix $HOME/my-ocaml\n"
  },
  {
    "path": "code/installation/opam_eval.rawsh",
    "content": "$ eval `opam config env`\n"
  },
  {
    "path": "code/installation/opam_init.rawsh",
    "content": "$ opam init\n<...>\n=-=-=-= Configuring OPAM =-=-=-=\nDo you want to update your configuration to use OPAM ? [Y/n] y\n[1/4] Do you want to update your shell configuration file ? [default: ~/.profile] y\n[2/4] Do you want to update your ~/.ocamlinit ? [Y/n] y\n[3/4] Do you want to install the auto-complete scripts ? [Y/n] y\n[4/4] Do you want to install the `opam-switch-eval` script ? [Y/n] y\nUser configuration:\n  ~/.ocamlinit is already up-to-date.\n  ~/.profile is already up-to-date.\nGloabal configuration:\n  Updating <root>/opam-init/init.sh\n    auto-completion : [true]\n    opam-switch-eval: [true]\n  Updating <root>/opam-init/init.zsh\n    auto-completion : [true]\n    opam-switch-eval: [true]\n  Updating <root>/opam-init/init.csh\n    auto-completion : [true]\n    opam-switch-eval: [true]\n"
  },
  {
    "path": "code/installation/opam_install.rawsh",
    "content": "$ opam install core core_extended core_bench async\n"
  },
  {
    "path": "code/installation/opam_install_utop.rawsh",
    "content": "$ opam install utop\n"
  },
  {
    "path": "code/installation/opam_list.rawsh",
    "content": "$ opam list\nInstalled packages for 4.01.0:\nasync                  109.38.00  Monadic concurrency library\nasync_core             109.38.00  Monadic concurrency library\nasync_extra            109.38.00  Monadic concurrency library\n<...>\n"
  },
  {
    "path": "code/installation/opam_switch.rawsh",
    "content": "$ opam switch 4.01.0dev+trunk\n$ eval `opam config env`\n"
  },
  {
    "path": "code/installation/open_core.ml",
    "content": "open Core.Std\n"
  },
  {
    "path": "code/installation/show_ocamlinit.rawsh",
    "content": "$ cat ~/.ocamlinit\n#use \"topfind\"\n#thread\n#camlp4o\n#require \"core.top\"\n#require \"core.syntax\"\n"
  },
  {
    "path": "code/installation/ubuntu_opam_ppa.rawsh",
    "content": "$ add-apt-repository ppa:avsm/ppa\n$ apt-get update\n$ apt-get install ocaml opam\n"
  },
  {
    "path": "code/json/_tags",
    "content": "true: -warn_32\n"
  },
  {
    "path": "code/json/book.json",
    "content": "{\n  \"title\": \"Real World OCaml\",\n  \"tags\" : [ \"functional programming\", \"ocaml\", \"algorithms\" ],\n  \"pages\": 450,\n  \"authors\": [\n    { \"name\": \"Jason Hickey\", \"affiliation\": \"Google\" },\n    { \"name\": \"Anil Madhavapeddy\", \"affiliation\": \"Cambridge\"},\n    { \"name\": \"Yaron Minsky\", \"affiliation\": \"Jane Street\"}\n  ],\n  \"is_online\": true\n}\n"
  },
  {
    "path": "code/json/build_github_atd.sh",
    "content": "atdgen -t github.atd\natdgen -j github.atd\nocamlfind ocamlc -package atd -i github_t.mli\n"
  },
  {
    "path": "code/json/build_github_org.sh",
    "content": "atdgen -t github_org.atd\natdgen -j github_org.atd\ncorebuild -pkg core_extended,yojson,atdgen github_org_info.native\n"
  },
  {
    "path": "code/json/build_json.topscript",
    "content": "#require \"yojson\" ;;\nopen Core.Std ;;\n#part 1\nlet person = `Assoc [ (\"name\", `String \"Anil\") ] ;;\n#part 2\nYojson.Basic.pretty_to_string ;;\n#part 3\nYojson.Basic.pretty_to_string person ;;\nYojson.Basic.pretty_to_channel stdout person ;;\n#part 4\nlet person = `Assoc (\"name\", `String \"Anil\");;\nYojson.Basic.pretty_to_string person ;;\n#part 5\nlet (person : Yojson.Basic.json) =\n  `Assoc (\"name\", `String \"Anil\");;\n"
  },
  {
    "path": "code/json/generate_github_org_json.sh",
    "content": "atdgen -j github_org.atd\ncat github_org_j.mli\n"
  },
  {
    "path": "code/json/generate_github_org_types.sh",
    "content": "atdgen -t github_org.atd\ncat github_org_t.mli\n"
  },
  {
    "path": "code/json/github.atd",
    "content": "type scope = [\n    User <json name=\"user\">\n  | Public_repo <json name=\"public_repo\">\n  | Repo <json name=\"repo\">\n  | Repo_status <json name=\"repo_status\">\n  | Delete_repo <json name=\"delete_repo\">\n  | Gist <json name=\"gist\">\n]\n\ntype app = {\n  name: string;\n  url: string;\n}  <ocaml field_prefix=\"app_\">\n\ntype authorization_request = {\n  scopes: scope list;\n  note: string;\n} <ocaml field_prefix=\"auth_req_\">\n\ntype authorization_response = {\n  scopes: scope list;\n  token: string;\n  app: app;\n  url: string;\n  id: int;\n  ?note: string option;\n  ?note_url: string option;\n}\n"
  },
  {
    "path": "code/json/github_j.ml",
    "content": "(* Auto-generated from \"github.atd\" *)\n\n\ntype scope = Github_t.scope\n\ntype app = Github_t.app = {\n  app_name (*atd name *): string;\n  app_url (*atd url *): string\n}\n\ntype authorization_request = Github_t.authorization_request = {\n  auth_req_scopes (*atd scopes *): scope list;\n  auth_req_note (*atd note *): string\n}\n\ntype authorization_response = Github_t.authorization_response = {\n  scopes: scope list;\n  token: string;\n  app: app;\n  url: string;\n  id: int;\n  note: string option;\n  note_url: string option\n}\n\nlet write_scope = (\n  fun ob x ->\n    match x with\n      | `User -> Bi_outbuf.add_string ob \"<\\\"user\\\">\"\n      | `Public_repo -> Bi_outbuf.add_string ob \"<\\\"public_repo\\\">\"\n      | `Repo -> Bi_outbuf.add_string ob \"<\\\"repo\\\">\"\n      | `Repo_status -> Bi_outbuf.add_string ob \"<\\\"repo_status\\\">\"\n      | `Delete_repo -> Bi_outbuf.add_string ob \"<\\\"delete_repo\\\">\"\n      | `Gist -> Bi_outbuf.add_string ob \"<\\\"gist\\\">\"\n)\nlet string_of_scope ?(len = 1024) x =\n  let ob = Bi_outbuf.create len in\n  write_scope ob x;\n  Bi_outbuf.contents ob\nlet read_scope = (\n  fun p lb ->\n    Yojson.Safe.read_space p lb;\n    match Yojson.Safe.start_any_variant p lb with\n      | `Edgy_bracket -> (\n          Yojson.Safe.read_space p lb;\n          let f =\n            fun s pos len ->\n              if pos < 0 || len < 0 || pos + len > String.length s then\n                invalid_arg \"out-of-bounds substring position or length\";\n              try\n                match len with\n                  | 4 -> (\n                      match String.unsafe_get s pos with\n                        | 'g' -> (\n                            if String.unsafe_get s (pos+1) = 'i' && String.unsafe_get s (pos+2) = 's' && String.unsafe_get s (pos+3) = 't' then (\n                              5\n                            )\n                            else (\n                              raise (Exit)\n                            )\n                          )\n                        | 'r' -> (\n                            if String.unsafe_get s (pos+1) = 'e' && String.unsafe_get s (pos+2) = 'p' && String.unsafe_get s (pos+3) = 'o' then (\n                              2\n                            )\n                            else (\n                              raise (Exit)\n                            )\n                          )\n                        | 'u' -> (\n                            if String.unsafe_get s (pos+1) = 's' && String.unsafe_get s (pos+2) = 'e' && String.unsafe_get s (pos+3) = 'r' then (\n                              0\n                            )\n                            else (\n                              raise (Exit)\n                            )\n                          )\n                        | _ -> (\n                            raise (Exit)\n                          )\n                    )\n                  | 11 -> (\n                      match String.unsafe_get s pos with\n                        | 'd' -> (\n                            if String.unsafe_get s (pos+1) = 'e' && String.unsafe_get s (pos+2) = 'l' && String.unsafe_get s (pos+3) = 'e' && String.unsafe_get s (pos+4) = 't' && String.unsafe_get s (pos+5) = 'e' && String.unsafe_get s (pos+6) = '_' && String.unsafe_get s (pos+7) = 'r' && String.unsafe_get s (pos+8) = 'e' && String.unsafe_get s (pos+9) = 'p' && String.unsafe_get s (pos+10) = 'o' then (\n                              4\n                            )\n                            else (\n                              raise (Exit)\n                            )\n                          )\n                        | 'p' -> (\n                            if String.unsafe_get s (pos+1) = 'u' && String.unsafe_get s (pos+2) = 'b' && String.unsafe_get s (pos+3) = 'l' && String.unsafe_get s (pos+4) = 'i' && String.unsafe_get s (pos+5) = 'c' && String.unsafe_get s (pos+6) = '_' && String.unsafe_get s (pos+7) = 'r' && String.unsafe_get s (pos+8) = 'e' && String.unsafe_get s (pos+9) = 'p' && String.unsafe_get s (pos+10) = 'o' then (\n                              1\n                            )\n                            else (\n                              raise (Exit)\n                            )\n                          )\n                        | 'r' -> (\n                            if String.unsafe_get s (pos+1) = 'e' && String.unsafe_get s (pos+2) = 'p' && String.unsafe_get s (pos+3) = 'o' && String.unsafe_get s (pos+4) = '_' && String.unsafe_get s (pos+5) = 's' && String.unsafe_get s (pos+6) = 't' && String.unsafe_get s (pos+7) = 'a' && String.unsafe_get s (pos+8) = 't' && String.unsafe_get s (pos+9) = 'u' && String.unsafe_get s (pos+10) = 's' then (\n                              3\n                            )\n                            else (\n                              raise (Exit)\n                            )\n                          )\n                        | _ -> (\n                            raise (Exit)\n                          )\n                    )\n                  | _ -> (\n                      raise (Exit)\n                    )\n              with Exit -> (\n                  Ag_oj_run.invalid_variant_tag (String.sub s pos len)\n                )\n          in\n          let i = Yojson.Safe.map_ident p f lb in\n          match i with\n            | 0 ->\n              Yojson.Safe.read_space p lb;\n              Yojson.Safe.read_gt p lb;\n              `User\n            | 1 ->\n              Yojson.Safe.read_space p lb;\n              Yojson.Safe.read_gt p lb;\n              `Public_repo\n            | 2 ->\n              Yojson.Safe.read_space p lb;\n              Yojson.Safe.read_gt p lb;\n              `Repo\n            | 3 ->\n              Yojson.Safe.read_space p lb;\n              Yojson.Safe.read_gt p lb;\n              `Repo_status\n            | 4 ->\n              Yojson.Safe.read_space p lb;\n              Yojson.Safe.read_gt p lb;\n              `Delete_repo\n            | 5 ->\n              Yojson.Safe.read_space p lb;\n              Yojson.Safe.read_gt p lb;\n              `Gist\n            | _ -> (\n                assert false\n              )\n        )\n      | `Double_quote -> (\n          let f =\n            fun s pos len ->\n              if pos < 0 || len < 0 || pos + len > String.length s then\n                invalid_arg \"out-of-bounds substring position or length\";\n              try\n                match len with\n                  | 4 -> (\n                      match String.unsafe_get s pos with\n                        | 'g' -> (\n                            if String.unsafe_get s (pos+1) = 'i' && String.unsafe_get s (pos+2) = 's' && String.unsafe_get s (pos+3) = 't' then (\n                              5\n                            )\n                            else (\n                              raise (Exit)\n                            )\n                          )\n                        | 'r' -> (\n                            if String.unsafe_get s (pos+1) = 'e' && String.unsafe_get s (pos+2) = 'p' && String.unsafe_get s (pos+3) = 'o' then (\n                              2\n                            )\n                            else (\n                              raise (Exit)\n                            )\n                          )\n                        | 'u' -> (\n                            if String.unsafe_get s (pos+1) = 's' && String.unsafe_get s (pos+2) = 'e' && String.unsafe_get s (pos+3) = 'r' then (\n                              0\n                            )\n                            else (\n                              raise (Exit)\n                            )\n                          )\n                        | _ -> (\n                            raise (Exit)\n                          )\n                    )\n                  | 11 -> (\n                      match String.unsafe_get s pos with\n                        | 'd' -> (\n                            if String.unsafe_get s (pos+1) = 'e' && String.unsafe_get s (pos+2) = 'l' && String.unsafe_get s (pos+3) = 'e' && String.unsafe_get s (pos+4) = 't' && String.unsafe_get s (pos+5) = 'e' && String.unsafe_get s (pos+6) = '_' && String.unsafe_get s (pos+7) = 'r' && String.unsafe_get s (pos+8) = 'e' && String.unsafe_get s (pos+9) = 'p' && String.unsafe_get s (pos+10) = 'o' then (\n                              4\n                            )\n                            else (\n                              raise (Exit)\n                            )\n                          )\n                        | 'p' -> (\n                            if String.unsafe_get s (pos+1) = 'u' && String.unsafe_get s (pos+2) = 'b' && String.unsafe_get s (pos+3) = 'l' && String.unsafe_get s (pos+4) = 'i' && String.unsafe_get s (pos+5) = 'c' && String.unsafe_get s (pos+6) = '_' && String.unsafe_get s (pos+7) = 'r' && String.unsafe_get s (pos+8) = 'e' && String.unsafe_get s (pos+9) = 'p' && String.unsafe_get s (pos+10) = 'o' then (\n                              1\n                            )\n                            else (\n                              raise (Exit)\n                            )\n                          )\n                        | 'r' -> (\n                            if String.unsafe_get s (pos+1) = 'e' && String.unsafe_get s (pos+2) = 'p' && String.unsafe_get s (pos+3) = 'o' && String.unsafe_get s (pos+4) = '_' && String.unsafe_get s (pos+5) = 's' && String.unsafe_get s (pos+6) = 't' && String.unsafe_get s (pos+7) = 'a' && String.unsafe_get s (pos+8) = 't' && String.unsafe_get s (pos+9) = 'u' && String.unsafe_get s (pos+10) = 's' then (\n                              3\n                            )\n                            else (\n                              raise (Exit)\n                            )\n                          )\n                        | _ -> (\n                            raise (Exit)\n                          )\n                    )\n                  | _ -> (\n                      raise (Exit)\n                    )\n              with Exit -> (\n                  Ag_oj_run.invalid_variant_tag (String.sub s pos len)\n                )\n          in\n          let i = Yojson.Safe.map_string p f lb in\n          match i with\n            | 0 ->\n              `User\n            | 1 ->\n              `Public_repo\n            | 2 ->\n              `Repo\n            | 3 ->\n              `Repo_status\n            | 4 ->\n              `Delete_repo\n            | 5 ->\n              `Gist\n            | _ -> (\n                assert false\n              )\n        )\n      | `Square_bracket -> (\n          Yojson.Safe.read_space p lb;\n          let f =\n            fun s pos len ->\n              if pos < 0 || len < 0 || pos + len > String.length s then\n                invalid_arg \"out-of-bounds substring position or length\";\n              Ag_oj_run.invalid_variant_tag (String.sub s pos len)\n          in\n          let i = Yojson.Safe.map_ident p f lb in\n          match i with\n            | _ -> (\n                assert false\n              )\n        )\n)\nlet scope_of_string s =\n  read_scope (Yojson.Safe.init_lexer ()) (Lexing.from_string s)\nlet write_app = (\n  fun ob x ->\n    Bi_outbuf.add_char ob '{';\n    let is_first = ref true in\n    if !is_first then\n      is_first := false\n    else\n      Bi_outbuf.add_char ob ',';\n    Bi_outbuf.add_string ob \"\\\"name\\\":\";\n    (\n      Yojson.Safe.write_string\n    )\n      ob x.app_name;\n    if !is_first then\n      is_first := false\n    else\n      Bi_outbuf.add_char ob ',';\n    Bi_outbuf.add_string ob \"\\\"url\\\":\";\n    (\n      Yojson.Safe.write_string\n    )\n      ob x.app_url;\n    Bi_outbuf.add_char ob '}';\n)\nlet string_of_app ?(len = 1024) x =\n  let ob = Bi_outbuf.create len in\n  write_app ob x;\n  Bi_outbuf.contents ob\nlet read_app = (\n  fun p lb ->\n    Yojson.Safe.read_space p lb;\n    Yojson.Safe.read_lcurl p lb;\n    let x =\n      {\n        app_name = Obj.magic 0.0;\n        app_url = Obj.magic 0.0;\n      }\n    in\n    let bits0 = ref 0 in\n    try\n      Yojson.Safe.read_space p lb;\n      Yojson.Safe.read_object_end lb;\n      Yojson.Safe.read_space p lb;\n      let f =\n        fun s pos len ->\n          if pos < 0 || len < 0 || pos + len > String.length s then\n            invalid_arg \"out-of-bounds substring position or length\";\n          match len with\n            | 3 -> (\n                if String.unsafe_get s pos = 'u' && String.unsafe_get s (pos+1) = 'r' && String.unsafe_get s (pos+2) = 'l' then (\n                  1\n                )\n                else (\n                  -1\n                )\n              )\n            | 4 -> (\n                if String.unsafe_get s pos = 'n' && String.unsafe_get s (pos+1) = 'a' && String.unsafe_get s (pos+2) = 'm' && String.unsafe_get s (pos+3) = 'e' then (\n                  0\n                )\n                else (\n                  -1\n                )\n              )\n            | _ -> (\n                -1\n              )\n      in\n      let i = Yojson.Safe.map_ident p f lb in\n      Ag_oj_run.read_until_field_value p lb;\n      (\n        match i with\n          | 0 ->\n            let v =\n              (\n                Ag_oj_run.read_string\n              ) p lb\n            in\n            Obj.set_field (Obj.repr x) 0 (Obj.repr v);\n            bits0 := !bits0 lor 0x1;\n          | 1 ->\n            let v =\n              (\n                Ag_oj_run.read_string\n              ) p lb\n            in\n            Obj.set_field (Obj.repr x) 1 (Obj.repr v);\n            bits0 := !bits0 lor 0x2;\n          | _ -> (\n              Yojson.Safe.skip_json p lb\n            )\n      );\n      while true do\n        Yojson.Safe.read_space p lb;\n        Yojson.Safe.read_object_sep p lb;\n        Yojson.Safe.read_space p lb;\n        let f =\n          fun s pos len ->\n            if pos < 0 || len < 0 || pos + len > String.length s then\n              invalid_arg \"out-of-bounds substring position or length\";\n            match len with\n              | 3 -> (\n                  if String.unsafe_get s pos = 'u' && String.unsafe_get s (pos+1) = 'r' && String.unsafe_get s (pos+2) = 'l' then (\n                    1\n                  )\n                  else (\n                    -1\n                  )\n                )\n              | 4 -> (\n                  if String.unsafe_get s pos = 'n' && String.unsafe_get s (pos+1) = 'a' && String.unsafe_get s (pos+2) = 'm' && String.unsafe_get s (pos+3) = 'e' then (\n                    0\n                  )\n                  else (\n                    -1\n                  )\n                )\n              | _ -> (\n                  -1\n                )\n        in\n        let i = Yojson.Safe.map_ident p f lb in\n        Ag_oj_run.read_until_field_value p lb;\n        (\n          match i with\n            | 0 ->\n              let v =\n                (\n                  Ag_oj_run.read_string\n                ) p lb\n              in\n              Obj.set_field (Obj.repr x) 0 (Obj.repr v);\n              bits0 := !bits0 lor 0x1;\n            | 1 ->\n              let v =\n                (\n                  Ag_oj_run.read_string\n                ) p lb\n              in\n              Obj.set_field (Obj.repr x) 1 (Obj.repr v);\n              bits0 := !bits0 lor 0x2;\n            | _ -> (\n                Yojson.Safe.skip_json p lb\n              )\n        );\n      done;\n      assert false;\n    with Yojson.End_of_object -> (\n        if !bits0 <> 0x3 then Ag_oj_run.missing_fields [| !bits0 |] [| \"name\"; \"url\" |];\n        Ag_oj_run.identity x\n      )\n)\nlet app_of_string s =\n  read_app (Yojson.Safe.init_lexer ()) (Lexing.from_string s)\nlet write__1 = (\n  Ag_oj_run.write_list (\n    write_scope\n  )\n)\nlet string_of__1 ?(len = 1024) x =\n  let ob = Bi_outbuf.create len in\n  write__1 ob x;\n  Bi_outbuf.contents ob\nlet read__1 = (\n  Ag_oj_run.read_list (\n    read_scope\n  )\n)\nlet _1_of_string s =\n  read__1 (Yojson.Safe.init_lexer ()) (Lexing.from_string s)\nlet write_authorization_request = (\n  fun ob x ->\n    Bi_outbuf.add_char ob '{';\n    let is_first = ref true in\n    if !is_first then\n      is_first := false\n    else\n      Bi_outbuf.add_char ob ',';\n    Bi_outbuf.add_string ob \"\\\"scopes\\\":\";\n    (\n      write__1\n    )\n      ob x.auth_req_scopes;\n    if !is_first then\n      is_first := false\n    else\n      Bi_outbuf.add_char ob ',';\n    Bi_outbuf.add_string ob \"\\\"note\\\":\";\n    (\n      Yojson.Safe.write_string\n    )\n      ob x.auth_req_note;\n    Bi_outbuf.add_char ob '}';\n)\nlet string_of_authorization_request ?(len = 1024) x =\n  let ob = Bi_outbuf.create len in\n  write_authorization_request ob x;\n  Bi_outbuf.contents ob\nlet read_authorization_request = (\n  fun p lb ->\n    Yojson.Safe.read_space p lb;\n    Yojson.Safe.read_lcurl p lb;\n    let x =\n      {\n        auth_req_scopes = Obj.magic 0.0;\n        auth_req_note = Obj.magic 0.0;\n      }\n    in\n    let bits0 = ref 0 in\n    try\n      Yojson.Safe.read_space p lb;\n      Yojson.Safe.read_object_end lb;\n      Yojson.Safe.read_space p lb;\n      let f =\n        fun s pos len ->\n          if pos < 0 || len < 0 || pos + len > String.length s then\n            invalid_arg \"out-of-bounds substring position or length\";\n          match len with\n            | 4 -> (\n                if String.unsafe_get s pos = 'n' && String.unsafe_get s (pos+1) = 'o' && String.unsafe_get s (pos+2) = 't' && String.unsafe_get s (pos+3) = 'e' then (\n                  1\n                )\n                else (\n                  -1\n                )\n              )\n            | 6 -> (\n                if String.unsafe_get s pos = 's' && String.unsafe_get s (pos+1) = 'c' && String.unsafe_get s (pos+2) = 'o' && String.unsafe_get s (pos+3) = 'p' && String.unsafe_get s (pos+4) = 'e' && String.unsafe_get s (pos+5) = 's' then (\n                  0\n                )\n                else (\n                  -1\n                )\n              )\n            | _ -> (\n                -1\n              )\n      in\n      let i = Yojson.Safe.map_ident p f lb in\n      Ag_oj_run.read_until_field_value p lb;\n      (\n        match i with\n          | 0 ->\n            let v =\n              (\n                read__1\n              ) p lb\n            in\n            Obj.set_field (Obj.repr x) 0 (Obj.repr v);\n            bits0 := !bits0 lor 0x1;\n          | 1 ->\n            let v =\n              (\n                Ag_oj_run.read_string\n              ) p lb\n            in\n            Obj.set_field (Obj.repr x) 1 (Obj.repr v);\n            bits0 := !bits0 lor 0x2;\n          | _ -> (\n              Yojson.Safe.skip_json p lb\n            )\n      );\n      while true do\n        Yojson.Safe.read_space p lb;\n        Yojson.Safe.read_object_sep p lb;\n        Yojson.Safe.read_space p lb;\n        let f =\n          fun s pos len ->\n            if pos < 0 || len < 0 || pos + len > String.length s then\n              invalid_arg \"out-of-bounds substring position or length\";\n            match len with\n              | 4 -> (\n                  if String.unsafe_get s pos = 'n' && String.unsafe_get s (pos+1) = 'o' && String.unsafe_get s (pos+2) = 't' && String.unsafe_get s (pos+3) = 'e' then (\n                    1\n                  )\n                  else (\n                    -1\n                  )\n                )\n              | 6 -> (\n                  if String.unsafe_get s pos = 's' && String.unsafe_get s (pos+1) = 'c' && String.unsafe_get s (pos+2) = 'o' && String.unsafe_get s (pos+3) = 'p' && String.unsafe_get s (pos+4) = 'e' && String.unsafe_get s (pos+5) = 's' then (\n                    0\n                  )\n                  else (\n                    -1\n                  )\n                )\n              | _ -> (\n                  -1\n                )\n        in\n        let i = Yojson.Safe.map_ident p f lb in\n        Ag_oj_run.read_until_field_value p lb;\n        (\n          match i with\n            | 0 ->\n              let v =\n                (\n                  read__1\n                ) p lb\n              in\n              Obj.set_field (Obj.repr x) 0 (Obj.repr v);\n              bits0 := !bits0 lor 0x1;\n            | 1 ->\n              let v =\n                (\n                  Ag_oj_run.read_string\n                ) p lb\n              in\n              Obj.set_field (Obj.repr x) 1 (Obj.repr v);\n              bits0 := !bits0 lor 0x2;\n            | _ -> (\n                Yojson.Safe.skip_json p lb\n              )\n        );\n      done;\n      assert false;\n    with Yojson.End_of_object -> (\n        if !bits0 <> 0x3 then Ag_oj_run.missing_fields [| !bits0 |] [| \"scopes\"; \"note\" |];\n        Ag_oj_run.identity x\n      )\n)\nlet authorization_request_of_string s =\n  read_authorization_request (Yojson.Safe.init_lexer ()) (Lexing.from_string s)\nlet write__2 = (\n  Ag_oj_run.write_option (\n    Yojson.Safe.write_string\n  )\n)\nlet string_of__2 ?(len = 1024) x =\n  let ob = Bi_outbuf.create len in\n  write__2 ob x;\n  Bi_outbuf.contents ob\nlet read__2 = (\n  fun p lb ->\n    Yojson.Safe.read_space p lb;\n    match Yojson.Safe.start_any_variant p lb with\n      | `Edgy_bracket -> (\n          Yojson.Safe.read_space p lb;\n          let f =\n            fun s pos len ->\n              if pos < 0 || len < 0 || pos + len > String.length s then\n                invalid_arg \"out-of-bounds substring position or length\";\n              try\n                if len = 4 then (\n                  match String.unsafe_get s pos with\n                    | 'N' -> (\n                        if String.unsafe_get s (pos+1) = 'o' && String.unsafe_get s (pos+2) = 'n' && String.unsafe_get s (pos+3) = 'e' then (\n                          0\n                        )\n                        else (\n                          raise (Exit)\n                        )\n                      )\n                    | 'S' -> (\n                        if String.unsafe_get s (pos+1) = 'o' && String.unsafe_get s (pos+2) = 'm' && String.unsafe_get s (pos+3) = 'e' then (\n                          1\n                        )\n                        else (\n                          raise (Exit)\n                        )\n                      )\n                    | _ -> (\n                        raise (Exit)\n                      )\n                )\n                else (\n                  raise (Exit)\n                )\n              with Exit -> (\n                  Ag_oj_run.invalid_variant_tag (String.sub s pos len)\n                )\n          in\n          let i = Yojson.Safe.map_ident p f lb in\n          match i with\n            | 0 ->\n              Yojson.Safe.read_space p lb;\n              Yojson.Safe.read_gt p lb;\n              None\n            | 1 ->\n              Ag_oj_run.read_until_field_value p lb;\n              let x = (\n                  Ag_oj_run.read_string\n                ) p lb\n              in\n              Yojson.Safe.read_space p lb;\n              Yojson.Safe.read_gt p lb;\n              Some x\n            | _ -> (\n                assert false\n              )\n        )\n      | `Double_quote -> (\n          let f =\n            fun s pos len ->\n              if pos < 0 || len < 0 || pos + len > String.length s then\n                invalid_arg \"out-of-bounds substring position or length\";\n              try\n                if len = 4 && String.unsafe_get s pos = 'N' && String.unsafe_get s (pos+1) = 'o' && String.unsafe_get s (pos+2) = 'n' && String.unsafe_get s (pos+3) = 'e' then (\n                  0\n                )\n                else (\n                  raise (Exit)\n                )\n              with Exit -> (\n                  Ag_oj_run.invalid_variant_tag (String.sub s pos len)\n                )\n          in\n          let i = Yojson.Safe.map_string p f lb in\n          match i with\n            | 0 ->\n              None\n            | _ -> (\n                assert false\n              )\n        )\n      | `Square_bracket -> (\n          Yojson.Safe.read_space p lb;\n          let f =\n            fun s pos len ->\n              if pos < 0 || len < 0 || pos + len > String.length s then\n                invalid_arg \"out-of-bounds substring position or length\";\n              try\n                if len = 4 && String.unsafe_get s pos = 'S' && String.unsafe_get s (pos+1) = 'o' && String.unsafe_get s (pos+2) = 'm' && String.unsafe_get s (pos+3) = 'e' then (\n                  0\n                )\n                else (\n                  raise (Exit)\n                )\n              with Exit -> (\n                  Ag_oj_run.invalid_variant_tag (String.sub s pos len)\n                )\n          in\n          let i = Yojson.Safe.map_ident p f lb in\n          match i with\n            | 0 ->\n              Yojson.Safe.read_space p lb;\n              Yojson.Safe.read_comma p lb;\n              Yojson.Safe.read_space p lb;\n              let x = (\n                  Ag_oj_run.read_string\n                ) p lb\n              in\n              Yojson.Safe.read_space p lb;\n              Yojson.Safe.read_rbr p lb;\n              Some x\n            | _ -> (\n                assert false\n              )\n        )\n)\nlet _2_of_string s =\n  read__2 (Yojson.Safe.init_lexer ()) (Lexing.from_string s)\nlet write_authorization_response = (\n  fun ob x ->\n    Bi_outbuf.add_char ob '{';\n    let is_first = ref true in\n    if !is_first then\n      is_first := false\n    else\n      Bi_outbuf.add_char ob ',';\n    Bi_outbuf.add_string ob \"\\\"scopes\\\":\";\n    (\n      write__1\n    )\n      ob x.scopes;\n    if !is_first then\n      is_first := false\n    else\n      Bi_outbuf.add_char ob ',';\n    Bi_outbuf.add_string ob \"\\\"token\\\":\";\n    (\n      Yojson.Safe.write_string\n    )\n      ob x.token;\n    if !is_first then\n      is_first := false\n    else\n      Bi_outbuf.add_char ob ',';\n    Bi_outbuf.add_string ob \"\\\"app\\\":\";\n    (\n      write_app\n    )\n      ob x.app;\n    if !is_first then\n      is_first := false\n    else\n      Bi_outbuf.add_char ob ',';\n    Bi_outbuf.add_string ob \"\\\"url\\\":\";\n    (\n      Yojson.Safe.write_string\n    )\n      ob x.url;\n    if !is_first then\n      is_first := false\n    else\n      Bi_outbuf.add_char ob ',';\n    Bi_outbuf.add_string ob \"\\\"id\\\":\";\n    (\n      Yojson.Safe.write_int\n    )\n      ob x.id;\n    (match x.note with None -> () | Some x ->\n      if !is_first then\n        is_first := false\n      else\n        Bi_outbuf.add_char ob ',';\n      Bi_outbuf.add_string ob \"\\\"note\\\":\";\n      (\n        Yojson.Safe.write_string\n      )\n        ob x;\n    );\n    (match x.note_url with None -> () | Some x ->\n      if !is_first then\n        is_first := false\n      else\n        Bi_outbuf.add_char ob ',';\n      Bi_outbuf.add_string ob \"\\\"note_url\\\":\";\n      (\n        Yojson.Safe.write_string\n      )\n        ob x;\n    );\n    Bi_outbuf.add_char ob '}';\n)\nlet string_of_authorization_response ?(len = 1024) x =\n  let ob = Bi_outbuf.create len in\n  write_authorization_response ob x;\n  Bi_outbuf.contents ob\nlet read_authorization_response = (\n  fun p lb ->\n    Yojson.Safe.read_space p lb;\n    Yojson.Safe.read_lcurl p lb;\n    let x =\n      {\n        scopes = Obj.magic 0.0;\n        token = Obj.magic 0.0;\n        app = Obj.magic 0.0;\n        url = Obj.magic 0.0;\n        id = Obj.magic 0.0;\n        note = None;\n        note_url = None;\n      }\n    in\n    let bits0 = ref 0 in\n    try\n      Yojson.Safe.read_space p lb;\n      Yojson.Safe.read_object_end lb;\n      Yojson.Safe.read_space p lb;\n      let f =\n        fun s pos len ->\n          if pos < 0 || len < 0 || pos + len > String.length s then\n            invalid_arg \"out-of-bounds substring position or length\";\n          match len with\n            | 2 -> (\n                if String.unsafe_get s pos = 'i' && String.unsafe_get s (pos+1) = 'd' then (\n                  4\n                )\n                else (\n                  -1\n                )\n              )\n            | 3 -> (\n                match String.unsafe_get s pos with\n                  | 'a' -> (\n                      if String.unsafe_get s (pos+1) = 'p' && String.unsafe_get s (pos+2) = 'p' then (\n                        2\n                      )\n                      else (\n                        -1\n                      )\n                    )\n                  | 'u' -> (\n                      if String.unsafe_get s (pos+1) = 'r' && String.unsafe_get s (pos+2) = 'l' then (\n                        3\n                      )\n                      else (\n                        -1\n                      )\n                    )\n                  | _ -> (\n                      -1\n                    )\n              )\n            | 4 -> (\n                if String.unsafe_get s pos = 'n' && String.unsafe_get s (pos+1) = 'o' && String.unsafe_get s (pos+2) = 't' && String.unsafe_get s (pos+3) = 'e' then (\n                  5\n                )\n                else (\n                  -1\n                )\n              )\n            | 5 -> (\n                if String.unsafe_get s pos = 't' && String.unsafe_get s (pos+1) = 'o' && String.unsafe_get s (pos+2) = 'k' && String.unsafe_get s (pos+3) = 'e' && String.unsafe_get s (pos+4) = 'n' then (\n                  1\n                )\n                else (\n                  -1\n                )\n              )\n            | 6 -> (\n                if String.unsafe_get s pos = 's' && String.unsafe_get s (pos+1) = 'c' && String.unsafe_get s (pos+2) = 'o' && String.unsafe_get s (pos+3) = 'p' && String.unsafe_get s (pos+4) = 'e' && String.unsafe_get s (pos+5) = 's' then (\n                  0\n                )\n                else (\n                  -1\n                )\n              )\n            | 8 -> (\n                if String.unsafe_get s pos = 'n' && String.unsafe_get s (pos+1) = 'o' && String.unsafe_get s (pos+2) = 't' && String.unsafe_get s (pos+3) = 'e' && String.unsafe_get s (pos+4) = '_' && String.unsafe_get s (pos+5) = 'u' && String.unsafe_get s (pos+6) = 'r' && String.unsafe_get s (pos+7) = 'l' then (\n                  6\n                )\n                else (\n                  -1\n                )\n              )\n            | _ -> (\n                -1\n              )\n      in\n      let i = Yojson.Safe.map_ident p f lb in\n      Ag_oj_run.read_until_field_value p lb;\n      (\n        match i with\n          | 0 ->\n            let v =\n              (\n                read__1\n              ) p lb\n            in\n            Obj.set_field (Obj.repr x) 0 (Obj.repr v);\n            bits0 := !bits0 lor 0x1;\n          | 1 ->\n            let v =\n              (\n                Ag_oj_run.read_string\n              ) p lb\n            in\n            Obj.set_field (Obj.repr x) 1 (Obj.repr v);\n            bits0 := !bits0 lor 0x2;\n          | 2 ->\n            let v =\n              (\n                read_app\n              ) p lb\n            in\n            Obj.set_field (Obj.repr x) 2 (Obj.repr v);\n            bits0 := !bits0 lor 0x4;\n          | 3 ->\n            let v =\n              (\n                Ag_oj_run.read_string\n              ) p lb\n            in\n            Obj.set_field (Obj.repr x) 3 (Obj.repr v);\n            bits0 := !bits0 lor 0x8;\n          | 4 ->\n            let v =\n              (\n                Ag_oj_run.read_int\n              ) p lb\n            in\n            Obj.set_field (Obj.repr x) 4 (Obj.repr v);\n            bits0 := !bits0 lor 0x10;\n          | 5 ->\n            if not (Yojson.Safe.read_null_if_possible p lb) then (\n              let v =\n                Some (\n                  (\n                    Ag_oj_run.read_string\n                  ) p lb\n                )\n              in\n              Obj.set_field (Obj.repr x) 5 (Obj.repr v);\n            )\n          | 6 ->\n            if not (Yojson.Safe.read_null_if_possible p lb) then (\n              let v =\n                Some (\n                  (\n                    Ag_oj_run.read_string\n                  ) p lb\n                )\n              in\n              Obj.set_field (Obj.repr x) 6 (Obj.repr v);\n            )\n          | _ -> (\n              Yojson.Safe.skip_json p lb\n            )\n      );\n      while true do\n        Yojson.Safe.read_space p lb;\n        Yojson.Safe.read_object_sep p lb;\n        Yojson.Safe.read_space p lb;\n        let f =\n          fun s pos len ->\n            if pos < 0 || len < 0 || pos + len > String.length s then\n              invalid_arg \"out-of-bounds substring position or length\";\n            match len with\n              | 2 -> (\n                  if String.unsafe_get s pos = 'i' && String.unsafe_get s (pos+1) = 'd' then (\n                    4\n                  )\n                  else (\n                    -1\n                  )\n                )\n              | 3 -> (\n                  match String.unsafe_get s pos with\n                    | 'a' -> (\n                        if String.unsafe_get s (pos+1) = 'p' && String.unsafe_get s (pos+2) = 'p' then (\n                          2\n                        )\n                        else (\n                          -1\n                        )\n                      )\n                    | 'u' -> (\n                        if String.unsafe_get s (pos+1) = 'r' && String.unsafe_get s (pos+2) = 'l' then (\n                          3\n                        )\n                        else (\n                          -1\n                        )\n                      )\n                    | _ -> (\n                        -1\n                      )\n                )\n              | 4 -> (\n                  if String.unsafe_get s pos = 'n' && String.unsafe_get s (pos+1) = 'o' && String.unsafe_get s (pos+2) = 't' && String.unsafe_get s (pos+3) = 'e' then (\n                    5\n                  )\n                  else (\n                    -1\n                  )\n                )\n              | 5 -> (\n                  if String.unsafe_get s pos = 't' && String.unsafe_get s (pos+1) = 'o' && String.unsafe_get s (pos+2) = 'k' && String.unsafe_get s (pos+3) = 'e' && String.unsafe_get s (pos+4) = 'n' then (\n                    1\n                  )\n                  else (\n                    -1\n                  )\n                )\n              | 6 -> (\n                  if String.unsafe_get s pos = 's' && String.unsafe_get s (pos+1) = 'c' && String.unsafe_get s (pos+2) = 'o' && String.unsafe_get s (pos+3) = 'p' && String.unsafe_get s (pos+4) = 'e' && String.unsafe_get s (pos+5) = 's' then (\n                    0\n                  )\n                  else (\n                    -1\n                  )\n                )\n              | 8 -> (\n                  if String.unsafe_get s pos = 'n' && String.unsafe_get s (pos+1) = 'o' && String.unsafe_get s (pos+2) = 't' && String.unsafe_get s (pos+3) = 'e' && String.unsafe_get s (pos+4) = '_' && String.unsafe_get s (pos+5) = 'u' && String.unsafe_get s (pos+6) = 'r' && String.unsafe_get s (pos+7) = 'l' then (\n                    6\n                  )\n                  else (\n                    -1\n                  )\n                )\n              | _ -> (\n                  -1\n                )\n        in\n        let i = Yojson.Safe.map_ident p f lb in\n        Ag_oj_run.read_until_field_value p lb;\n        (\n          match i with\n            | 0 ->\n              let v =\n                (\n                  read__1\n                ) p lb\n              in\n              Obj.set_field (Obj.repr x) 0 (Obj.repr v);\n              bits0 := !bits0 lor 0x1;\n            | 1 ->\n              let v =\n                (\n                  Ag_oj_run.read_string\n                ) p lb\n              in\n              Obj.set_field (Obj.repr x) 1 (Obj.repr v);\n              bits0 := !bits0 lor 0x2;\n            | 2 ->\n              let v =\n                (\n                  read_app\n                ) p lb\n              in\n              Obj.set_field (Obj.repr x) 2 (Obj.repr v);\n              bits0 := !bits0 lor 0x4;\n            | 3 ->\n              let v =\n                (\n                  Ag_oj_run.read_string\n                ) p lb\n              in\n              Obj.set_field (Obj.repr x) 3 (Obj.repr v);\n              bits0 := !bits0 lor 0x8;\n            | 4 ->\n              let v =\n                (\n                  Ag_oj_run.read_int\n                ) p lb\n              in\n              Obj.set_field (Obj.repr x) 4 (Obj.repr v);\n              bits0 := !bits0 lor 0x10;\n            | 5 ->\n              if not (Yojson.Safe.read_null_if_possible p lb) then (\n                let v =\n                  Some (\n                    (\n                      Ag_oj_run.read_string\n                    ) p lb\n                  )\n                in\n                Obj.set_field (Obj.repr x) 5 (Obj.repr v);\n              )\n            | 6 ->\n              if not (Yojson.Safe.read_null_if_possible p lb) then (\n                let v =\n                  Some (\n                    (\n                      Ag_oj_run.read_string\n                    ) p lb\n                  )\n                in\n                Obj.set_field (Obj.repr x) 6 (Obj.repr v);\n              )\n            | _ -> (\n                Yojson.Safe.skip_json p lb\n              )\n        );\n      done;\n      assert false;\n    with Yojson.End_of_object -> (\n        if !bits0 <> 0x1f then Ag_oj_run.missing_fields [| !bits0 |] [| \"scopes\"; \"token\"; \"app\"; \"url\"; \"id\" |];\n        Ag_oj_run.identity x\n      )\n)\nlet authorization_response_of_string s =\n  read_authorization_response (Yojson.Safe.init_lexer ()) (Lexing.from_string s)\n"
  },
  {
    "path": "code/json/github_j.mli",
    "content": "(* Auto-generated from \"github.atd\" *)\n\n\ntype scope = Github_t.scope\n\ntype app = Github_t.app = {\n  app_name (*atd name *): string;\n  app_url (*atd url *): string\n}\n\ntype authorization_request = Github_t.authorization_request = {\n  auth_req_scopes (*atd scopes *): scope list;\n  auth_req_note (*atd note *): string\n}\n\ntype authorization_response = Github_t.authorization_response = {\n  scopes: scope list;\n  token: string;\n  app: app;\n  url: string;\n  id: int;\n  note: string option;\n  note_url: string option\n}\n\nval write_scope :\n  Bi_outbuf.t -> scope -> unit\n  (** Output a JSON value of type {!scope}. *)\n\nval string_of_scope :\n  ?len:int -> scope -> string\n  (** Serialize a value of type {!scope}\n      into a JSON string.\n      @param len specifies the initial length\n                 of the buffer used internally.\n                 Default: 1024. *)\n\nval read_scope :\n  Yojson.Safe.lexer_state -> Lexing.lexbuf -> scope\n  (** Input JSON data of type {!scope}. *)\n\nval scope_of_string :\n  string -> scope\n  (** Deserialize JSON data of type {!scope}. *)\n\nval write_app :\n  Bi_outbuf.t -> app -> unit\n  (** Output a JSON value of type {!app}. *)\n\nval string_of_app :\n  ?len:int -> app -> string\n  (** Serialize a value of type {!app}\n      into a JSON string.\n      @param len specifies the initial length\n                 of the buffer used internally.\n                 Default: 1024. *)\n\nval read_app :\n  Yojson.Safe.lexer_state -> Lexing.lexbuf -> app\n  (** Input JSON data of type {!app}. *)\n\nval app_of_string :\n  string -> app\n  (** Deserialize JSON data of type {!app}. *)\n\nval write_authorization_request :\n  Bi_outbuf.t -> authorization_request -> unit\n  (** Output a JSON value of type {!authorization_request}. *)\n\nval string_of_authorization_request :\n  ?len:int -> authorization_request -> string\n  (** Serialize a value of type {!authorization_request}\n      into a JSON string.\n      @param len specifies the initial length\n                 of the buffer used internally.\n                 Default: 1024. *)\n\nval read_authorization_request :\n  Yojson.Safe.lexer_state -> Lexing.lexbuf -> authorization_request\n  (** Input JSON data of type {!authorization_request}. *)\n\nval authorization_request_of_string :\n  string -> authorization_request\n  (** Deserialize JSON data of type {!authorization_request}. *)\n\nval write_authorization_response :\n  Bi_outbuf.t -> authorization_response -> unit\n  (** Output a JSON value of type {!authorization_response}. *)\n\nval string_of_authorization_response :\n  ?len:int -> authorization_response -> string\n  (** Serialize a value of type {!authorization_response}\n      into a JSON string.\n      @param len specifies the initial length\n                 of the buffer used internally.\n                 Default: 1024. *)\n\nval read_authorization_response :\n  Yojson.Safe.lexer_state -> Lexing.lexbuf -> authorization_response\n  (** Input JSON data of type {!authorization_response}. *)\n\nval authorization_response_of_string :\n  string -> authorization_response\n  (** Deserialize JSON data of type {!authorization_response}. *)\n\n"
  },
  {
    "path": "code/json/github_j_excerpt.mli",
    "content": "val string_of_authorization_request :\n  ?len:int -> authorization_request -> string\n  (** Serialize a value of type {!authorization_request}\n      into a JSON string.\n      @param len specifies the initial length\n                 of the buffer used internally.\n                 Default: 1024. *)\n\nval string_of_authorization_response :\n  ?len:int -> authorization_response -> string\n  (** Serialize a value of type {!authorization_response}\n      into a JSON string.\n      @param len specifies the initial length\n                 of the buffer used internally.\n                 Default: 1024. *)\n"
  },
  {
    "path": "code/json/github_org.atd",
    "content": "type org = {\n  login: string;\n  id: int;\n  url: string;\n  ?name: string option;\n  ?blog: string option;\n  ?email: string option;\n  public_repos: int\n}\n"
  },
  {
    "path": "code/json/github_org_info.ml",
    "content": "open Core.Std\n\nlet print_org file () =\n  let url = sprintf \"https://api.github.com/orgs/%s\" file in\n  Core_extended.Shell.run_full \"curl\" [url]\n  |> Github_org_j.org_of_string\n  |> fun org ->\n  let open Github_org_t in\n  let name = Option.value ~default:\"???\" org.name in\n  printf \"%s (%d) with %d public repos\\n\"\n    name org.id org.public_repos\n\nlet () =\n  Command.basic ~summary:\"Print Github organization information\"\n    Command.Spec.(empty +> anon (\"organization\" %: string))\n    print_org\n  |> Command.run\n"
  },
  {
    "path": "code/json/github_org_j.ml",
    "content": "(* Auto-generated from \"github_org.atd\" *)\n\n\ntype org = Github_org_t.org = {\n  login: string;\n  id: int;\n  url: string;\n  name: string option;\n  blog: string option;\n  email: string option;\n  public_repos: int\n}\n\nlet write__1 = (\n  Ag_oj_run.write_option (\n    Yojson.Safe.write_string\n  )\n)\nlet string_of__1 ?(len = 1024) x =\n  let ob = Bi_outbuf.create len in\n  write__1 ob x;\n  Bi_outbuf.contents ob\nlet read__1 = (\n  fun p lb ->\n    Yojson.Safe.read_space p lb;\n    match Yojson.Safe.start_any_variant p lb with\n      | `Edgy_bracket -> (\n          Yojson.Safe.read_space p lb;\n          let f =\n            fun s pos len ->\n              if pos < 0 || len < 0 || pos + len > String.length s then\n                invalid_arg \"out-of-bounds substring position or length\";\n              try\n                if len = 4 then (\n                  match String.unsafe_get s pos with\n                    | 'N' -> (\n                        if String.unsafe_get s (pos+1) = 'o' && String.unsafe_get s (pos+2) = 'n' && String.unsafe_get s (pos+3) = 'e' then (\n                          0\n                        )\n                        else (\n                          raise (Exit)\n                        )\n                      )\n                    | 'S' -> (\n                        if String.unsafe_get s (pos+1) = 'o' && String.unsafe_get s (pos+2) = 'm' && String.unsafe_get s (pos+3) = 'e' then (\n                          1\n                        )\n                        else (\n                          raise (Exit)\n                        )\n                      )\n                    | _ -> (\n                        raise (Exit)\n                      )\n                )\n                else (\n                  raise (Exit)\n                )\n              with Exit -> (\n                  Ag_oj_run.invalid_variant_tag (String.sub s pos len)\n                )\n          in\n          let i = Yojson.Safe.map_ident p f lb in\n          match i with\n            | 0 ->\n              Yojson.Safe.read_space p lb;\n              Yojson.Safe.read_gt p lb;\n              None\n            | 1 ->\n              Ag_oj_run.read_until_field_value p lb;\n              let x = (\n                  Ag_oj_run.read_string\n                ) p lb\n              in\n              Yojson.Safe.read_space p lb;\n              Yojson.Safe.read_gt p lb;\n              Some x\n            | _ -> (\n                assert false\n              )\n        )\n      | `Double_quote -> (\n          let f =\n            fun s pos len ->\n              if pos < 0 || len < 0 || pos + len > String.length s then\n                invalid_arg \"out-of-bounds substring position or length\";\n              try\n                if len = 4 && String.unsafe_get s pos = 'N' && String.unsafe_get s (pos+1) = 'o' && String.unsafe_get s (pos+2) = 'n' && String.unsafe_get s (pos+3) = 'e' then (\n                  0\n                )\n                else (\n                  raise (Exit)\n                )\n              with Exit -> (\n                  Ag_oj_run.invalid_variant_tag (String.sub s pos len)\n                )\n          in\n          let i = Yojson.Safe.map_string p f lb in\n          match i with\n            | 0 ->\n              None\n            | _ -> (\n                assert false\n              )\n        )\n      | `Square_bracket -> (\n          Yojson.Safe.read_space p lb;\n          let f =\n            fun s pos len ->\n              if pos < 0 || len < 0 || pos + len > String.length s then\n                invalid_arg \"out-of-bounds substring position or length\";\n              try\n                if len = 4 && String.unsafe_get s pos = 'S' && String.unsafe_get s (pos+1) = 'o' && String.unsafe_get s (pos+2) = 'm' && String.unsafe_get s (pos+3) = 'e' then (\n                  0\n                )\n                else (\n                  raise (Exit)\n                )\n              with Exit -> (\n                  Ag_oj_run.invalid_variant_tag (String.sub s pos len)\n                )\n          in\n          let i = Yojson.Safe.map_ident p f lb in\n          match i with\n            | 0 ->\n              Yojson.Safe.read_space p lb;\n              Yojson.Safe.read_comma p lb;\n              Yojson.Safe.read_space p lb;\n              let x = (\n                  Ag_oj_run.read_string\n                ) p lb\n              in\n              Yojson.Safe.read_space p lb;\n              Yojson.Safe.read_rbr p lb;\n              Some x\n            | _ -> (\n                assert false\n              )\n        )\n)\nlet _1_of_string s =\n  read__1 (Yojson.Safe.init_lexer ()) (Lexing.from_string s)\nlet write_org = (\n  fun ob x ->\n    Bi_outbuf.add_char ob '{';\n    let is_first = ref true in\n    if !is_first then\n      is_first := false\n    else\n      Bi_outbuf.add_char ob ',';\n    Bi_outbuf.add_string ob \"\\\"login\\\":\";\n    (\n      Yojson.Safe.write_string\n    )\n      ob x.login;\n    if !is_first then\n      is_first := false\n    else\n      Bi_outbuf.add_char ob ',';\n    Bi_outbuf.add_string ob \"\\\"id\\\":\";\n    (\n      Yojson.Safe.write_int\n    )\n      ob x.id;\n    if !is_first then\n      is_first := false\n    else\n      Bi_outbuf.add_char ob ',';\n    Bi_outbuf.add_string ob \"\\\"url\\\":\";\n    (\n      Yojson.Safe.write_string\n    )\n      ob x.url;\n    (match x.name with None -> () | Some x ->\n      if !is_first then\n        is_first := false\n      else\n        Bi_outbuf.add_char ob ',';\n      Bi_outbuf.add_string ob \"\\\"name\\\":\";\n      (\n        Yojson.Safe.write_string\n      )\n        ob x;\n    );\n    (match x.blog with None -> () | Some x ->\n      if !is_first then\n        is_first := false\n      else\n        Bi_outbuf.add_char ob ',';\n      Bi_outbuf.add_string ob \"\\\"blog\\\":\";\n      (\n        Yojson.Safe.write_string\n      )\n        ob x;\n    );\n    (match x.email with None -> () | Some x ->\n      if !is_first then\n        is_first := false\n      else\n        Bi_outbuf.add_char ob ',';\n      Bi_outbuf.add_string ob \"\\\"email\\\":\";\n      (\n        Yojson.Safe.write_string\n      )\n        ob x;\n    );\n    if !is_first then\n      is_first := false\n    else\n      Bi_outbuf.add_char ob ',';\n    Bi_outbuf.add_string ob \"\\\"public_repos\\\":\";\n    (\n      Yojson.Safe.write_int\n    )\n      ob x.public_repos;\n    Bi_outbuf.add_char ob '}';\n)\nlet string_of_org ?(len = 1024) x =\n  let ob = Bi_outbuf.create len in\n  write_org ob x;\n  Bi_outbuf.contents ob\nlet read_org = (\n  fun p lb ->\n    Yojson.Safe.read_space p lb;\n    Yojson.Safe.read_lcurl p lb;\n    let x =\n      {\n        login = Obj.magic 0.0;\n        id = Obj.magic 0.0;\n        url = Obj.magic 0.0;\n        name = None;\n        blog = None;\n        email = None;\n        public_repos = Obj.magic 0.0;\n      }\n    in\n    let bits0 = ref 0 in\n    try\n      Yojson.Safe.read_space p lb;\n      Yojson.Safe.read_object_end lb;\n      Yojson.Safe.read_space p lb;\n      let f =\n        fun s pos len ->\n          if pos < 0 || len < 0 || pos + len > String.length s then\n            invalid_arg \"out-of-bounds substring position or length\";\n          match len with\n            | 2 -> (\n                if String.unsafe_get s pos = 'i' && String.unsafe_get s (pos+1) = 'd' then (\n                  1\n                )\n                else (\n                  -1\n                )\n              )\n            | 3 -> (\n                if String.unsafe_get s pos = 'u' && String.unsafe_get s (pos+1) = 'r' && String.unsafe_get s (pos+2) = 'l' then (\n                  2\n                )\n                else (\n                  -1\n                )\n              )\n            | 4 -> (\n                match String.unsafe_get s pos with\n                  | 'b' -> (\n                      if String.unsafe_get s (pos+1) = 'l' && String.unsafe_get s (pos+2) = 'o' && String.unsafe_get s (pos+3) = 'g' then (\n                        4\n                      )\n                      else (\n                        -1\n                      )\n                    )\n                  | 'n' -> (\n                      if String.unsafe_get s (pos+1) = 'a' && String.unsafe_get s (pos+2) = 'm' && String.unsafe_get s (pos+3) = 'e' then (\n                        3\n                      )\n                      else (\n                        -1\n                      )\n                    )\n                  | _ -> (\n                      -1\n                    )\n              )\n            | 5 -> (\n                match String.unsafe_get s pos with\n                  | 'e' -> (\n                      if String.unsafe_get s (pos+1) = 'm' && String.unsafe_get s (pos+2) = 'a' && String.unsafe_get s (pos+3) = 'i' && String.unsafe_get s (pos+4) = 'l' then (\n                        5\n                      )\n                      else (\n                        -1\n                      )\n                    )\n                  | 'l' -> (\n                      if String.unsafe_get s (pos+1) = 'o' && String.unsafe_get s (pos+2) = 'g' && String.unsafe_get s (pos+3) = 'i' && String.unsafe_get s (pos+4) = 'n' then (\n                        0\n                      )\n                      else (\n                        -1\n                      )\n                    )\n                  | _ -> (\n                      -1\n                    )\n              )\n            | 12 -> (\n                if String.unsafe_get s pos = 'p' && String.unsafe_get s (pos+1) = 'u' && String.unsafe_get s (pos+2) = 'b' && String.unsafe_get s (pos+3) = 'l' && String.unsafe_get s (pos+4) = 'i' && String.unsafe_get s (pos+5) = 'c' && String.unsafe_get s (pos+6) = '_' && String.unsafe_get s (pos+7) = 'r' && String.unsafe_get s (pos+8) = 'e' && String.unsafe_get s (pos+9) = 'p' && String.unsafe_get s (pos+10) = 'o' && String.unsafe_get s (pos+11) = 's' then (\n                  6\n                )\n                else (\n                  -1\n                )\n              )\n            | _ -> (\n                -1\n              )\n      in\n      let i = Yojson.Safe.map_ident p f lb in\n      Ag_oj_run.read_until_field_value p lb;\n      (\n        match i with\n          | 0 ->\n            let v =\n              (\n                Ag_oj_run.read_string\n              ) p lb\n            in\n            Obj.set_field (Obj.repr x) 0 (Obj.repr v);\n            bits0 := !bits0 lor 0x1;\n          | 1 ->\n            let v =\n              (\n                Ag_oj_run.read_int\n              ) p lb\n            in\n            Obj.set_field (Obj.repr x) 1 (Obj.repr v);\n            bits0 := !bits0 lor 0x2;\n          | 2 ->\n            let v =\n              (\n                Ag_oj_run.read_string\n              ) p lb\n            in\n            Obj.set_field (Obj.repr x) 2 (Obj.repr v);\n            bits0 := !bits0 lor 0x4;\n          | 3 ->\n            if not (Yojson.Safe.read_null_if_possible p lb) then (\n              let v =\n                Some (\n                  (\n                    Ag_oj_run.read_string\n                  ) p lb\n                )\n              in\n              Obj.set_field (Obj.repr x) 3 (Obj.repr v);\n            )\n          | 4 ->\n            if not (Yojson.Safe.read_null_if_possible p lb) then (\n              let v =\n                Some (\n                  (\n                    Ag_oj_run.read_string\n                  ) p lb\n                )\n              in\n              Obj.set_field (Obj.repr x) 4 (Obj.repr v);\n            )\n          | 5 ->\n            if not (Yojson.Safe.read_null_if_possible p lb) then (\n              let v =\n                Some (\n                  (\n                    Ag_oj_run.read_string\n                  ) p lb\n                )\n              in\n              Obj.set_field (Obj.repr x) 5 (Obj.repr v);\n            )\n          | 6 ->\n            let v =\n              (\n                Ag_oj_run.read_int\n              ) p lb\n            in\n            Obj.set_field (Obj.repr x) 6 (Obj.repr v);\n            bits0 := !bits0 lor 0x8;\n          | _ -> (\n              Yojson.Safe.skip_json p lb\n            )\n      );\n      while true do\n        Yojson.Safe.read_space p lb;\n        Yojson.Safe.read_object_sep p lb;\n        Yojson.Safe.read_space p lb;\n        let f =\n          fun s pos len ->\n            if pos < 0 || len < 0 || pos + len > String.length s then\n              invalid_arg \"out-of-bounds substring position or length\";\n            match len with\n              | 2 -> (\n                  if String.unsafe_get s pos = 'i' && String.unsafe_get s (pos+1) = 'd' then (\n                    1\n                  )\n                  else (\n                    -1\n                  )\n                )\n              | 3 -> (\n                  if String.unsafe_get s pos = 'u' && String.unsafe_get s (pos+1) = 'r' && String.unsafe_get s (pos+2) = 'l' then (\n                    2\n                  )\n                  else (\n                    -1\n                  )\n                )\n              | 4 -> (\n                  match String.unsafe_get s pos with\n                    | 'b' -> (\n                        if String.unsafe_get s (pos+1) = 'l' && String.unsafe_get s (pos+2) = 'o' && String.unsafe_get s (pos+3) = 'g' then (\n                          4\n                        )\n                        else (\n                          -1\n                        )\n                      )\n                    | 'n' -> (\n                        if String.unsafe_get s (pos+1) = 'a' && String.unsafe_get s (pos+2) = 'm' && String.unsafe_get s (pos+3) = 'e' then (\n                          3\n                        )\n                        else (\n                          -1\n                        )\n                      )\n                    | _ -> (\n                        -1\n                      )\n                )\n              | 5 -> (\n                  match String.unsafe_get s pos with\n                    | 'e' -> (\n                        if String.unsafe_get s (pos+1) = 'm' && String.unsafe_get s (pos+2) = 'a' && String.unsafe_get s (pos+3) = 'i' && String.unsafe_get s (pos+4) = 'l' then (\n                          5\n                        )\n                        else (\n                          -1\n                        )\n                      )\n                    | 'l' -> (\n                        if String.unsafe_get s (pos+1) = 'o' && String.unsafe_get s (pos+2) = 'g' && String.unsafe_get s (pos+3) = 'i' && String.unsafe_get s (pos+4) = 'n' then (\n                          0\n                        )\n                        else (\n                          -1\n                        )\n                      )\n                    | _ -> (\n                        -1\n                      )\n                )\n              | 12 -> (\n                  if String.unsafe_get s pos = 'p' && String.unsafe_get s (pos+1) = 'u' && String.unsafe_get s (pos+2) = 'b' && String.unsafe_get s (pos+3) = 'l' && String.unsafe_get s (pos+4) = 'i' && String.unsafe_get s (pos+5) = 'c' && String.unsafe_get s (pos+6) = '_' && String.unsafe_get s (pos+7) = 'r' && String.unsafe_get s (pos+8) = 'e' && String.unsafe_get s (pos+9) = 'p' && String.unsafe_get s (pos+10) = 'o' && String.unsafe_get s (pos+11) = 's' then (\n                    6\n                  )\n                  else (\n                    -1\n                  )\n                )\n              | _ -> (\n                  -1\n                )\n        in\n        let i = Yojson.Safe.map_ident p f lb in\n        Ag_oj_run.read_until_field_value p lb;\n        (\n          match i with\n            | 0 ->\n              let v =\n                (\n                  Ag_oj_run.read_string\n                ) p lb\n              in\n              Obj.set_field (Obj.repr x) 0 (Obj.repr v);\n              bits0 := !bits0 lor 0x1;\n            | 1 ->\n              let v =\n                (\n                  Ag_oj_run.read_int\n                ) p lb\n              in\n              Obj.set_field (Obj.repr x) 1 (Obj.repr v);\n              bits0 := !bits0 lor 0x2;\n            | 2 ->\n              let v =\n                (\n                  Ag_oj_run.read_string\n                ) p lb\n              in\n              Obj.set_field (Obj.repr x) 2 (Obj.repr v);\n              bits0 := !bits0 lor 0x4;\n            | 3 ->\n              if not (Yojson.Safe.read_null_if_possible p lb) then (\n                let v =\n                  Some (\n                    (\n                      Ag_oj_run.read_string\n                    ) p lb\n                  )\n                in\n                Obj.set_field (Obj.repr x) 3 (Obj.repr v);\n              )\n            | 4 ->\n              if not (Yojson.Safe.read_null_if_possible p lb) then (\n                let v =\n                  Some (\n                    (\n                      Ag_oj_run.read_string\n                    ) p lb\n                  )\n                in\n                Obj.set_field (Obj.repr x) 4 (Obj.repr v);\n              )\n            | 5 ->\n              if not (Yojson.Safe.read_null_if_possible p lb) then (\n                let v =\n                  Some (\n                    (\n                      Ag_oj_run.read_string\n                    ) p lb\n                  )\n                in\n                Obj.set_field (Obj.repr x) 5 (Obj.repr v);\n              )\n            | 6 ->\n              let v =\n                (\n                  Ag_oj_run.read_int\n                ) p lb\n              in\n              Obj.set_field (Obj.repr x) 6 (Obj.repr v);\n              bits0 := !bits0 lor 0x8;\n            | _ -> (\n                Yojson.Safe.skip_json p lb\n              )\n        );\n      done;\n      assert false;\n    with Yojson.End_of_object -> (\n        if !bits0 <> 0xf then Ag_oj_run.missing_fields [| !bits0 |] [| \"login\"; \"id\"; \"url\"; \"public_repos\" |];\n        Ag_oj_run.identity x\n      )\n)\nlet org_of_string s =\n  read_org (Yojson.Safe.init_lexer ()) (Lexing.from_string s)\n"
  },
  {
    "path": "code/json/github_org_j.mli",
    "content": "(* Auto-generated from \"github_org.atd\" *)\n\n\ntype org = Github_org_t.org = {\n  login: string;\n  id: int;\n  url: string;\n  name: string option;\n  blog: string option;\n  email: string option;\n  public_repos: int\n}\n\nval write_org :\n  Bi_outbuf.t -> org -> unit\n  (** Output a JSON value of type {!org}. *)\n\nval string_of_org :\n  ?len:int -> org -> string\n  (** Serialize a value of type {!org}\n      into a JSON string.\n      @param len specifies the initial length\n                 of the buffer used internally.\n                 Default: 1024. *)\n\nval read_org :\n  Yojson.Safe.lexer_state -> Lexing.lexbuf -> org\n  (** Input JSON data of type {!org}. *)\n\nval org_of_string :\n  string -> org\n  (** Deserialize JSON data of type {!org}. *)\n\n"
  },
  {
    "path": "code/json/github_org_t.ml",
    "content": "(* Auto-generated from \"github_org.atd\" *)\n\n\ntype org = {\n  login: string;\n  id: int;\n  url: string;\n  name: string option;\n  blog: string option;\n  email: string option;\n  public_repos: int\n}\n"
  },
  {
    "path": "code/json/github_org_t.mli",
    "content": "(* Auto-generated from \"github_org.atd\" *)\n\n\ntype org = {\n  login: string;\n  id: int;\n  url: string;\n  name: string option;\n  blog: string option;\n  email: string option;\n  public_repos: int\n}\n"
  },
  {
    "path": "code/json/github_t.ml",
    "content": "(* Auto-generated from \"github.atd\" *)\n\n\ntype scope = [\n    `User | `Public_repo | `Repo | `Repo_status | `Delete_repo | `Gist\n]\n\ntype app = { app_name (*atd name *): string; app_url (*atd url *): string }\n\ntype authorization_request = {\n  auth_req_scopes (*atd scopes *): scope list;\n  auth_req_note (*atd note *): string\n}\n\ntype authorization_response = {\n  scopes: scope list;\n  token: string;\n  app: app;\n  url: string;\n  id: int;\n  note: string option;\n  note_url: string option\n}\n"
  },
  {
    "path": "code/json/github_t.mli",
    "content": "(* Auto-generated from \"github.atd\" *)\n\n\ntype scope = [\n    `User | `Public_repo | `Repo | `Repo_status | `Delete_repo | `Gist\n]\n\ntype app = { app_name (*atd name *): string; app_url (*atd url *): string }\n\ntype authorization_request = {\n  auth_req_scopes (*atd scopes *): scope list;\n  auth_req_note (*atd note *): string\n}\n\ntype authorization_response = {\n  scopes: scope list;\n  token: string;\n  app: app;\n  url: string;\n  id: int;\n  note: string option;\n  note_url: string option\n}\n"
  },
  {
    "path": "code/json/install.topscript",
    "content": "#require \"yojson\" ;;\nopen Yojson ;;\n"
  },
  {
    "path": "code/json/install_atdgen.rawsh",
    "content": "$ opam install atdgen\n$ atdgen -version\n1.2.3\n"
  },
  {
    "path": "code/json/list_excerpt.mli",
    "content": "val map  : 'a list -> f:('a -> 'b)   -> 'b list\nval fold : 'a list -> init:'accum -> f:('accum -> 'a -> 'accum) -> 'accum\n(* part 1 *)\nval iter : 'a list -> f:('a -> unit) -> unit\n"
  },
  {
    "path": "code/json/parse_book.ml",
    "content": "open Core.Std\n\nlet () =\n  (* Read the JSON file *)\n  let json = Yojson.Basic.from_file \"book.json\" in\n\n  (* Locally open the JSON manipulation functions *)\n  let open Yojson.Basic.Util in\n  let title = json |> member \"title\" |> to_string in\n  let tags = json |> member \"tags\" |> to_list |> filter_string in\n  let pages = json |> member \"pages\" |> to_int in\n  let is_online = json |> member \"is_online\" |> to_bool_option in\n  let is_translated = json |> member \"is_translated\" |> to_bool_option in\n  let authors = json |> member \"authors\" |> to_list in\n  let names = List.map authors ~f:(fun json -> member \"name\" json |> to_string) in\n\n  (* Print the results of the parsing *)\n  printf \"Title: %s (%d)\\n\" title pages;\n  printf \"Authors: %s\\n\" (String.concat ~sep:\", \" names);\n  printf \"Tags: %s\\n\" (String.concat ~sep:\", \" tags);\n  let string_of_bool_option =\n    function\n    | None -> \"<unknown>\"\n    | Some true -> \"yes\"\n    | Some false -> \"no\" in\n  printf \"Online: %s\\n\" (string_of_bool_option is_online);\n  printf \"Translated: %s\\n\" (string_of_bool_option is_translated)\n"
  },
  {
    "path": "code/json/parse_book.topscript",
    "content": "#require \"yojson\" ;;\nlet json = Yojson.Basic.from_file \"book.json\" ;;\n#part 1\nopen Yojson.Basic.Util ;;\nlet title = json |> member \"title\" |> to_string ;;\n#part 2\nlet tags = json |> member \"tags\" |> to_list |> filter_string ;;\nlet pages = json |> member \"pages\" |> to_int ;;\n#part 3\nlet is_online = json |> member \"is_online\" |> to_bool_option ;;\nlet is_translated = json |> member \"is_translated\" |> to_bool_option ;;\n#part 4\nlet authors = json |> member \"authors\" |> to_list ;;\n#part 5\nlet names =\n  json |> member \"authors\" |> to_list \n  |> List.map ~f:(fun json -> member \"name\" json |> to_string) ;;\n"
  },
  {
    "path": "code/json/read_json.ml",
    "content": "open Core.Std\n\nlet () =\n  (* Read JSON file into an OCaml string *)\n  let buf = In_channel.read_all \"book.json\" in\n  (* Use the string JSON constructor *)\n  let json1 = Yojson.Basic.from_string buf in\n  (* Use the file JSON constructor *)\n  let json2 = Yojson.Basic.from_file \"book.json\" in\n  (* Test that the two values are the same *)\n  print_endline (if json1 = json2 then \"OK\" else \"FAIL\")\n"
  },
  {
    "path": "code/json/run_github_org.sh",
    "content": "./github_org_info.native mirage\n./github_org_info.native janestreet\n"
  },
  {
    "path": "code/json/run_parse_book.sh",
    "content": "corebuild -pkg yojson parse_book.native\n./parse_book.native\n"
  },
  {
    "path": "code/json/run_read_json.sh",
    "content": "corebuild -pkg yojson read_json.native\n./read_json.native\n"
  },
  {
    "path": "code/json/yojson_basic.mli",
    "content": "type json = [\n  | `Assoc of (string * json) list\n  | `Bool of bool\n  | `Float of float\n  | `Int of int\n  | `List of json list\n  | `Null\n  | `String of string\n]\n\n(* part 1 *)\nval from_string : ?buf:Bi_outbuf.t -> ?fname:string -> ?lnum:int ->\n   string -> json\n(* Read a JSON value from a string.\n   [buf]   : use this buffer at will during parsing instead of\n             creating a new one. \n   [fname] : data file name to be used in error messages. It does not \n             have to be a real file. \n   [lnum]  : number of the first line of input. Default is 1. *)\n\nval from_file : ?buf:Bi_outbuf.t -> ?fname:string -> ?lnum:int -> \n   string -> json\n(* Read a JSON value from a file. See [from_string] for the meaning of the optional\n   arguments. *)\n\nval from_channel : ?buf:Bi_outbuf.t -> ?fname:string -> ?lnum:int ->\n  in_channel -> json\n  (** Read a JSON value from a channel.\n      See [from_string] for the meaning of the optional arguments. *)\n"
  },
  {
    "path": "code/json/yojson_basic_simple.mli",
    "content": "val from_string  : string     -> json\nval from_file    : string     -> json\nval from_channel : in_channel -> json\n"
  },
  {
    "path": "code/json/yojson_safe.mli",
    "content": "type json = [\n  | `Assoc of (string * json) list\n  | `Bool of bool\n  | `Float of float\n  | `Floatlit of string\n  | `Int of int\n  | `Intlit of string\n  | `List of json list\n  | `Null\n  | `String of string\n  | `Stringlit of string\n  | `Tuple of json list\n  | `Variant of string * json option\n]\n\n(* part 1 *)\nval to_basic : json -> Yojson.Basic.json\n(** Tuples are converted to JSON arrays, Variants are converted to\n    JSON strings or arrays of a string (constructor) and a json value\n    (argument). Long integers are converted to JSON strings.\n    Examples:\n\n    `Tuple [ `Int 1; `Float 2.3 ]   ->    `List [ `Int 1; `Float 2.3 ]\n    `Variant (\"A\", None)            ->    `String \"A\"\n    `Variant (\"B\", Some x)          ->    `List [ `String \"B\", x ]\n    `Intlit \"12345678901234567890\"  ->    `String \"12345678901234567890\"\n *)\n"
  },
  {
    "path": "code/lists-and-patterns/example.ml",
    "content": ""
  },
  {
    "path": "code/lists-and-patterns/example.mli",
    "content": ""
  },
  {
    "path": "code/lists-and-patterns/lists_layout.ascii",
    "content": "+---+---+   +---+---+   +---+---+\n| 1 | *---->| 2 | *---->| 3 | *---->||\n+---+---+   +---+---+   +---+---+\n"
  },
  {
    "path": "code/lists-and-patterns/main.topscript",
    "content": "[1;2;3];;\n#part 1\n1 :: (2 :: (3 :: [])) ;;\n1 :: 2 :: 3 :: [] ;;\n#part 2\nlet empty = [];;\n3 :: empty;;\n\"three\" :: empty;;\n#part 3\nlet l = 1 :: 2 :: 3 :: [];;\nlet m = 0 :: l;;\nl;;\n#part 4\nlet rec sum l =\n    match l with\n    | [] -> 0\n    | hd :: tl -> hd + sum tl\n  ;;\nsum [1;2;3];;\nsum [];;\n#part 5\nlet rec drop_value l to_drop =\n    match l with\n    | [] -> []\n    | to_drop :: tl -> drop_value tl to_drop\n    | hd :: tl -> hd :: drop_value tl to_drop\n  ;;\n#part 6\ndrop_value [1;2;3] 2;;\n#part 7\nlet rec drop_value l to_drop =\n    match l with\n    | [] -> []\n    | hd :: tl ->\n      let new_tl = drop_value tl to_drop in\n      if hd = to_drop then new_tl else hd :: new_tl\n  ;;\ndrop_value [1;2;3] 2;;\n#part 8\nlet rec drop_zero l =\n    match l with\n    | [] -> []\n    | 0  :: tl -> drop_zero tl\n    | hd :: tl -> hd :: drop_zero tl\n  ;;\ndrop_zero [1;2;0;3];;\n#part 9\nlet plus_one_match x =\n    match x with\n    | 0 -> 1\n    | 1 -> 2\n    | 2 -> 3\n    | _ -> x + 1\n\n  let plus_one_if x =\n    if      x = 0 then 1\n    else if x = 1 then 2\n    else if x = 2 then 3\n    else x + 1\n  ;;\n#part 10\n#require \"core_bench\";;\nopen Core_bench.Std;;\nlet run_bench tests =\n  Bench.bench\n    ~ascii_table:true\n    ~display:Textutils.Ascii_table.Display.column_titles\n    tests\n;;\n[ Bench.Test.create ~name:\"plus_one_match\" (fun () ->\n      ignore (plus_one_match 10))\n  ; Bench.Test.create ~name:\"plus_one_if\" (fun () ->\n      ignore (plus_one_if 10)) ]\n  |> run_bench\n  ;;\n#part 11\nlet rec sum_if l =\n    if List.is_empty l then 0\n    else List.hd_exn l + sum_if (List.tl_exn l)\n  ;;\n#part 12\nlet numbers = List.range 0 1000 in\n  [ Bench.Test.create ~name:\"sum_if\" (fun () -> ignore (sum_if numbers))\n  ; Bench.Test.create ~name:\"sum\"    (fun () -> ignore (sum numbers)) ]\n  |> run_bench\n  ;;\n#part 13\nlet rec drop_zero l =\n    match l with\n    | [] -> []\n    | 0  :: tl -> drop_zero tl\n  ;;\n#part 14\nList.map ~f:String.length [\"Hello\"; \"World!\"];;\n#part 15\nList.map2_exn ~f:Int.max [1;2;3] [3;2;1];;\n#part 16\nList.map2_exn ~f:Int.max [1;2;3] [3;2;1;0];;\n#part 17\nList.fold;;\n#part 18\nList.fold ~init:0 ~f:(+) [1;2;3;4];;\n#part 19\nList.fold ~init:[] ~f:(fun list x -> x :: list) [1;2;3;4];;\n#part 20\nlet max_widths header rows =\n    let lengths l = List.map ~f:String.length l in\n    List.fold rows\n      ~init:(lengths header)\n      ~f:(fun acc row ->\n        List.map2_exn ~f:Int.max acc (lengths row))\n  ;;\n#part 21\nlet render_separator widths =\n    let pieces = List.map widths\n      ~f:(fun w -> String.make (w + 2) '-')\n    in\n    \"|\" ^ String.concat ~sep:\"+\" pieces ^ \"|\"\n  ;;\nrender_separator [3;6;2];;\n#part 22\nlet s = \".\" ^ \".\"  ^ \".\"  ^ \".\"  ^ \".\"  ^ \".\"  ^ \".\";;\n#part 23\nlet s = String.concat [\".\";\".\";\".\";\".\";\".\";\".\";\".\"];;\n#part 24\nlet pad s length =\n    \" \" ^ s ^ String.make (length - String.length s + 1) ' '\n  ;;\npad \"hello\" 10;;\n#part 25\nlet render_row row widths =\n    let padded = List.map2_exn row widths ~f:pad in\n    \"|\" ^ String.concat ~sep:\"|\" padded ^ \"|\"\n  ;;\nrender_row [\"Hello\";\"World\"] [10;15];;\n#part 26\nlet render_table header rows =\n    let widths = max_widths header rows in\n    String.concat ~sep:\"\\n\"\n      (render_row header widths\n       :: render_separator widths\n       :: List.map rows ~f:(fun row -> render_row row widths)\n      )\n  ;;\n#part 27\nList.reduce;;\n#part 28\nList.reduce ~f:(+) [1;2;3;4;5];;\nList.reduce ~f:(+) [];;\n#part 29\nList.filter ~f:(fun x -> x mod 2 = 0) [1;2;3;4;5];;\n#part 30\nList.filter_map (Sys.ls_dir \".\") ~f:(fun fname ->\n    match String.rsplit2 ~on:'.' fname with\n    | None  | Some (\"\",_) -> None\n    | Some (_,ext) ->\n      Some ext)\n  |> List.dedup\n  ;;\n#part 31\nlet is_ocaml_source s =\n    match String.rsplit2 s ~on:'.' with\n    | Some (_,(\"ml\"|\"mli\")) -> true\n    | _ -> false\n  ;;\nlet (ml_files,other_files) =\n    List.partition_tf (Sys.ls_dir \".\")  ~f:is_ocaml_source;;\n#part 32\nList.append [1;2;3] [4;5;6];;\n#part 33\n[1;2;3] @ [4;5;6];;\n#part 34\nList.concat [[1;2];[3;4;5];[6];[]];;\n#part 35\nlet rec ls_rec s =\n    if Sys.is_file_exn ~follow_symlinks:true s\n    then [s]\n    else\n      Sys.ls_dir s\n      |> List.map ~f:(fun sub -> ls_rec (s ^/ sub))\n      |> List.concat\n  ;;\n#part 36\nlet rec ls_rec s =\n    if Sys.is_file_exn ~follow_symlinks:true s\n    then [s]\n    else\n      Sys.ls_dir s\n      |> List.concat_map ~f:(fun sub -> ls_rec (s ^/ sub))\n  ;;\n#part 37\nlet rec length = function\n    | [] -> 0\n    | _ :: tl -> 1 + length tl\n  ;;\nlength [1;2;3];;\n#part 38\nlet make_list n = List.init n ~f:(fun x -> x);;\nlength (make_list 10);;\nlength (make_list 10_000_000);;\n#part 39\nlet rec length_plus_n l n =\n    match l with\n    | [] -> n\n    | _ :: tl -> length_plus_n tl (n + 1)\n  ;;\nlet length l = length_plus_n l 0 ;;\nlength [1;2;3;4];;\n#part 40\nlength (make_list 10_000_000);;\n#part 41\nlet rec destutter list =\n    match list with\n    | [] -> []\n    | [hd] -> [hd]\n    | hd :: hd' :: tl ->\n      if hd = hd' then destutter (hd' :: tl)\n      else hd :: destutter (hd' :: tl)\n  ;;\n#part 42\nlet rec destutter = function\n    | [] as l -> l\n    | [_] as l -> l\n    | hd :: (hd' :: _ as tl) ->\n      if hd = hd' then destutter tl\n      else hd :: destutter tl\n  ;;\n#part 43\nlet rec destutter = function\n    | [] | [_] as l -> l\n    | hd :: (hd' :: _ as tl) ->\n      if hd = hd' then destutter tl\n      else hd :: destutter tl\n  ;;\n#part 44\nlet rec destutter = function\n    | [] | [_] as l -> l\n    | hd :: (hd' :: _ as tl) when hd = hd' -> destutter tl\n    | hd :: tl -> hd :: destutter tl\n  ;;\n#part 45\n3 = 4;;\n[3;4;5] = [3;4;5];;\n[Some 3; None] = [None; Some 3];;\n#part 46\n(=);;\n#part 47\n(fun x -> x + 1) = (fun x -> x + 1);;\n#part 48\nlet rec count_some list =\n    match list with\n    | [] -> 0\n    | x :: tl when Option.is_none x -> count_some tl\n    | x :: tl when Option.is_some x -> 1 + count_some tl\n  ;;\n#part 49\ncount_some [Some 3; None; Some 4];;\n#part 50\nlet rec count_some list =\n    match list with\n    | [] -> 0\n    | x :: tl when Option.is_none x -> count_some tl\n    | x :: tl when Option.is_some x -> 1 + count_some tl\n    | x :: tl -> -1 (* unreachable *)\n  ;;\n#part 51\nlet rec count_some list =\n    match list with\n    | [] -> 0\n    | x :: tl when Option.is_none x -> count_some tl\n    | _ :: tl -> 1 + count_some tl\n  ;;\n#part 52\nlet rec count_some list =\n    match list with\n    | [] -> 0\n    | None   :: tl -> count_some tl\n    | Some _ :: tl -> 1 + count_some tl\n  ;;\n#part 53\nlet count_some l = List.count ~f:Option.is_some l;;\n#part 54\n#part 55\n#part 56\n#part 57\n#part 58\n#part 59\n#part 60\n#part 61\n#part 62\n#part 63\n#part 64\n#part 65\n#part 66\n#part 67\n#part 68\n#part 69\nprintf \"%s\\n\"\n   (render_table\n     [\"language\";\"architect\";\"first release\"]\n     [ [\"Lisp\" ;\"John McCarthy\" ;\"1958\"] ;\n       [\"C\"    ;\"Dennis Ritchie\";\"1969\"] ;\n       [\"ML\"   ;\"Robin Milner\"  ;\"1973\"] ;\n       [\"OCaml\";\"Xavier Leroy\"  ;\"1996\"] ;\n     ]);;\n"
  },
  {
    "path": "code/maps-and-hash-tables/comparable.ml",
    "content": "module type Comparable = sig\n  type t\n  val sexp_of_t : t -> Sexp.t\n  val t_of_sexp : Sexp.t -> t\n  val compare : t -> t -> int\nend\n"
  },
  {
    "path": "code/maps-and-hash-tables/core_phys_equal.topscript",
    "content": "open Core.Std ;;\n1 == 2 ;;\nphys_equal 1 2 ;;\n"
  },
  {
    "path": "code/maps-and-hash-tables/main-22.rawscript",
    "content": "# module Foo_and_bar : sig\n    type t = { foo: Int.Set.t; bar: string }\n    include Comparable.S with type t := t\n  end = struct\n    module T = struct\n      type t = { foo: Int.Set.t; bar: string } with sexp\n      let compare t1 t2 =\n        let c = Int.Set.compare t1.foo t2.foo in\n        if c <> 0 then c else String.compare t1.bar t2.bar\n    end\n    include T\n    include Comparable.Make(T)\n  end;;\nmodule Foo_and_bar :\nsig\n  type t = { foo : Int.Set.t; bar : string; }\n  val ( >= ) : t -> t -> bool\n  val ( <= ) : t -> t -> bool\n  val ( = ) : t -> t -> bool\n\n    ...\n\nend\n"
  },
  {
    "path": "code/maps-and-hash-tables/main-23.rawscript",
    "content": "# module Foo_and_bar : sig\n    type t = { foo: Int.Set.t; bar: string }\n    include Comparable.S with type t := t\n  end = struct\n    module T = struct\n      type t = { foo: Int.Set.t; bar: string } with sexp, compare\n    end\n    include T\n    include Comparable.Make(T)\n  end;;\nmodule Foo_and_bar :\nsig\n  type t = { foo : Int.Set.t; bar : string; }\n  val ( >= ) : t -> t -> bool\n  val ( <= ) : t -> t -> bool\n  val ( = ) : t -> t -> bool\n\n  ...\n\nend\n"
  },
  {
    "path": "code/maps-and-hash-tables/main-24.rawscript",
    "content": "# module Foo_and_bar : sig\n    type t = { foo: int; bar: string }\n    include Comparable.S with type t := t\n  end = struct\n    module T = struct\n      type t = { foo: int; bar: string } with sexp\n    end\n    include T\n    include Comparable.Poly(T)\n  end;;\nmodule Foo_and_bar :\nsig\n  type t = { foo : int; bar : string; }\n  val ( >= ) : t -> t -> bool\n  val ( <= ) : t -> t -> bool\n  val ( = ) : t -> t -> bool\n\n  ...\n\nend\n\n"
  },
  {
    "path": "code/maps-and-hash-tables/main-30.rawscript",
    "content": "# module Foo_and_bar : sig\n    type t = { foo: int; bar: string }\n    include Hashable.S with type t := t\n  end = struct\n    module T = struct\n      type t = { foo: int; bar: string } with sexp, compare\n      let hash t =\n        (Int.hash t.foo) lxor (String.hash t.bar)\n    end\n    include T\n    include Hashable.Make(T)\n  end;;\nmodule Foo_and_bar :\nsig\n  type t = { foo : int; bar : string; }\n  module Hashable : sig type t = t end\n  val hash : t -> int\n  val compare : t -> t -> int\n  val hashable : t Pooled_hashtbl.Hashable.t\n\n  ...\n\nend\n"
  },
  {
    "path": "code/maps-and-hash-tables/main.topscript",
    "content": "let x = 0;;\n#part 1\nlet digit_alist =\n    [ 0, \"zero\"; 1, \"one\"; 2, \"two\"  ; 3, \"three\"; 4, \"four\"\n    ; 5, \"five\"; 6, \"six\"; 7, \"seven\"; 8, \"eight\"; 9, \"nine\" ]\n  ;;\n#part 2\nList.Assoc.find digit_alist 6;;\nList.Assoc.find digit_alist 22;;\nList.Assoc.add digit_alist 0 \"zilch\";;\n#part 3\nlet digit_map = Map.of_alist_exn digit_alist\n                     ~comparator:Int.comparator;;\nMap.find digit_map 3;;\n#part 4\nlet zilch_map = Map.add digit_map ~key:0 ~data:\"zilch\";;\n#part 5\nlet left = String.Map.of_alist_exn [\"foo\",1; \"bar\",3; \"snoo\", 0]\n  let right = String.Map.of_alist_exn [\"foo\",0; \"snoo\", 0]\n  let diff = Map.symmetric_diff ~data_equal:Int.equal left right\n  ;;\n#part 6\nMap.symmetric_diff;;\n#part 7\nmodule Reverse = Comparator.Make(struct\n    type t = string\n    let sexp_of_t = String.sexp_of_t\n    let t_of_sexp = String.t_of_sexp\n    let compare x y = String.compare y x\n  end);;\n#part 8\nlet alist = [\"foo\", 0; \"snoo\", 3];;\nlet ord_map = Map.of_alist_exn ~comparator:String.comparator alist;;\nlet rev_map = Map.of_alist_exn ~comparator:Reverse.comparator alist;;\n#part 9\nMap.min_elt ord_map;;\nMap.min_elt rev_map;;\n#part 10\nMap.symmetric_diff ord_map rev_map;;\n#part 11\nlet ord_tree = Map.to_tree ord_map;;\n#part 12\nMap.Tree.find ~comparator:String.comparator ord_tree \"snoo\";;\n#part 13\nMap.Tree.find ~comparator:Reverse.comparator ord_tree \"snoo\";;\n#part 14\nMap.of_alist_exn ~comparator:Comparator.Poly.comparator digit_alist;;\n#part 15\nMap.Poly.of_alist_exn digit_alist;;\n#part 16\nMap.symmetric_diff (Map.Poly.singleton 3 \"three\")\n                     (Int.Map.singleton  3 \"four\" ) ;;\n#part 17\nlet dedup ~comparator l =\n    List.fold l ~init:(Set.empty ~comparator) ~f:Set.add\n    |> Set.to_list\n  ;;\ndedup ~comparator:Int.comparator [8;3;2;3;7;8;10];;\n#part 18\nlet (s1,s2) = (Int.Set.of_list [1;2],\n                 Int.Set.of_list [2;1]);;\n#part 19\nSet.equal s1 s2;;\n#part 20\ns1 = s2;;\n#part 21\nSet.to_tree s1 = Set.to_tree s2;;\n#part 22\nmodule Foo_and_bar : sig\n    type t = { foo: Int.Set.t; bar: string }\n    include Comparable.S with type t := t\n  end = struct\n    module T = struct\n      type t = { foo: Int.Set.t; bar: string } with sexp\n      let compare t1 t2 =\n        let c = Int.Set.compare t1.foo t2.foo in\n        if c <> 0 then c else String.compare t1.bar t2.bar\n    end\n    include T\n    include Comparable.Make(T)\n  end;;\n#part 23\nmodule Foo_and_bar : sig\n    type t = { foo: Int.Set.t; bar: string }\n    include Comparable.S with type t := t\n  end = struct\n    module T = struct\n      type t = { foo: Int.Set.t; bar: string } with sexp, compare\n    end\n    include T\n    include Comparable.Make(T)\n  end;;\n#part 24\nmodule Foo_and_bar : sig\n    type t = { foo: int; bar: string }\n    include Comparable.S with type t := t\n  end = struct\n    module T = struct\n      type t = { foo: int; bar: string } with sexp\n    end\n    include T\n    include Comparable.Poly(T)\n  end;;\n#part 25\nlet table = Hashtbl.create ~hashable:String.hashable ();;\nHashtbl.replace table ~key:\"three\" ~data:3;;\nHashtbl.find table \"three\";;\n#part 26\nlet table = String.Table.create ();;\n#part 27\nlet table = Hashtbl.create ~hashable:Hashtbl.Poly.hashable ();;\n#part 28\nlet table = Hashtbl.Poly.create ();;\n#part 29\nCaml.Hashtbl.hash (List.range 0 9);;\nCaml.Hashtbl.hash (List.range 0 10);;\nCaml.Hashtbl.hash (List.range 0 11);;\nCaml.Hashtbl.hash (List.range 0 100);;\n#part 30\nmodule Foo_and_bar : sig\n    type t = { foo: int; bar: string }\n    include Hashable.S with type t := t\n  end = struct\n    module T = struct\n      type t = { foo: int; bar: string } with sexp, compare\n      let hash t =\n        (Int.hash t.foo) lxor (String.hash t.bar)\n    end\n    include T\n    include Hashable.Make(T)\n  end;;\n"
  },
  {
    "path": "code/maps-and-hash-tables/map_vs_hash.ml",
    "content": "open Core.Std\nopen Core_bench.Std\n\nlet map_iter ~num_keys ~iterations =\n  let rec loop i map =\n    if i <= 0 then ()\n    else loop (i - 1)\n           (Map.change map (i mod num_keys) (fun current ->\n              Some (1 + Option.value ~default:0 current)))\n  in\n  loop iterations Int.Map.empty\n\nlet table_iter ~num_keys ~iterations =\n  let table = Int.Table.create ~size:num_keys () in\n  let rec loop i =\n    if i <= 0 then ()\n    else (\n      Hashtbl.change table (i mod num_keys) (fun current ->\n        Some (1 + Option.value ~default:0 current));\n      loop (i - 1)\n    )\n  in\n  loop iterations\n\nlet tests ~num_keys ~iterations =\n  let test name f = Bench.Test.create f ~name in\n  [ test \"map\"   (fun () -> map_iter   ~num_keys ~iterations)\n  ; test \"table\" (fun () -> table_iter ~num_keys ~iterations)\n  ]\n\nlet () =\n  tests ~num_keys:1000 ~iterations:100_000\n  |> Bench.make_command\n  |> Command.run\n"
  },
  {
    "path": "code/maps-and-hash-tables/map_vs_hash2.ml",
    "content": "open Core.Std\nopen Core_bench.Std\n\nlet create_maps ~num_keys ~iterations =\n  let rec loop i map =\n    if i <= 0 then []\n    else\n      let new_map =\n        Map.change map (i mod num_keys) (fun current ->\n          Some (1 + Option.value ~default:0 current))\n      in\n      new_map :: loop (i - 1) new_map\n  in\n  loop iterations Int.Map.empty\n\nlet create_tables ~num_keys ~iterations =\n  let table = Int.Table.create ~size:num_keys () in\n  let rec loop i =\n    if i <= 0 then []\n    else (\n      Hashtbl.change table (i mod num_keys) (fun current ->\n        Some (1 + Option.value ~default:0 current));\n      let new_table = Hashtbl.copy table in\n      new_table :: loop (i - 1)\n    )\n  in\n  loop iterations\n\nlet tests ~num_keys ~iterations =\n  let test name f = Bench.Test.create f ~name in\n  [ test \"map\"   (fun () -> ignore (create_maps   ~num_keys ~iterations))\n  ; test \"table\" (fun () -> ignore (create_tables ~num_keys ~iterations))\n  ]\n\nlet () =\n  tests ~num_keys:50 ~iterations:1000\n  |> Bench.make_command\n  |> Command.run\n"
  },
  {
    "path": "code/maps-and-hash-tables/phys_equal.rawscript",
    "content": "# type t1 = { foo1:int; bar1:t2 } and t2 = { foo2:int; bar2:t1 } ;;\ntype t1 = { foo1 : int; bar1 : t2; }\nand t2 = { foo2 : int; bar2 : t1; }\n# let rec v1 = { foo1=1; bar1=v2 } and v2 = { foo2=2; bar2=v1 } ;;\n<lots of text>\n# v1 == v1;;\n- : bool = true\n# phys_equal v1 v1;;\n- : bool = true\n# v1 = v1 ;;\n<press ^Z and kill the process now>\n"
  },
  {
    "path": "code/maps-and-hash-tables/run_map_vs_hash.sh",
    "content": "corebuild -pkg core_bench map_vs_hash.native\n./map_vs_hash.native -ascii -clear-columns time speedup\n"
  },
  {
    "path": "code/maps-and-hash-tables/run_map_vs_hash2.sh",
    "content": "corebuild -pkg core_bench map_vs_hash2.native\n./map_vs_hash2.native -ascii -clear-columns time speedup\n"
  },
  {
    "path": "code/memory-repr/block.ascii",
    "content": "+------------------------+---------+----------+----------+----------+----\n| size of block in words |  color  | tag byte | value[0] | value[1] | ...\n+------------------------+---------+----------+----------+----------+----\n <-either 22 or 54 bits-> <-2 bit-> <--8 bit-->\n"
  },
  {
    "path": "code/memory-repr/custom_ops.c",
    "content": "struct custom_operations {\n  char *identifier;\n  void (*finalize)(value v);\n  int (*compare)(value v1, value v2);\n  intnat (*hash)(value v);\n  void (*serialize)(value v,\n                    /*out*/ uintnat * wsize_32 /*size in bytes*/,\n                    /*out*/ uintnat * wsize_64 /*size in bytes*/);\n  uintnat (*deserialize)(void * dst);\n  int (*compare_ext)(value v1, value v2);\n};\n"
  },
  {
    "path": "code/memory-repr/float_array_layout.ascii",
    "content": "+---------+----------+----------- - - - -\n| header  | float[0] | float[1] | ....\n+---------+----------+----------+- - - - -\n"
  },
  {
    "path": "code/memory-repr/reprs.topscript",
    "content": "Obj.is_block (Obj.repr (1,2,3)) ;;\nObj.is_block (Obj.repr 1) ;;\n#part 1\nObj.tag (Obj.repr 1.0) ;;\nObj.double_tag ;;\n#part 2\nObj.double_tag ;;\nObj.double_array_tag ;;\n#part 3\nObj.tag (Obj.repr [| 1.0; 2.0; 3.0 |]) ;;\nObj.tag (Obj.repr (1.0, 2.0, 3.0) ) ;;\nObj.double_field (Obj.repr [| 1.1; 2.2; 3.3 |]) 1 ;;\nObj.double_field (Obj.repr 1.234) 0 ;;\n#part 4\ntype t = Apple | Orange | Pear ;;\n((Obj.magic (Obj.repr Apple)) : int) ;;\n((Obj.magic (Obj.repr Pear)) : int) ;;\nObj.is_block (Obj.repr Apple) ;;\n#part 5\ntype t = Apple | Orange of int | Pear of string | Kiwi ;;\nObj.is_block (Obj.repr (Orange 1234)) ;;\nObj.tag (Obj.repr (Orange 1234)) ;;\nObj.tag (Obj.repr (Pear \"xyz\")) ;;\n(Obj.magic (Obj.field (Obj.repr (Orange 1234)) 0) : int) ;;\n(Obj.magic (Obj.field (Obj.repr (Pear \"xyz\")) 0) : string) ;;\n#part 6\nPa_type_conv.hash_variant \"Foo\" ;;\n(Obj.magic (Obj.repr `Foo) : int) ;;\n"
  },
  {
    "path": "code/memory-repr/simple_record.topscript",
    "content": "type t = { foo: int; bar: int } ;;\nlet x = { foo = 13; bar = 14 } ;;\n"
  },
  {
    "path": "code/memory-repr/string_block.ascii",
    "content": "+---------------+----------------+--------+-----------+\n| header        | 'a' 'b' 'c' 'd' 'e' 'f' | '\\O' '\\1' |\n+---------------+----------------+--------+-----------+\n                L data                    L padding\n"
  },
  {
    "path": "code/memory-repr/string_size_calc.ascii",
    "content": "number_of_words_in_block * sizeof(word) - last_byte_of_block - 1\n"
  },
  {
    "path": "code/memory-repr/tuple_layout.ascii",
    "content": "+---------+----------+----------- - - - -\n| header  | value[0] | value[1] | ....\n+---------+----------+----------+- - - - -\n"
  },
  {
    "path": "code/objects/IsBarbell.java",
    "content": "boolean IsBarbell(Shape[] s) {\n  return s.length == 3 && (s[0] instanceof Circle) &&\n    (s[1] instanceof Line) && (s[2] instanceof Circle) &&\n        ((Circle) s[0]).radius() == ((Circle) s[2]).radius();\n}\n"
  },
  {
    "path": "code/objects/Shape.java",
    "content": "String GetShapeName(Shape s) {\n  if (s instanceof Square) {\n    return \"Square\";\n  } else if (s instanceof Circle) {\n    return \"Circle\";\n  } else {\n    return \"Other\";\n  }\n}\n"
  },
  {
    "path": "code/objects/immutable.topscript",
    "content": "1;;\n#part 1\nlet imm_stack init = object\n    val v = init\n\n    method pop =\n      match v with\n      | hd :: tl -> Some (hd, {< v = tl >})\n      | [] -> None \n\n    method push hd = \n      {< v = hd :: v >}\n  end ;;\n\n#part 2\nlet s = imm_stack [3; 2; 1] ;;\nlet t = s#push 4 ;;\ns#pop ;;\nt#pop ;;\n"
  },
  {
    "path": "code/objects/is_barbell.ml",
    "content": "let is_barbell = function\n| [Circle r1; Line _; Circle r2] when r1 = r2 -> true\n| _ -> false\n"
  },
  {
    "path": "code/objects/narrowing.ml",
    "content": "(* part 1 *)\ntype shape = < variant : repr; area : float>\nand circle = < variant : repr; area : float; radius : int >\nand line = < variant : repr; area : float; length : int >\nand repr =\n | Circle of circle\n | Line of line;;\n\nlet is_barbell = function\n| [s1; s2; s3] ->\n   (match s1#variant, s2#variant, s3#variant with\n    | Circle c1, Line _, Circle c2 when c1#radius = c2#radius -> true\n    | _ -> false)\n| _ -> false;;\n"
  },
  {
    "path": "code/objects/polymorphism.topscript",
    "content": "1;;\n#part 1\nlet area sq = sq#width * sq#width ;;\nlet minimize sq : unit = sq#resize 1 ;;\nlet limit sq = \n    if (area sq) > 100 then minimize sq ;;\n\n#part 2\nlet toggle sq b : unit = \n    if b then sq#resize `Fullscreen\n    else minimize sq ;;\n\n#part 3\nlet area_closed (sq: < width : int >) = sq#width * sq#width ;;\nlet sq = object\n    method width = 30 \n    method name = \"sq\" \n  end ;;\narea_closed sq ;;\n\n#part 4\ntype square = < width : int; ..> ;;\n"
  },
  {
    "path": "code/objects/row_polymorphism.topscript",
    "content": "type shape = < area : float > ;;\n\ntype square = < area : float; width : int > ;;\n\nlet square w = object\n    method area = Float.of_int (w * w)\n    method width = w\n  end ;;\n\ntype circle = < area : float; radius : int > ;;\n\nlet circle r = object\n    method area = 3.14 *. (Float.of_int r) ** 2.0\n    method radius = r\n  end ;;\n\n#part 1\nlet remove_large l =\n    List.filter ~f:(fun s -> s#area <= 100.) l ;;\n\n#part 2\nlet squares : < area : float; width : int > list = \n    [square 5; square 15; square 10] ;;\nremove_large squares ;;\n\n#part 3\nlet remove_large (l: < area : float > list) = \n    List.filter ~f:(fun s -> s#area <= 100.) l ;;\nremove_large (squares :> < area : float > list ) ;;\n\n#part 4\nlet hlist: < area: float; ..> list = [square 10; circle 30] ;;\n\n#part 5\nlet shape_ref: < area: float; ..> ref = ref (square 40) ;;\nshape_ref := circle 20 ;;\n\n#part 6\nlet hlist: shape list = [(square 10 :> shape); (circle 30 :> shape)] ;;\nlet shape_ref: shape ref = ref (square 40 :> shape) ;;\nshape_ref := (circle 20 :> shape) ;;\n"
  },
  {
    "path": "code/objects/stack.topscript",
    "content": "1;;\n#part 1\nlet s = object\n    val mutable v = [0; 2]\n\n    method pop =\n      match v with\n      | hd :: tl -> \n        v <- tl;\n        Some hd\n      | [] -> None\n\n    method push hd = \n      v <- hd :: v\n  end ;;\n#part 2\ns#pop ;;\ns#push 4 ;;\ns#pop ;;\n\n#part 3\nlet stack init = object\n    val mutable v = init\n\n    method pop =\n      match v with\n      | hd :: tl -> \n        v <- tl;\n        Some hd\n      | [] -> None\n\n    method push hd = \n      v <- hd :: v\n  end ;;\nlet s = stack [3; 2; 1] ;;\ns#pop ;;\n\n#part 4\nlet print_pop st = Option.iter ~f:(printf \"Popped: %d\\n\") st#pop ;;\nprint_pop (stack [5;4;3;2;1]) ;;\nlet t = object\n    method pop = Some (Float.to_int (Time.to_float (Time.now ())))\n  end ;;\nprint_pop t ;;\n"
  },
  {
    "path": "code/objects/subtyping.ml",
    "content": "(* part 1 *)\ntype shape = < area : float >\n\ntype square = < area : float; width : int >\n\nlet square w = object\n  method area = Float.of_int (w * w)\n  method width = w\nend\n\ntype circle = < area : float; radius : int >\n\nlet circle r = object\n  method area = 3.14 *. (Float.of_int r) ** 2.0\n  method radius = r\nend\n\n(* part 2 *)\ntype 'a stack = < pop: 'a option; push: 'a -> unit >\n\nlet square_stack: square stack = stack [square 30; square 10]\n\nlet circle_stack: circle stack = stack [circle 20; circle 40]\n"
  },
  {
    "path": "code/objects/subtyping.topscript",
    "content": "let stack init = object\n    val mutable v = init\n\n    method pop =\n      match v with\n      | hd :: tl -> \n        v <- tl;\n        Some hd\n      | [] -> None\n  \n    method push hd = \n      v <- hd :: v\n  end ;;\n  \ntype shape = < area : float > ;;\n\ntype square = < area : float; width : int > ;;\n\nlet square w = object\n    method area = Float.of_int (w * w)\n    method width = w\n  end ;;\n\ntype circle = < area : float; radius : int > ;;\n\nlet circle r = object\n    method area = 3.14 *. (Float.of_int r) ** 2.0\n    method radius = r\n  end ;;\n\ntype 'a stack = < pop: 'a option; push: 'a -> unit > ;;\n\nlet square_stack: square stack = stack [square 30; square 10] ;;\n\nlet circle_stack: circle stack = stack [circle 20; circle 40] ;;\n\n#part 1\nlet shape w : shape = square w ;;\nlet shape w : shape = (square w :> shape) ;;\n\n#part 2\nlet coin = object\n    method shape = circle 5\n    method color = \"silver\"\n  end ;;\nlet map = object\n    method shape = square 10\n  end ;;\n\n#part 3\ntype item = < shape : shape > ;;\nlet items = [ (coin :> item) ; (map :> item) ] ;;\n\n#part 4\ntype num = [ `Int of int | `Float of float ] ;;\ntype const = [ num | `String of string ] ;;\nlet n : num = `Int 3 ;;\nlet c : const = (n :> const) ;;\n\n#part 5\nlet squares: square list = [ square 10; square 20 ] ;;\nlet shapes: shape list = (squares :> shape list) ;;\n\n#part 6\nlet square_array: square array = [| square 10; square 20 |] ;;\nlet shape_array: shape array = (square_array :> shape array) ;;\n\n#part 7\nlet shape_to_string: shape -> string = \n    fun s -> sprintf \"Shape(%F)\" s#area ;;\nlet square_to_string: square -> string = \n    (shape_to_string :> square -> string) ;;\n\n#part 8\nmodule Either = struct\n    type ('a, 'b) t = \n      | Left of 'a\n      | Right of 'b\n    let left x = Left x\n    let right x = Right x\n  end ;;\n(Either.left (square 40) :> (shape, shape) Either.t) ;;\n\n#part 9\nmodule AbstractEither : sig \n    type ('a, 'b) t\n    val left: 'a -> ('a, 'b) t\n    val right: 'b -> ('a, 'b) t\n  end = Either ;;\n(AbstractEither.left (square 40) :> (shape, shape) AbstractEither.t) ;;\n\n#part 10\nmodule VarEither : sig \n    type (+'a, +'b) t\n    val left: 'a -> ('a, 'b) t\n    val right: 'b -> ('a, 'b) t\n  end = Either ;;\n(VarEither.left (square 40) :> (shape, shape) VarEither.t) ;;\n\n#part 11\nlet total_area (shape_stacks: shape stack list) =\n    let stack_area acc st = \n      let rec loop acc =\n        match st#pop with\n        | Some s -> loop (acc +. s#area)\n        | None -> acc\n      in\n        loop acc\n    in\n      List.fold ~init:0.0 ~f:stack_area shape_stacks ;;\n\n#part 12\ntotal_area [(square_stack :> shape stack); (circle_stack :> shape stack)] ;;\n\n#part 13\ntype 'a readonly_stack = < pop : 'a option > ;;\nlet total_area (shape_stacks: shape readonly_stack list) =\n    let stack_area acc st = \n      let rec loop acc =\n        match st#pop with\n        | Some s -> loop (acc +. s#area)\n        | None -> acc\n      in\n        loop acc\n    in\n      List.fold ~init:0.0 ~f:stack_area shape_stacks ;;\ntotal_area [(square_stack :> shape readonly_stack); (circle_stack :> shape readonly_stack)] ;;\n"
  },
  {
    "path": "code/ocp-index/index_ncurses.sh",
    "content": "corebuild -pkg ctypes.foreign -tag bin_annot ncurses.cmi\nocp-index complete -I . Ncur\nocp-index complete -I . Ncurses.a\nocp-index complete -I . Ncurses.\n"
  },
  {
    "path": "code/packing/A.ml",
    "content": "let v = \"hello\"\n"
  },
  {
    "path": "code/packing/B.ml",
    "content": "let w = 42\n"
  },
  {
    "path": "code/packing/X.mlpack",
    "content": "A\nB\n"
  },
  {
    "path": "code/packing/_tags",
    "content": "<*.cmx> and not \"X.cmx\": for-pack(X)\n"
  },
  {
    "path": "code/packing/build_test.sh",
    "content": "corebuild test.inferred.mli test.cmi\ncat _build/test.inferred.mli\nocamlobjinfo _build/test.cmi\n"
  },
  {
    "path": "code/packing/show_files.sh",
    "content": "cat A.ml\ncat B.ml\ncat _tags\ncat X.mlpack\n"
  },
  {
    "path": "code/packing/test.ml",
    "content": "let v = X.A.v\nlet w = X.B.w\n"
  },
  {
    "path": "code/parsing/basic_parser.mly",
    "content": "%token <int> INT\n%token <float> FLOAT\n%token <string> ID\n%token <string> STRING\n%token TRUE\n%token FALSE\n%token NULL\n%token LEFT_BRACE\n%token RIGHT_BRACE\n%token LEFT_BRACK\n%token RIGHT_BRACK\n%token COLON\n%token COMMA\n%token EOF\n\n%start <unit> exp\n\n%%\n\nexp: { () }\n"
  },
  {
    "path": "code/parsing/build_short_parser.sh",
    "content": "corebuild -use-menhir short_parser.mli\n"
  },
  {
    "path": "code/parsing/example.json",
    "content": "{\n  \"title\": \"Cities\",\n  \"cities\": [\n    { \"name\": \"Chicago\",  \"zips\": [60601] },\n    { \"name\": \"New York\", \"zips\": [10004] } \n  ]\n}\n"
  },
  {
    "path": "code/parsing/json.ml",
    "content": "type value = [\n  | `Assoc of (string * value) list\n  | `Bool of bool\n  | `Float of float\n  | `Int of int\n  | `List of value list\n  | `Null\n  | `String of string\n]\n\n(* part 1 *)\nopen Core.Std\nlet rec output_value outc = function\n  | `Assoc obj  -> print_assoc outc obj\n  | `List l     -> print_list outc l\n  | `String s   -> printf \"\\\"%s\\\"\" s\n  | `Int i      -> printf \"%d\" i\n  | `Float x    -> printf \"%f\" x\n  | `Bool true  -> output_string outc \"true\"\n  | `Bool false -> output_string outc \"false\"\n  | `Null       -> output_string outc \"null\"\n\nand print_assoc outc obj =\n  output_string outc \"{ \";\n  let sep = ref \"\" in\n  List.iter ~f:(fun (key, value) ->\n      printf \"%s\\\"%s\\\": %a\" !sep key output_value value;\n      sep := \",\\n  \") obj;\n  output_string outc \" }\"\n\nand print_list outc arr =\n  output_string outc \"[\";\n  List.iteri ~f:(fun i v ->\n      if i > 0 then\n        output_string outc \", \";\n      output_value outc v) arr;\n  output_string outc \"]\"\n"
  },
  {
    "path": "code/parsing/lex.syntax",
    "content": "{ OCaml code }\nlet definitions...\nrules...\n{ OCaml code }\n"
  },
  {
    "path": "code/parsing/lexer.mll",
    "content": "{\nopen Lexing\nopen Parser\n\nexception SyntaxError of string\n\nlet next_line lexbuf =\n  let pos = lexbuf.lex_curr_p in\n  lexbuf.lex_curr_p <-\n    { pos with pos_bol = lexbuf.lex_curr_pos;\n               pos_lnum = pos.pos_lnum + 1\n    }\n}\n\n(* part 1 *)\nlet int = '-'? ['0'-'9'] ['0'-'9']*\n\n(* part 2 *)\nlet digit = ['0'-'9']\nlet frac = '.' digit*\nlet exp = ['e' 'E'] ['-' '+']? digit+\nlet float = digit* frac? exp?\n\n(* part 3 *)\nlet white = [' ' '\\t']+\nlet newline = '\\r' | '\\n' | \"\\r\\n\"\nlet id = ['a'-'z' 'A'-'Z' '_'] ['a'-'z' 'A'-'Z' '0'-'9' '_']*\n\n(* part 4 *)\nrule read =\n  parse\n  | white    { read lexbuf }\n  | newline  { next_line lexbuf; read lexbuf }\n  | int      { INT (int_of_string (Lexing.lexeme lexbuf)) }\n  | float    { FLOAT (float_of_string (Lexing.lexeme lexbuf)) }\n  | \"true\"   { TRUE }\n  | \"false\"  { FALSE }\n  | \"null\"   { NULL }\n  | '\"'      { read_string (Buffer.create 17) lexbuf }\n  | '{'      { LEFT_BRACE }\n  | '}'      { RIGHT_BRACE }\n  | '['      { LEFT_BRACK }\n  | ']'      { RIGHT_BRACK }\n  | ':'      { COLON }\n  | ','      { COMMA }\n  | _ { raise (SyntaxError (\"Unexpected char: \" ^ Lexing.lexeme lexbuf)) }\n  | eof      { EOF }\n\n(* part 5 *)\nand read_string buf =\n  parse\n  | '\"'       { STRING (Buffer.contents buf) }\n  | '\\\\' '/'  { Buffer.add_char buf '/'; read_string buf lexbuf }\n  | '\\\\' '\\\\' { Buffer.add_char buf '\\\\'; read_string buf lexbuf }\n  | '\\\\' 'b'  { Buffer.add_char buf '\\b'; read_string buf lexbuf }\n  | '\\\\' 'f'  { Buffer.add_char buf '\\012'; read_string buf lexbuf }\n  | '\\\\' 'n'  { Buffer.add_char buf '\\n'; read_string buf lexbuf }\n  | '\\\\' 'r'  { Buffer.add_char buf '\\r'; read_string buf lexbuf }\n  | '\\\\' 't'  { Buffer.add_char buf '\\t'; read_string buf lexbuf }\n  | [^ '\"' '\\\\']+\n    { Buffer.add_string buf (Lexing.lexeme lexbuf);\n      read_string buf lexbuf\n    }\n  | _ { raise (SyntaxError (\"Illegal string character: \" ^ Lexing.lexeme lexbuf)) }\n  | eof { raise (SyntaxError (\"String is not terminated\")) }\n"
  },
  {
    "path": "code/parsing/lexer_int_fragment.mll",
    "content": "| int { INT (int_of_string (Lexing.lexeme lexbuf)) }\n"
  },
  {
    "path": "code/parsing/manual_token_type.ml",
    "content": "type token =\n  | NULL\n  | TRUE\n  | FALSE\n  | STRING of string\n  | INT of int\n  | FLOAT of float\n  | ID of string\n  | LEFT_BRACK\n  | RIGHT_BRACK\n  | LEFT_BRACE\n  | RIGHT_BRACE\n  | COMMA\n  | COLON\n  | EOF\n"
  },
  {
    "path": "code/parsing/parsed_example.ml",
    "content": "`Assoc\n  [\"title\", `String \"Cities\";\n   \"cities\", `List\n     [`Assoc [\"name\", `String \"Chicago\"; \"zips\", `List [`Int 60601]];\n      `Assoc [\"name\", `String \"New York\"; \"zips\", `List [`Int 10004]]]]\n"
  },
  {
    "path": "code/parsing/parser.mly",
    "content": "%token <int> INT\n%token <float> FLOAT\n%token <string> ID\n%token <string> STRING\n%token TRUE\n%token FALSE\n%token NULL\n%token LEFT_BRACE\n%token RIGHT_BRACE\n%token LEFT_BRACK\n%token RIGHT_BRACK\n%token COLON\n%token COMMA\n%token EOF\n(* part 1 *)\n%start <Json.value option> prog\n%%\n(* part 2 *)\nprog:\n  | EOF       { None }\n  | v = value { Some v }\n  ;\n\n(* part 3 *)\nvalue:\n  | LEFT_BRACE; obj = object_fields; RIGHT_BRACE\n    { `Assoc obj }\n  | LEFT_BRACK; vl = array_values; RIGHT_BRACK\n    { `List vl }\n  | s = STRING\n    { `String s }\n  | i = INT\n    { `Int i }\n  | x = FLOAT\n    { `Float x }\n  | TRUE\n    { `Bool true }\n  | FALSE\n    { `Bool false }\n  | NULL\n    { `Null }\n  ;\n\n(* part 4 *)\nobject_fields: obj = rev_object_fields { List.rev obj };\n\nrev_object_fields:\n  | (* empty *) { [] }\n  | obj = rev_object_fields; COMMA; k = ID; COLON; v = value\n    { (k, v) :: obj }\n  ;\n\n(* part 5 *)\narray_values:\n  | (* empty *) { [] }\n  | vl = rev_values { List.rev vl }\n  ;\n\nrev_values:\n  | v = value { [v] }\n  | vl = rev_values; COMMA; v = value\n    { v :: vl }\n  ;\n"
  },
  {
    "path": "code/parsing/production.syntax",
    "content": "symbol: [ id1 = ] symbol1; [ id2 = ] symbol2; ...; [ idN = ] symbolN\n   { OCaml code }\n"
  },
  {
    "path": "code/parsing/prog.mli",
    "content": "val prog:(Lexing.lexbuf -> token) -> Lexing.lexbuf -> Json.value option\n"
  },
  {
    "path": "code/parsing/quadratic_rule.mly",
    "content": "%token <int> INT\n%token <float> FLOAT\n%token <string> ID\n%token <string> STRING\n%token TRUE\n%token FALSE\n%token NULL\n%token LEFT_BRACE\n%token RIGHT_BRACE\n%token LEFT_BRACK\n%token RIGHT_BRACK\n%token COLON\n%token COMMA\n%token EOF\n(* part 1 *)\n%start <Json.value option> prog\n%%\n(* part 2 *)\nprog:\n  | EOF       { None }\n  | v = value { Some v }\n  ;\n\n(* part 3 *)\nvalue:\n  | LEFT_BRACE; obj = object_fields; RIGHT_BRACE\n    { `Assoc obj }\n  | LEFT_BRACK; vl = array_values; RIGHT_BRACK\n    { `List vl }\n  | s = STRING\n    { `String s }\n  | i = INT\n    { `Int i }\n  | x = FLOAT\n    { `Float x }\n  | TRUE\n    { `Bool true }\n  | FALSE\n    { `Bool false }\n  | NULL\n    { `Null }\n  ;\n\n(* part 4 *)\n(* Quadratic left-recursive rule *)\nobject_fields:\n  | (* empty *) { [] }\n  | obj = object_fields; COMMA; k = ID; COLON; v = value\n    { obj @ [k, v] }\n  ;\n\n(* part 5 *)\narray_values:\n  | (* empty *) { [] }\n  | vl = rev_values\n    { List.rev vl }\n  ;\n\nrev_values:\n  | v = value { [v] }\n  | vl = rev_values; COMMA; v = value\n    { v :: vl }\n  ;\n"
  },
  {
    "path": "code/parsing/right_rec_rule.mly",
    "content": "%token <int> INT\n%token <float> FLOAT\n%token <string> ID\n%token <string> STRING\n%token TRUE\n%token FALSE\n%token NULL\n%token LEFT_BRACE\n%token RIGHT_BRACE\n%token LEFT_BRACK\n%token RIGHT_BRACK\n%token COLON\n%token COMMA\n%token EOF\n(* part 1 *)\n%start <Json.value option> prog\n%%\n(* part 2 *)\nprog:\n  | EOF       { None }\n  | v = value { Some v }\n  ;\n\n(* part 3 *)\nvalue:\n  | LEFT_BRACE; obj = object_fields; RIGHT_BRACE\n    { `Assoc obj }\n  | LEFT_BRACK; vl = array_values; RIGHT_BRACK\n    { `List vl }\n  | s = STRING\n    { `String s }\n  | i = INT\n    { `Int i }\n  | x = FLOAT\n    { `Float x }\n  | TRUE\n    { `Bool true }\n  | FALSE\n    { `Bool false }\n  | NULL\n    { `Null }\n  ;\n\n(* part 4 *)\n(* Inefficient right-recursive rule *)\nobject_fields:\n  | (* empty *) { [] }\n  | k = ID; COLON; v = value; COMMA; obj = object_fields\n    { (k, v) :: obj }\n\n(* part 5 *)\narray_values: /* empty */\n    { [] }\n  | vl = rev_values\n    { List.rev vl }\n  ;\n\nrev_values: v = value\n    { [v] }\n  | vl = rev_values; COMMA; v = value\n    { v :: vl }\n  ;\n"
  },
  {
    "path": "code/parsing/short_parser.mly",
    "content": "%token <int> INT\n%token <float> FLOAT\n%token <string> STRING\n%token TRUE\n%token FALSE\n%token NULL\n%token LEFT_BRACE\n%token RIGHT_BRACE\n%token LEFT_BRACK\n%token RIGHT_BRACK\n%token COLON\n%token COMMA\n%token EOF\n\n%start <Json.value option> prog\n\n%%\n(* part 1 *)\nprog:\n  | v = value { Some v }\n  | EOF       { None   } ;\n\nvalue:\n  | LEFT_BRACE; obj = obj_fields; RIGHT_BRACE { `Assoc obj  }\n  | LEFT_BRACK; vl = list_fields; RIGHT_BRACK { `List vl    }\n  | s = STRING                                { `String s   }\n  | i = INT                                   { `Int i      }\n  | x = FLOAT                                 { `Float x    }\n  | TRUE                                      { `Bool true  }\n  | FALSE                                     { `Bool false }\n  | NULL                                      { `Null       } ;\n\nobj_fields:\n    obj = separated_list(COMMA, obj_field)    { obj } ;\n\nobj_field:\n    k = STRING; COLON; v = value              { (k, v) } ;\n\nlist_fields:\n    vl = separated_list(COMMA, value)         { vl } ;\n"
  },
  {
    "path": "code/parsing/tokenized_example.ml",
    "content": ""
  },
  {
    "path": "code/parsing/tokens.ml",
    "content": "[ LEFT_BRACE; ID(\"title\"); COLON; STRING(\"Cities\"); COMMA; ID(\"cities\"); ...\n"
  },
  {
    "path": "code/parsing/yacc.syntax",
    "content": "<declarations>\n%%\n<rules>\n%%\n<optional_ocaml_code>\n"
  },
  {
    "path": "code/parsing-test/build_json_parser.sh",
    "content": "corebuild -use-menhir parser.mli\n"
  },
  {
    "path": "code/parsing-test/build_test.sh",
    "content": "ocamlbuild -use-menhir -tag thread -use-ocamlfind -quiet -pkg core test.native\n./test.native test1.json\n"
  },
  {
    "path": "code/parsing-test/run_broken_test.errsh",
    "content": "cat test2.json\n./test.native test2.json\n"
  },
  {
    "path": "code/parsing-test/test.ml",
    "content": "open Core.Std\nopen Lexer\nopen Lexing\n\nlet print_position outx lexbuf =\n  let pos = lexbuf.lex_curr_p in\n  fprintf outx \"%s:%d:%d\" pos.pos_fname\n    pos.pos_lnum (pos.pos_cnum - pos.pos_bol + 1)\n\nlet parse_with_error lexbuf =\n  try Parser.prog Lexer.read lexbuf with\n  | SyntaxError msg ->\n    fprintf stderr \"%a: %s\\n\" print_position lexbuf msg;\n    None\n  | Parser.Error ->\n    fprintf stderr \"%a: syntax error\\n\" print_position lexbuf;\n    exit (-1)\n\n(* part 1 *)\nlet rec parse_and_print lexbuf =\n  match parse_with_error lexbuf with\n  | Some value ->\n    printf \"%a\\n\" Json.output_value value;\n    parse_and_print lexbuf\n  | None -> ()\n\nlet loop filename () =\n  let inx = In_channel.create filename in\n  let lexbuf = Lexing.from_channel inx in\n  lexbuf.lex_curr_p <- { lexbuf.lex_curr_p with pos_fname = filename };\n  parse_and_print lexbuf;\n  In_channel.close inx\n\n(* part 2 *)\nlet () =\n  Command.basic ~summary:\"Parse and display JSON\"\n    Command.Spec.(empty +> anon (\"filename\" %: file))\n    loop \n  |> Command.run\n"
  },
  {
    "path": "code/parsing-test/test1.json",
    "content": "true\nfalse\nnull\n[1, 2, 3., 4.0, .5, 5.5e5, 6.3]\n\"Hello World\"\n{ \"field1\": \"Hello\",\n  \"field2\": 17e13,\n  \"field3\": [1, 2, 3],\n  \"field4\": { \"fieldA\": 1, \"fieldB\": \"Hello\" }\n}\n"
  },
  {
    "path": "code/parsing-test/test2.json",
    "content": "{ \"name\": \"Chicago\",\n  \"zips\": [12345,\n}\n{ \"name\": \"New York\",\n  \"zips\": [10004]\n}\n"
  },
  {
    "path": "code/principal/build_principal.sh",
    "content": "corebuild -tag principal principal.cmi non_principal.cmi\n"
  },
  {
    "path": "code/records/functional_update.syntax",
    "content": "{ <record> with <field> = <value>;\n                <field> = <value>;\n                ...\n}\n"
  },
  {
    "path": "code/records/main-29.rawscript",
    "content": "# module Logon = struct\n    type t =\n      { session_id: string;\n        time: Time.t;\n        user: string;\n        credentials: string;\n      }\n    with fields\n  end;;\nmodule Logon :\n  sig\n    type t = {\n      session_id : string;\n      time : Time.t;\n      user : string;\n      credentials : string;\n    }\n    val credentials : t -> string\n    val user : t -> string\n    val time : t -> Time.t\n    val session_id : t -> string\n    module Fields :\n      sig\n        val names : string list\n        val credentials :\n          ([< `Read | `Set_and_create ], t, string) Field.t_with_perm\n        val user :\n          ([< `Read | `Set_and_create ], t, string) Field.t_with_perm\n        val time :\n          ([< `Read | `Set_and_create ], t, Time.t) Field.t_with_perm\n        val session_id :\n          ([< `Read | `Set_and_create ], t, string) Field.t_with_perm\n\n        [ ... many definitions omitted ... ]\n\n      end\n  end\n"
  },
  {
    "path": "code/records/main.topscript",
    "content": "type host_info =\n    { hostname   : string;\n      os_name    : string;\n      cpu_arch   : string;\n      timestamp  : Time.t;\n    };;\n#part 1\n#require \"core_extended\";;\nopen Core_extended.Std;;\nlet my_host =\n    let sh = Shell.sh_one_exn in\n    { hostname   = sh \"hostname\";\n      os_name    = sh \"uname -s\";\n      cpu_arch   = sh \"uname -p\";\n      timestamp  = Time.now ();\n    };;\n#part 2\nmy_host.cpu_arch;;\n#part 3\ntype 'a timestamped = { item: 'a; time: Time.t };;\n#part 4\nlet first_timestamped list =\n    List.reduce list ~f:(fun a b -> if a.time < b.time then a else b)\n  ;;\n#part 5\nlet host_info_to_string { hostname = h; os_name = os;\n                            cpu_arch = c; timestamp = ts;\n                          } =\n       sprintf \"%s (%s / %s, on %s)\" h os c (Time.to_sec_string ts);;\nhost_info_to_string my_host;;\n#part 6\ntype host_info =\n    { hostname   : string;\n      os_name    : string;\n      cpu_arch   : string;\n      os_release : string;\n      timestamp  : Time.t;\n    } ;;\n#part 7\n#warnings \"+9\";;\nlet host_info_to_string { hostname = h; os_name = os;\n                            cpu_arch = c; timestamp = ts;\n                          } =\n    sprintf \"%s (%s / %s, on %s)\" h os c (Time.to_sec_string ts);;\n#part 8\nlet host_info_to_string { hostname = h; os_name = os;\n                            cpu_arch = c; timestamp = ts; _\n                          } =\n    sprintf \"%s (%s / %s, on %s)\" h os c (Time.to_sec_string ts);;\n#part 9\nlet host_info_to_string { hostname; os_name; cpu_arch; timestamp; _ } =\n     sprintf \"%s (%s / %s) <%s>\" hostname os_name cpu_arch\n       (Time.to_string timestamp);;\n#part 10\nlet my_host =\n    let sh cmd = Shell.sh_one_exn cmd in\n    let hostname   = sh \"hostname\" in\n    let os_name    = sh \"uname -s\" in\n    let cpu_arch   = sh \"uname -p\" in\n    let os_release = sh \"uname -r\" in\n    let timestamp  = Time.now () in\n    { hostname; os_name; cpu_arch; os_release; timestamp };;\n#part 11\nlet create_host_info ~hostname ~os_name ~cpu_arch ~os_release =\n    { os_name; cpu_arch; os_release;\n      hostname = String.lowercase hostname;\n      timestamp = Time.now () };;\n#part 12\nlet create_host_info\n    ~hostname:hostname ~os_name:os_name\n    ~cpu_arch:cpu_arch ~os_release:os_release =\n    { os_name = os_name;\n      cpu_arch = cpu_arch;\n      os_release = os_release;\n      hostname = String.lowercase hostname;\n      timestamp = Time.now () };;\n#part 13\ntype log_entry =\n    { session_id: string;\n      time: Time.t;\n      important: bool;\n      message: string;\n    }\n  type heartbeat =\n    { session_id: string;\n      time: Time.t;\n      status_message: string;\n    }\n  type logon =\n    { session_id: string;\n      time: Time.t;\n      user: string;\n      credentials: string;\n    }\n;;\n#part 14\nlet get_session_id t = t.session_id;;\n#part 15\nlet get_heartbeat_session_id (t:heartbeat) = t.session_id;;\n#part 16\nlet status_and_session t = (t.status_message, t.session_id);;\nlet session_and_status t = (t.session_id, t.status_message);;\nlet session_and_status (t:heartbeat) = (t.session_id, t.status_message);;\n#part 17\nmodule Log_entry = struct\n    type t =\n      { session_id: string;\n        time: Time.t;\n        important: bool;\n        message: string;\n      }\n  end\n  module Heartbeat = struct\n    type t =\n      { session_id: string;\n        time: Time.t;\n        status_message: string;\n      }\n  end\n  module Logon = struct\n    type t =\n      { session_id: string;\n        time: Time.t;\n        user: string;\n        credentials: string;\n      }\n  end;;\n#part 18\nlet create_log_entry ~session_id ~important message =\n     { Log_entry.time = Time.now (); Log_entry.session_id;\n       Log_entry.important; Log_entry.message }\n  ;;\n#part 19\nlet create_log_entry ~session_id ~important message =\n     { Log_entry.\n       time = Time.now (); session_id; important; message }\n  ;;\n#part 20\nlet message_to_string { Log_entry.important; message; _ } =\n    if important then String.uppercase message else message\n  ;;\n#part 21\nlet is_important t = t.Log_entry.important;;\n#part 22\ntype client_info =\n   { addr: Unix.Inet_addr.t;\n     port: int;\n     user: string;\n     credentials: string;\n     last_heartbeat_time: Time.t;\n   };;\nlet register_heartbeat t hb =\n      { addr = t.addr;\n        port = t.port;\n        user = t.user;\n        credentials = t.credentials;\n        last_heartbeat_time = hb.Heartbeat.time;\n      };;\n#part 23\nlet register_heartbeat t hb =\n    { t with last_heartbeat_time = hb.Heartbeat.time };;\n#part 24\ntype client_info =\n   { addr: Unix.Inet_addr.t;\n     port: int;\n     user: string;\n     credentials: string;\n     last_heartbeat_time: Time.t;\n     last_heartbeat_status: string;\n   };;\n#part 25\nlet register_heartbeat t hb =\n    { t with last_heartbeat_time   = hb.Heartbeat.time;\n             last_heartbeat_status = hb.Heartbeat.status_message;\n    };;\n#part 26\ntype client_info =\n   { addr: Unix.Inet_addr.t;\n     port: int;\n     user: string;\n     credentials: string;\n     mutable last_heartbeat_time: Time.t;\n     mutable last_heartbeat_status: string;\n   };;\n#part 27\nlet register_heartbeat t hb =\n    t.last_heartbeat_time   <- hb.Heartbeat.time;\n    t.last_heartbeat_status <- hb.Heartbeat.status_message\n  ;;\n#part 28\nlet get_users logons =\n     List.dedup (List.map logons ~f:(fun x -> x.Logon.user));;\n#part 29\nmodule Logon = struct\n    type t =\n      { session_id: string;\n        time: Time.t;\n        user: string;\n        credentials: string;\n      }\n    with fields\n  end;;\n#part 30\nlet get_users logons = List.dedup (List.map logons ~f:Logon.user);;\n#part 31\nField.get Logon.Fields.user;;\n#part 32\nField.get;;\n#part 33\nlet show_field field to_string record =\n    let name = Field.name field in\n    let field_string = to_string (Field.get field record) in\n    name ^ \": \" ^ field_string\n  ;;\n#part 34\nlet logon = { Logon.\n                session_id = \"26685\";\n                time = Time.now ();\n                user = \"yminsky\";\n                credentials = \"Xy2d9W\"; }\n  ;;\nshow_field Logon.Fields.user Fn.id logon;;\nshow_field Logon.Fields.time Time.to_string logon;;\n#part 35\nLogon.Fields.iter;;\n#part 36\nlet print_logon logon =\n    let print to_string field =\n      printf \"%s\\n\" (show_field field to_string logon)\n    in\n    Logon.Fields.iter\n      ~session_id:(print Fn.id)\n      ~time:(print Time.to_string)\n      ~user:(print Fn.id)\n      ~credentials:(print Fn.id)\n  ;;\nprint_logon logon;;\n#part 37\n#part 38\n#part 39\n#part 40\n#part 41\n#part 42\n#part 43\n#part 44\n#part 45\n#part 46\n#part 47\n#part 48\n#part 49\n#part 50\n"
  },
  {
    "path": "code/records/record.syntax",
    "content": "type <record-name> =\n  { <field> : <type> ;\n    <field> : <type> ;\n    ...\n  }\n"
  },
  {
    "path": "code/records/warn_help.sh",
    "content": "ocaml -warn-help | egrep '\\b9\\b'\n"
  },
  {
    "path": "code/sexpr/auto_making_sexp.topscript",
    "content": "type t = { foo: int; bar: float } with sexp ;;\nt_of_sexp (Sexp.of_string \"((bar 35) (foo 3))\") ;;\n#part 1\nexception Bad_message of string list ;;\nExn.to_string (Bad_message [\"1\";\"2\";\"3\"]) ;;\nexception Good_message of string list with sexp;;\nExn.to_string (Good_message [\"1\";\"2\";\"3\"]) ;;\n"
  },
  {
    "path": "code/sexpr/basic.scm",
    "content": "(this (is an) (s expression))\n"
  },
  {
    "path": "code/sexpr/build_read_foo.errsh",
    "content": "corebuild read_foo.native\n./read_foo.native foo_example_broken.scm\n"
  },
  {
    "path": "code/sexpr/build_read_foo_better_errors.errsh",
    "content": "corebuild read_foo_better_errors.native\n./read_foo_better_errors.native foo_example_broken.scm\n"
  },
  {
    "path": "code/sexpr/build_test_interval.sh",
    "content": "corebuild test_interval.native\n./test_interval.native\n"
  },
  {
    "path": "code/sexpr/build_test_interval_manual_sexp.sh",
    "content": "corebuild test_interval_manual_sexp.native\n"
  },
  {
    "path": "code/sexpr/build_test_interval_nosexp.errsh",
    "content": "corebuild test_interval_nosexp.native\n"
  },
  {
    "path": "code/sexpr/comment_heavy.scm",
    "content": ";; comment_heavy_example.scm\n((this is included)\n ; (this is commented out\n (this stays)\n #; (all of this is commented\n     out (even though it crosses lines.))\n  (and #| block delimiters #| which can be nested |#\n     will comment out\n    an arbitrary multi-line block))) |#\n   now we're done\n   ))\n"
  },
  {
    "path": "code/sexpr/example.scm",
    "content": ";; example.scm\n\n((foo 3.3) ;; This is a comment\n (bar \"this is () an \\\" atom\"))\n"
  },
  {
    "path": "code/sexpr/example_broken.scm",
    "content": ";; example.scm\n\n((foo 3.3) ;; This is a comment\n  bar \"this is () an \\\" atom\"))\n"
  },
  {
    "path": "code/sexpr/example_load.topscript",
    "content": "Sexp.load_sexp \"example.scm\" ;;\n#part 1\nSexp.load_sexp \"comment_heavy.scm\" ;;\n#part 2\nExn.handle_uncaught ~exit:false (fun () ->\n    ignore (Sexp.load_sexp \"example_broken.scm\")) ;;\n"
  },
  {
    "path": "code/sexpr/foo_broken_example.scm",
    "content": "((a \"not-an-integer\")\n (b \"not-an-integer\")\n (c 1.0))\n"
  },
  {
    "path": "code/sexpr/inline_sexp.topscript",
    "content": "let l = [(1,\"one\"); (2,\"two\")] ;;\nList.iter l ~f:(fun x ->\n    <:sexp_of<int * string>> x\n    |> Sexp.to_string\n    |> print_endline) ;;\n"
  },
  {
    "path": "code/sexpr/int_interval.ml",
    "content": "(* Module for representing closed integer intervals *)\nopen Core.Std\n\n(* Invariant: For any Range (x,y), y >= x *)\ntype t =\n  | Range of int * int\n  | Empty\nwith sexp\n\nlet is_empty =\n  function \n  | Empty -> true \n  | Range _ -> false\n\nlet create x y =\n  if x > y then\n    Empty \n  else \n    Range (x,y)\n\nlet contains i x =\n  match i with\n  | Empty -> false\n  | Range (low,high) -> x >= low && x <= high\n"
  },
  {
    "path": "code/sexpr/int_interval.mli",
    "content": "type t with sexp\n\nval is_empty : t -> bool\nval create : int -> int -> t\nval contains : t -> int -> bool\n\n"
  },
  {
    "path": "code/sexpr/int_interval_manual_sexp.ml",
    "content": "(* Module for representing closed integer intervals *)\nopen Core.Std\n\n(* Invariant: For any Range (x,y), y >= x *)\ntype t =\n  | Range of int * int\n  | Empty\nwith sexp\n\nlet is_empty =\n  function \n  | Empty -> true \n  | Range _ -> false\n\nlet create x y =\n  if x > y then\n    Empty \n  else \n    Range (x,y)\n\nlet contains i x =\n  match i with\n  | Empty -> false\n  | Range (low,high) -> x >= low && x <= high\n"
  },
  {
    "path": "code/sexpr/int_interval_manual_sexp.mli",
    "content": "open Core.Std\n\ntype t\nval t_of_sexp : Sexp.t -> t\nval sexp_of_t : t -> Sexp.t\n\nval is_empty : t -> bool\nval create : int -> int -> t\nval contains : t -> int -> bool\n"
  },
  {
    "path": "code/sexpr/int_interval_nosexp.ml",
    "content": "(* Module for representing closed integer intervals *)\nopen Core.Std\n\n(* Invariant: For any Range (x,y), y >= x *)\ntype t =\n  | Range of int * int\n  | Empty\nwith sexp\n\nlet is_empty =\n  function \n  | Empty -> true \n  | Range _ -> false\n\nlet create x y =\n  if x > y then\n    Empty \n  else \n    Range (x,y)\n\nlet contains i x =\n  match i with\n  | Empty -> false\n  | Range (low,high) -> x >= low && x <= high\n"
  },
  {
    "path": "code/sexpr/int_interval_nosexp.mli",
    "content": "type t\n\nval is_empty : t -> bool\nval create : int -> int -> t\nval contains : t -> int -> bool\n"
  },
  {
    "path": "code/sexpr/list_top_packages.sh",
    "content": "ocamlfind list | grep top\n"
  },
  {
    "path": "code/sexpr/manually_making_sexp.topscript",
    "content": "type t = { foo: int; bar: float } ;;\nlet sexp_of_t t =\n    let a x = Sexp.Atom x and l x = Sexp.List x in\n    l [ l [a \"foo\"; Int.sexp_of_t t.foo  ];\n        l [a \"bar\"; Float.sexp_of_t t.bar]; ] ;;\nsexp_of_t { foo = 3; bar = -5.5 } ;;\n"
  },
  {
    "path": "code/sexpr/print_sexp.topscript",
    "content": "Sexp.List [\n    Sexp.Atom \"this\";\n    Sexp.List [ Sexp.Atom \"is\"; Sexp.Atom \"an\"];\n    Sexp.List [ Sexp.Atom \"s\"; Sexp.Atom \"expression\" ];\n  ];;\n"
  },
  {
    "path": "code/sexpr/read_foo.ml",
    "content": "open Core.Std\n\ntype t = { \n  a: string;\n  b: int;\n  c: float option \n} with sexp\n\nlet run () =\n  let t =\n    Sexp.load_sexp \"foo_broken_example.scm\"\n    |> t_of_sexp\n  in\n  printf \"b is: %d\\n%!\" t.b\n\nlet () =\n  Exn.handle_uncaught ~exit:true run\n"
  },
  {
    "path": "code/sexpr/read_foo_better_errors.ml",
    "content": "open Core.Std\n\ntype t = { \n  a: string;\n  b: int;\n  c: float option \n} with sexp\n\nlet run () =\n  let t = Sexp.load_sexp_conv_exn \"foo_broken_example.scm\" t_of_sexp in\n  printf \"b is: %d\\n%!\" t.b\n\nlet () =\n  Exn.handle_uncaught ~exit:true run\n"
  },
  {
    "path": "code/sexpr/sexp.mli",
    "content": "module Sexp : sig\n  type t =\n  | Atom of string\n  | List of t list\nend\n"
  },
  {
    "path": "code/sexpr/sexp_default.topscript",
    "content": "type http_server_config = {\n     web_root: string;\n     port: int;\n     addr: string;\n  } with sexp ;;\n#part 1\ntype http_server_config = {\n     web_root: string;\n     port: int with default(80);\n     addr: string with default(\"localhost\");\n  } with sexp ;;\n#part 2\nlet cfg = http_server_config_of_sexp\n   (Sexp.of_string \"((web_root /var/www/html))\") ;;\n#part 3\nsexp_of_http_server_config cfg ;;\n#part 4\ntype http_server_config = {\n     web_root: string;\n     port: int with default(80), sexp_drop_default;\n     addr: string with default(\"localhost\"), sexp_drop_default;\n  } with sexp ;;\nlet cfg = http_server_config_of_sexp\n  (Sexp.of_string \"((web_root /var/www/html))\") ;;\nsexp_of_http_server_config cfg ;;\n#part 5\nsexp_of_http_server_config { cfg with port = 8080 } ;;\nsexp_of_http_server_config\n  { cfg with port = 8080; addr = \"192.168.0.1\" } ;;\n"
  },
  {
    "path": "code/sexpr/sexp_list.topscript",
    "content": "type compatible_versions =\n  | Specific of string list\n  | All with sexp ;;\nsexp_of_compatible_versions\n  (Specific [\"3.12.0\"; \"3.12.1\"; \"3.13.0\"]) ;;\n#part 1\ntype compatible_versions =\n  | Specific of string sexp_list\n  | All with sexp ;;\nsexp_of_compatible_versions\n  (Specific [\"3.12.0\"; \"3.12.1\"; \"3.13.0\"]) ;;\n"
  },
  {
    "path": "code/sexpr/sexp_opaque.topscript",
    "content": "type no_converter = int * int ;;\ntype t = { a: no_converter; b: string } with sexp ;;\n#part 1\ntype t = { a: no_converter sexp_opaque; b: string } with sexp ;;\n#part 2\nsexp_of_t { a = (3,4); b = \"foo\" } ;;\n#part 3\nt_of_sexp (Sexp.of_string \"((a whatever) (b foo))\") ;;\n#part 4\ntype t = { a: no_converter sexp_opaque list; b: string } with sexp ;;\nt_of_sexp (Sexp.of_string \"((a ()) (b foo))\") ;;\n#part 5\ntype t = { a: no_converter sexp_opaque; b: string } with sexp_of ;;\ntype t = { a: no_converter sexp_opaque; b: string } with of_sexp ;;\n"
  },
  {
    "path": "code/sexpr/sexp_option.topscript",
    "content": "type t = { a: int option; b: string } with sexp ;;\nsexp_of_t { a = None; b = \"hello\" } ;;\nsexp_of_t { a = Some 3; b = \"hello\" } ;;\n#part 1\ntype t = { a: int sexp_option; b: string } with sexp ;;\nsexp_of_t { a = Some 3; b = \"hello\" } ;;\nsexp_of_t { a = None; b = \"hello\" } ;;\n"
  },
  {
    "path": "code/sexpr/sexp_override.ml",
    "content": "type t =\n  | Range of int * int\n  | Empty\nwith sexp\n\nlet create x y =\n  if x > y then Empty else Range (x,y)\n\nlet t_of_sexp sexp =\n  let t = t_of_sexp sexp in\n  begin match t with\n    | Empty -> ()\n    | Range (x,y) ->\n      if y < x then of_sexp_error \"Upper and lower bound of Range swapped\" sexp\n  end;\n  t\n"
  },
  {
    "path": "code/sexpr/sexp_printer.topscript",
    "content": "Sexp.to_string (Sexp.List [Sexp.Atom \"1\"; Sexp.Atom \"2\"]) ;;\nSexp.of_string (\"(1 2 (3 4))\") ;;\n"
  },
  {
    "path": "code/sexpr/test_interval.ml",
    "content": "open Core.Std\n\nlet intervals =\n  let module I = Int_interval in\n  [ I.create 3 4;\n    I.create 5 4; (* should be empty *)\n    I.create 2 3;\n    I.create 1 6;\n  ]\n\nlet () =\n  intervals\n  |> List.sexp_of_t Int_interval.sexp_of_t\n  |> Sexp.to_string_hum\n  |> print_endline\n"
  },
  {
    "path": "code/sexpr/test_interval_manual_sexp.ml",
    "content": "open Core.Std\nmodule Int_interval = Int_interval_manual_sexp\n\nlet intervals =\n  let module I = Int_interval in\n  [ I.create 3 4;\n    I.create 5 4; (* should be empty *)\n    I.create 2 3;\n    I.create 1 6;\n  ]\n\nlet () =\n  intervals\n  |> List.sexp_of_t Int_interval.sexp_of_t\n  |> Sexp.to_string_hum\n  |> print_endline\n"
  },
  {
    "path": "code/sexpr/test_interval_nosexp.ml",
    "content": "open Core.Std\nmodule Int_interval = Int_interval_nosexp\n\nlet intervals =\n  let module I = Int_interval in\n  [ I.create 3 4;\n    I.create 5 4; (* should be empty *)\n    I.create 2 3;\n    I.create 1 6;\n  ]\n\nlet () =\n  intervals\n  |> List.sexp_of_t Int_interval.sexp_of_t\n  |> Sexp.to_string_hum\n  |> print_endline\n"
  },
  {
    "path": "code/sexpr/to_from_sexp.topscript",
    "content": "Int.sexp_of_t 3;;\nString.sexp_of_t \"hello\";;\nExn.sexp_of_t (Invalid_argument \"foo\");;\n#part 1\nList.sexp_of_t;;\nList.sexp_of_t Int.sexp_of_t [1; 2; 3];;\n#part 2\nList.t_of_sexp;;\nList.t_of_sexp Int.t_of_sexp (Sexp.of_string \"(1 2 3)\");;\nList.t_of_sexp Int.t_of_sexp (Sexp.of_string \"(1 2 three)\");;\n"
  },
  {
    "path": "code/variables-and-functions/abs_diff.mli",
    "content": "val abs_diff : int -> (int -> int)\n"
  },
  {
    "path": "code/variables-and-functions/htable_sig1.ml",
    "content": "val create_hashtable : int -> bool -> ('a,'b) Hashtable.t\n"
  },
  {
    "path": "code/variables-and-functions/htable_sig2.ml",
    "content": "val create_hashtable :\n  init_size:int -> allow_shrinking:bool -> ('a,'b) Hashtable.t\n"
  },
  {
    "path": "code/variables-and-functions/let.syntax",
    "content": "let <variable> = <expr>\n"
  },
  {
    "path": "code/variables-and-functions/let_in.syntax",
    "content": "let <variable> = <expr1> in <expr2>\n"
  },
  {
    "path": "code/variables-and-functions/main.topscript",
    "content": "let x = 3;;\nlet y = 4;;\nlet z = x + y;;\n#part 1\nlet languages = \"OCaml,Perl,C++,C\";;\nlet dashed_languages =\n    let language_list = String.split languages ~on:',' in\n    String.concat ~sep:\"-\" language_list\n  ;;\n#part 2\nlanguage_list;;\n#part 3\nlet languages = \"OCaml,Perl,C++,C\";;\nlet dashed_languages =\n     let languages = String.split languages ~on:',' in\n     String.concat ~sep:\"-\" languages\n  ;;\n#part 4\nlanguages;;\n#part 5\nlet area_of_ring inner_radius outer_radius =\n     let pi = acos (-1.) in\n     let area_of_circle r = pi *. r *. r in\n     area_of_circle outer_radius -. area_of_circle inner_radius\n  ;;\narea_of_ring 1. 3.;;\n#part 6\nlet area_of_ring inner_radius outer_radius =\n     let pi = acos (-1.) in\n     let area_of_circle r = pi *. r *. r in\n     let pi = 0. in\n     area_of_circle outer_radius -. area_of_circle inner_radius\n  ;;\n#part 7\nlet (ints,strings) = List.unzip [(1,\"one\"); (2,\"two\"); (3,\"three\")];;\n#part 8\nlet upcase_first_entry line =\n     let (first :: rest) = String.split ~on:',' line in\n     String.concat ~sep:\",\" (String.uppercase first :: rest)\n  ;;\n#part 9\nlet upcase_first_entry line =\n     match String.split ~on:',' line with\n     | [] -> assert false (* String.split returns at least one element *)\n     | first :: rest -> String.concat ~sep:\",\" (String.uppercase first :: rest)\n  ;;\n#part 10\n(fun x -> x + 1);;\n#part 11\n(fun x -> x + 1) 7;;\n#part 12\nList.map ~f:(fun x -> x + 1) [1;2;3];;\n#part 13\nlet increments = [ (fun x -> x + 1); (fun x -> x + 2) ] ;;\nList.map ~f:(fun g -> g 5) increments;;\n#part 14\nlet plusone = (fun x -> x + 1);;\nplusone 3;;\n#part 15\nlet plusone x = x + 1;;\n#part 16\n(fun x -> x + 1) 7;;\nlet x = 7 in x + 1;;\n#part 17\nlet abs_diff x y = abs (x - y);;\nabs_diff 3 4;;\n#part 18\nlet abs_diff =\n    (fun x -> (fun y -> abs (x - y)));;\n#part 19\nlet dist_from_3 = abs_diff 3;;\ndist_from_3 8;;\ndist_from_3 (-1);;\n#part 20\nlet abs_diff = (fun x y -> abs (x - y));;\n#part 21\nlet abs_diff (x,y) = abs (x - y);;\nabs_diff (3,4);;\n#part 22\nlet rec find_first_stutter list =\n    match list with\n    | [] | [_] ->\n      (* only zero or one elements, so no repeats *)\n      None\n    | x :: y :: tl ->\n      if x = y then Some x else find_first_stutter (y::tl)\n   ;;\n#part 23\nlet rec is_even x =\n    if x = 0 then true else is_odd (x - 1)\n  and is_odd x =\n    if x = 0 then false else is_even (x - 1)\n ;;\nList.map ~f:is_even [0;1;2;3;4;5];;\nList.map ~f:is_odd [0;1;2;3;4;5];;\n#part 24\nInt.max 3 4  (* prefix *);;\n3 + 4        (* infix  *);;\n#part 25\n(+) 3 4;;\nList.map ~f:((+) 3) [4;5;6];;\n#part 26\nlet (+!) (x1,y1) (x2,y2) = (x1 + x2, y1 + y2);;\n(3,2) +! (-2,4);;\n#part 27\nlet (***) x y = (x ** y) ** y;;\n#part 28\nlet ( *** ) x y = (x ** y) ** y;;\n#part 29\nInt.max 3 (-4);;\nInt.max 3 -4;;\n#part 30\n(Int.max 3) - 4;;\n#part 31\nlet (|>) x f = f x ;;\n#part 32\nlet path = \"/usr/bin:/usr/local/bin:/bin:/sbin\";;\n  String.split ~on:':' path\n  |> List.dedup ~compare:String.compare\n  |> List.iter ~f:print_endline\n  ;;\n#part 33\n  let split_path = String.split ~on:':' path in\n  let deduped_path = List.dedup ~compare:String.compare split_path in\n  List.iter ~f:print_endline deduped_path\n  ;;\n#part 34\nList.iter ~f:print_endline [\"Two\"; \"lines\"];;\n#part 35\nList.iter ~f:print_endline;;\n#part 36\nlet (^>) x f = f x;;\nSys.getenv_exn \"PATH\"\n  ^> String.split ~on:':' path\n  ^> List.dedup ~compare:String.compare\n  ^> List.iter ~f:print_endline\n  ;;\n#part 37\nlet some_or_zero = function\n     | Some x -> x\n     | None -> 0\n  ;;\nList.map ~f:some_or_zero [Some 3; None; Some 4];;\n#part 38\nlet some_or_zero num_opt =\n    match num_opt with\n    | Some x -> x\n    | None -> 0\n  ;;\n#part 39\nlet some_or_default default = function\n     | Some x -> x\n     | None -> default\n  ;;\nsome_or_default 3 (Some 5);;\nList.map ~f:(some_or_default 100) [Some 3; None; Some 4];;\n#part 40\nlet ratio ~num ~denom = float num /. float denom;;\n#part 41\nratio ~num:3 ~denom:10;;\nratio ~denom:10 ~num:3;;\n#part 42\nlet num = 3 in\nlet denom = 4 in\nratio ~num ~denom;;\n#part 43\n  String.split ~on:':' path\n  |> List.dedup ~compare:String.compare\n  |> List.iter ~f:print_endline\n  ;;\n#part 44\nlet apply_to_tuple f (first,second) = f ~first ~second;;\n#part 45\nlet apply_to_tuple_2 f (first,second) = f ~second ~first;;\n#part 46\nlet divide ~first ~second = first / second;;\n#part 47\napply_to_tuple_2 divide (3,4);;\n#part 48\nlet apply_to_tuple f (first,second) = f ~first ~second;;\napply_to_tuple divide (3,4);;\n#part 49\nlet concat ?sep x y =\n     let sep = match sep with None -> \"\" | Some x -> x in\n     x ^ sep ^ y\n  ;;\nconcat \"foo\" \"bar\"             (* without the optional argument *);;\nconcat ~sep:\":\" \"foo\" \"bar\"    (* with the optional argument    *);;\n#part 50\nlet concat ?(sep=\"\") x y = x ^ sep ^ y ;;\n#part 51\nconcat ~sep:\":\" \"foo\" \"bar\" (* provide the optional argument *);;\nconcat ?sep:(Some \":\") \"foo\" \"bar\" (* pass an explicit [Some] *);;\n#part 52\nconcat \"foo\" \"bar\" (* don't provide the optional argument *);;\nconcat ?sep:None \"foo\" \"bar\" (* explicitly pass `None` *);;\n#part 53\nlet uppercase_concat ?(sep=\"\") a b = concat ~sep (String.uppercase a) b ;;\nuppercase_concat \"foo\" \"bar\";;\nuppercase_concat \"foo\" \"bar\" ~sep:\":\";;\n#part 54\nlet uppercase_concat ?sep a b = concat ?sep (String.uppercase a) b ;;\n#part 55\nlet numeric_deriv ~delta ~x ~y ~f =\n    let x' = x +. delta in\n    let y' = y +. delta in\n    let base = f ~x ~y in\n    let dx = (f ~x:x' ~y -. base) /. delta in\n    let dy = (f ~x ~y:y' -. base) /. delta in\n    (dx,dy)\n  ;;\n#part 56\nlet numeric_deriv ~delta ~x ~y ~f =\n    let x' = x +. delta in\n    let y' = y +. delta in\n    let base = f ~x ~y in\n    let dx = (f ~y ~x:x' -. base) /. delta in\n    let dy = (f ~x ~y:y' -. base) /. delta in\n    (dx,dy)\n  ;;\n#part 57\nlet numeric_deriv ~delta ~x ~y ~(f: x:float -> y:float -> float) =\n    let x' = x +. delta in\n    let y' = y +. delta in\n    let base = f ~x ~y in\n    let dx = (f ~y ~x:x' -. base) /. delta in\n    let dy = (f ~x ~y:y' -. base) /. delta in\n    (dx,dy)\n  ;;\n#part 58\nlet colon_concat = concat ~sep:\":\";;\ncolon_concat \"a\" \"b\";;\n#part 59\nlet prepend_pound = concat \"# \";;\nprepend_pound \"a BASH comment\";;\n#part 60\nprepend_pound \"a BASH comment\" ~sep:\":\";;\n#part 61\nlet concat x ?(sep=\"\") y = x ^ sep ^ y ;;\n#part 62\nlet prepend_pound = concat \"# \";;\nprepend_pound \"a BASH comment\";;\nprepend_pound \"a BASH comment\" ~sep:\"--- \";;\n#part 63\nconcat \"a\" \"b\" ~sep:\"=\";;\n#part 64\nlet concat x y ?(sep=\"\") = x ^ sep ^ y ;;\n#part 65\nconcat \"a\" \"b\";;\n#part 66\n#part 67\n#part 68\n#part 69\n#part 70\n#part 71\n#part 72\n#part 73\n#part 74\n#part 75\n#part 76\n#part 77\n#part 78\n#part 79\n"
  },
  {
    "path": "code/variables-and-functions/numerical_deriv_alt_sig.mli",
    "content": "val numeric_deriv :\n  delta:float ->\n  x:float -> y:float -> f:(?x:float -> y:float -> float) -> float * float\n\n"
  },
  {
    "path": "code/variables-and-functions/operators.syntax",
    "content": "! $ % & * + - . / : < = > ? @ ^ | ~\n"
  },
  {
    "path": "code/variables-and-functions/substring_sig1.ml",
    "content": "val substring: string -> int -> int -> string\n"
  },
  {
    "path": "code/variables-and-functions/substring_sig2.ml",
    "content": "val substring: string -> pos:int -> len:int -> string\n"
  },
  {
    "path": "code/variants/blang.topscript",
    "content": "type 'a expr =\n    | Base  of 'a\n    | Const of bool\n    | And   of 'a expr list\n    | Or    of 'a expr list\n    | Not   of 'a expr\n  ;;\n#part 1\ntype mail_field = To | From | CC | Date | Subject\n  type mail_predicate = { field: mail_field;\n                          contains: string }\n  ;;\n#part 2\nlet test field contains = Base { field; contains };;\nAnd [ Or [ test To \"doligez\"; test CC \"doligez\" ];\n        test Subject \"runtime\";\n      ]\n  ;;\n#part 3\nlet rec eval expr base_eval =\n    (* a shortcut, so we don't need to repeatedly pass [base_eval]\n       explicitly to [eval] *)\n    let eval' expr = eval expr base_eval in\n    match expr with\n    | Base  base   -> base_eval base\n    | Const bool   -> bool\n    | And   exprs -> List.for_all exprs ~f:eval'\n    | Or    exprs -> List.exists  exprs ~f:eval'\n    | Not   expr  -> not (eval' expr)\n  ;;\n#part 4\nlet and_ l =\n    if List.mem l (Const false) then Const false\n    else\n      match List.filter l ~f:((<>) (Const true)) with\n      | [] -> Const true\n      | [ x ] -> x\n      | l -> And l\n\n  let or_ l =\n    if List.mem l (Const true) then Const true\n    else\n      match List.filter l ~f:((<>) (Const false)) with\n      | [] -> Const false\n      | [x] -> x\n      | l -> Or l\n\n  let not_ = function\n    | Const b -> Const (not b)\n    | e -> Not e\n  ;;\n#part 5\nlet rec simplify = function\n    | Base _ | Const _ as x -> x\n    | And l -> and_ (List.map ~f:simplify l)\n    | Or l  -> or_  (List.map ~f:simplify l)\n    | Not e -> not_ (simplify e)\n  ;;\n#part 6\nsimplify (Not (And [ Or [Base \"it's snowing\"; Const true];\n                       Base \"it's raining\"]));;\n#part 7\nsimplify (Not (And [ Or [Base \"it's snowing\"; Const true];\n                       Not (Not (Base \"it's raining\"))]));;\n#part 8\nlet not_ = function\n    | Const b -> Const (not b)\n    | (Base _ | And _ | Or _ | Not _) as e -> Not e\n  ;;\n#part 9\nlet not_ = function\n    | Const b -> Const (not b)\n    | Not e -> e\n    | (Base _ | And _ | Or _ ) as e -> Not e\n  ;;\n"
  },
  {
    "path": "code/variants/catch_all.topscript",
    "content": "type basic_color =\n   | Black | Red | Green | Yellow | Blue | Magenta | Cyan | White ;;\nlet basic_color_to_int = function\n  | Black -> 0 | Red     -> 1 | Green -> 2 | Yellow -> 3\n  | Blue  -> 4 | Magenta -> 5 | Cyan  -> 6 | White  -> 7 ;;\n#part 1\ntype color =\n  | Basic of basic_color     (* basic colors *)\n  | Bold  of basic_color     (* bold basic colors *)\n  | RGB   of int * int * int (* 6x6x6 color cube *)\n  | Gray  of int             (* 24 grayscale levels *)\n;;\n#part 2\nlet color_to_int = function\n    | Basic (basic_color,weight) ->\n      let base = match weight with Bold -> 8 | Regular -> 0 in\n      base + basic_color_to_int basic_color\n    | RGB (r,g,b) -> 16 + b + g * 6 + r * 36\n    | Gray i -> 232 + i ;;\n#part 3\nlet color_to_int = function\n    | Basic basic_color -> basic_color_to_int basic_color\n    | RGB (r,g,b) -> 16 + b + g * 6 + r * 36\n    | Gray i -> 232 + i ;;\n#part 4\nlet color_to_int = function\n    | Basic basic_color -> basic_color_to_int basic_color\n    | Bold  basic_color -> 8 + basic_color_to_int basic_color\n    | RGB (r,g,b) -> 16 + b + g * 6 + r * 36\n    | Gray i -> 232 + i ;;\n#part 5\nlet oldschool_color_to_int = function\n    | Basic (basic_color,weight) ->\n      let base = match weight with Bold -> 8 | Regular -> 0 in\n      base + basic_color_to_int basic_color\n    | _ -> basic_color_to_int White;;\n   \n"
  },
  {
    "path": "code/variants/logger.topscript",
    "content": "  module Heartbeat = struct\n    type t =\n      { session_id: string;\n        time: Time.t;\n        status_message: string;\n      }\n  end\n  module Logon = struct\n    type t =\n      { session_id: string;\n        time: Time.t;\n        user: string;\n        credentials: string;\n      }\n  end;;\n#part 1\nmodule Log_entry = struct\n    type t =\n      { session_id: string;\n        time: Time.t;\n        important: bool;\n        message: string;\n      }\n  end\n  ;;\n#part 2\ntype client_message = | Logon of Logon.t\n                        | Heartbeat of Heartbeat.t\n                        | Log_entry of Log_entry.t\n  ;;\n#part 3\nlet messages_for_user user messages =\n    let (user_messages,_) =\n      List.fold messages ~init:([],String.Set.empty)\n        ~f:(fun ((messages,user_sessions) as acc) message ->\n          match message with\n          | Logon m ->\n            if m.Logon.user = user then\n              (message::messages, Set.add user_sessions m.Logon.session_id)\n            else acc\n          | Heartbeat _ | Log_entry _ ->\n            let session_id = match message with\n              | Logon     m -> m.Logon.session_id\n              | Heartbeat m -> m.Heartbeat.session_id\n              | Log_entry m -> m.Log_entry.session_id\n            in\n            if Set.mem user_sessions session_id then\n              (message::messages,user_sessions)\n            else acc\n        )\n    in\n    List.rev user_messages\n  ;;\n#part 4\nmodule Log_entry = struct\n    type t = { important: bool;\n               message: string;\n             }\n  end\n  module Heartbeat = struct\n    type t = { status_message: string; }\n  end\n  module Logon = struct\n    type t = { user: string;\n               credentials: string;\n             }\n  end ;;\n#part 5\ntype details =\n    | Logon of Logon.t\n    | Heartbeat of Heartbeat.t\n    | Log_entry of Log_entry.t\n ;;\n#part 6\nmodule Common = struct\n    type t = { session_id: string;\n               time: Time.t;\n             }\n  end ;;\n#part 7\nlet messages_for_user user messages =\n    let (user_messages,_) =\n      List.fold messages ~init:([],String.Set.empty)\n        ~f:(fun ((messages,user_sessions) as acc) ((common,details) as message) ->\n          let session_id = common.Common.session_id in\n          match details with\n          | Logon m ->\n            if m.Logon.user = user then\n              (message::messages, Set.add user_sessions session_id)\n            else acc\n          | Heartbeat _ | Log_entry _ ->\n            if Set.mem user_sessions session_id then\n              (message::messages,user_sessions)\n            else acc\n        )\n    in\n    List.rev user_messages\n  ;;\n#part 8\nlet handle_message server_state (common,details) =\n    match details with\n    | Log_entry m -> handle_log_entry server_state (common,m)\n    | Logon     m -> handle_logon     server_state (common,m)\n    | Heartbeat m -> handle_heartbeat server_state (common,m)\n  ;;\n"
  },
  {
    "path": "code/variants/main-2.rawscript",
    "content": "# let color_by_number number text =\n    sprintf \"\\027[38;5;%dm%s\\027[0m\" number text;;\nval color_by_number : int -> string -> string = <fun>\n# let blue = color_by_number (basic_color_to_int Blue) \"Blue\";;\nval blue : string = \"\\027[38;5;4mBlue\\027[0m\"\n# printf \"Hello %s World!\\n\" blue;;\nHello Blue World!\n"
  },
  {
    "path": "code/variants/main-5.rawscript",
    "content": "# let color_print color s =\n     printf \"%s\\n\" (color_by_number (color_to_int color) s);;\nval color_print : color -> string -> unit = <fun>\n# color_print (Basic (Red,Bold)) \"A bold red!\";;\nA bold red!\n# color_print (Gray 4) \"A muted gray...\";;\nA muted gray...\n"
  },
  {
    "path": "code/variants/main.topscript",
    "content": "type basic_color =\n   | Black | Red | Green | Yellow | Blue | Magenta | Cyan | White ;;\nCyan ;;\n[Blue; Magenta; Red] ;;\n#part 1\nlet basic_color_to_int = function\n  | Black -> 0 | Red     -> 1 | Green -> 2 | Yellow -> 3\n  | Blue  -> 4 | Magenta -> 5 | Cyan  -> 6 | White  -> 7 ;;\nList.map ~f:basic_color_to_int [Blue;Red];;\n#part 2\nlet color_by_number number text =\n    sprintf \"\\027[38;5;%dm%s\\027[0m\" number text;;\nlet blue = color_by_number (basic_color_to_int Blue) \"Blue\";;\n(* printf \"Hello %s World!\\n\" blue*) ();;\n#part 3\ntype weight = Regular | Bold\n  type color =\n  | Basic of basic_color * weight (* basic colors, regular and bold *)\n  | RGB   of int * int * int       (* 6x6x6 color cube *)\n  | Gray  of int                   (* 24 grayscale levels *)\n;;\n[RGB (250,70,70); Basic (Green, Regular)];;\n#part 4\nlet color_to_int = function\n    | Basic (basic_color,weight) ->\n      let base = match weight with Bold -> 8 | Regular -> 0 in\n      base + basic_color_to_int basic_color\n    | RGB (r,g,b) -> 16 + b + g * 6 + r * 36\n    | Gray i -> 232 + i ;;\n#part 5\nlet color_print color s =\n     printf \"%s\\n\" (color_by_number (color_to_int color) s);;\n(* color_print (Basic (Red,Bold)) \"A bold red!\"*) ();;\n(* color_print (Gray 4) \"A muted gray...\" *) ();;\n#part 6\nlet three = `Int 3;;\nlet four = `Float 4.;;\nlet nan = `Not_a_number;;\n[three; four; nan];;\n#part 7\nlet five = `Int \"five\";;\n[three; four; five];;\n#part 8\nlet is_positive = function\n     | `Int   x -> x > 0\n     | `Float x -> x > 0.\n  ;;\n#part 9\nlet exact = List.filter ~f:is_positive [three;four];;\n#part 10\nlet is_positive = function\n     | `Int   x -> Ok (x > 0)\n     | `Float x -> Ok (x > 0.)\n     | `Not_a_number -> Error \"not a number\";;\nList.filter [three; four] ~f:(fun x ->\n     match is_positive x with Error _ -> false | Ok b -> b);;\n#part 11\ntype extended_color =\n    | Basic of basic_color * weight  (* basic colors, regular and bold *)\n    | RGB   of int * int * int       (* 6x6x6 color space *)\n    | Gray  of int                   (* 24 grayscale levels *)\n    | RGBA  of int * int * int * int (* 6x6x6x6 color space *)\n  ;;\n#part 12\nlet extended_color_to_int = function\n    | RGBA (r,g,b,a) -> 256 + a + b * 6 + g * 36 + r * 216\n    | (Basic _ | RGB _ | Gray _) as color -> color_to_int color\n  ;;\n#part 13\nlet basic_color_to_int = function\n    | `Black -> 0 | `Red     -> 1 | `Green -> 2 | `Yellow -> 3\n    | `Blue  -> 4 | `Magenta -> 5 | `Cyan  -> 6 | `White  -> 7\n\n  let color_to_int = function\n    | `Basic (basic_color,weight) ->\n      let base = match weight with `Bold -> 8 | `Regular -> 0 in\n      base + basic_color_to_int basic_color\n    | `RGB (r,g,b) -> 16 + b + g * 6 + r * 36\n    | `Gray i -> 232 + i\n ;;\n#part 14\nlet extended_color_to_int = function\n    | `RGBA (r,g,b,a) -> 256 + a + b * 6 + g * 36 + r * 216\n    | (`Basic _ | `RGB _ | `Gray _) as color -> color_to_int color\n  ;;\n#part 15\nlet extended_color_to_int = function\n    | `RGBA (r,g,b,a) -> 256 + a + b * 6 + g * 36 + r * 216\n    | color -> color_to_int color\n  ;;\n#part 16\nlet is_positive_permissive = function\n     | `Int   x -> Ok (x > 0)\n     | `Float x -> Ok (x > 0.)\n     | _ -> Error \"Unknown number type\"\n  ;;\nis_positive_permissive (`Int 0);;\nis_positive_permissive (`Ratio (3,4));;\n#part 17\nis_positive_permissive (`Floot 3.5);;\n#part 18\n#part 19\n#part 20\n#part 21\n#part 22\n#part 23\n#part 24\n#part 25\n#part 26\n#part 27\n#part 28\n#part 29\n#part 30\n#part 31\n#part 32\n#part 33\n#part 34\n#part 35\n#part 36\n#part 37\n#part 38\n#part 39\n#part 40\n#part 41\n#part 42\n#part 43\n#part 44\n#part 45\n#part 46\n#part 47\n#part 48\n#part 49\n#part 50\n\n"
  },
  {
    "path": "code/variants/variant.syntax",
    "content": "type <variant> =\n  | <Tag> [ of <type> [* <type>]... ]\n  | <Tag> [ of <type> [* <type>]... ]\n  | ...\n"
  },
  {
    "path": "code/variants-termcol/build.sh",
    "content": "corebuild terminal_color.native\n"
  },
  {
    "path": "code/variants-termcol/terminal_color.ml",
    "content": "open Core.Std\n\ntype basic_color =\n  [ `Black   | `Blue | `Cyan  | `Green\n  | `Magenta | `Red  | `White | `Yellow ]\n\ntype color =\n  [ `Basic of basic_color * [ `Bold | `Regular ]\n  | `Gray of int\n  | `RGB  of int * int * int ]\n\ntype extended_color =\n  [ color\n  | `RGBA of int * int * int * int ]\n\nlet basic_color_to_int = function\n  | `Black -> 0 | `Red     -> 1 | `Green -> 2 | `Yellow -> 3\n  | `Blue  -> 4 | `Magenta -> 5 | `Cyan  -> 6 | `White  -> 7\n\nlet color_to_int = function\n  | `Basic (basic_color,weight) ->\n    let base = match weight with `Bold -> 8 | `Regular -> 0 in\n    base + basic_color_to_int basic_color\n  | `RGB (r,g,b) -> 16 + b + g * 6 + r * 36\n  | `Gray i -> 232 + i\n\nlet extended_color_to_int = function\n  | `RGBA (r,g,b,a) -> 256 + a + b * 6 + g * 36 + r * 216\n  | `Grey x -> 2000 + x\n  | (`Basic _ | `RGB _ | `Gray _) as color -> color_to_int color\n"
  },
  {
    "path": "code/variants-termcol/terminal_color.mli",
    "content": "open Core.Std\n\ntype basic_color =\n  [ `Black   | `Blue | `Cyan  | `Green\n  | `Magenta | `Red  | `White | `Yellow ]\n\ntype color =\n  [ `Basic of basic_color * [ `Bold | `Regular ]\n  | `Gray of int\n  | `RGB  of int * int * int ]\n\ntype extended_color =\n  [ color\n  | `RGBA of int * int * int * int ]\n\nval color_to_int          : color -> int\nval extended_color_to_int : extended_color -> int\n"
  },
  {
    "path": "code/variants-termcol-annotated/build.errsh",
    "content": "corebuild terminal_color.native\n"
  },
  {
    "path": "code/variants-termcol-annotated/terminal_color.ml",
    "content": "open Core.Std\n\ntype basic_color =\n  [ `Black   | `Blue | `Cyan  | `Green\n  | `Magenta | `Red  | `White | `Yellow ]\n\ntype color =\n  [ `Basic of basic_color * [ `Bold | `Regular ]\n  | `Gray of int\n  | `RGB  of int * int * int ]\n\ntype extended_color =\n  [ color\n  | `RGBA of int * int * int * int ]\n\nlet basic_color_to_int = function\n  | `Black -> 0 | `Red     -> 1 | `Green -> 2 | `Yellow -> 3\n  | `Blue  -> 4 | `Magenta -> 5 | `Cyan  -> 6 | `White  -> 7\n\nlet color_to_int = function\n  | `Basic (basic_color,weight) ->\n    let base = match weight with `Bold -> 8 | `Regular -> 0 in\n    base + basic_color_to_int basic_color\n  | `RGB (r,g,b) -> 16 + b + g * 6 + r * 36\n  | `Gray i -> 232 + i\n\n(* part 1 *)\nlet extended_color_to_int : extended_color -> int = function\n  | `RGBA (r,g,b,a) -> 256 + a + b * 6 + g * 36 + r * 216\n  | `Grey x -> 2000 + x\n  | (`Basic _ | `RGB _ | `Gray _) as color -> color_to_int color\n"
  },
  {
    "path": "code/variants-termcol-annotated/terminal_color.mli",
    "content": "open Core.Std\n\ntype basic_color =\n  [ `Black   | `Blue | `Cyan  | `Green\n  | `Magenta | `Red  | `White | `Yellow ]\n\ntype color =\n  [ `Basic of basic_color * [ `Bold | `Regular ]\n  | `Gray of int\n  | `RGB  of int * int * int ]\n\ntype extended_color =\n  [ color\n  | `RGBA of int * int * int * int ]\n\nval color_to_int          : color -> int\nval extended_color_to_int : extended_color -> int\n"
  },
  {
    "path": "code/variants-termcol-fixed/build.sh",
    "content": "corebuild terminal_color.native\n"
  },
  {
    "path": "code/variants-termcol-fixed/terminal_color.ml",
    "content": "open Core.Std\n\ntype basic_color =\n  [ `Black   | `Blue | `Cyan  | `Green\n  | `Magenta | `Red  | `White | `Yellow ]\n\ntype color =\n  [ `Basic of basic_color * [ `Bold | `Regular ]\n  | `Gray of int\n  | `RGB  of int * int * int ]\n\ntype extended_color =\n  [ color\n  | `RGBA of int * int * int * int ]\n\nlet basic_color_to_int = function\n  | `Black -> 0 | `Red     -> 1 | `Green -> 2 | `Yellow -> 3\n  | `Blue  -> 4 | `Magenta -> 5 | `Cyan  -> 6 | `White  -> 7\n\nlet color_to_int = function\n  | `Basic (basic_color,weight) ->\n    let base = match weight with `Bold -> 8 | `Regular -> 0 in\n    base + basic_color_to_int basic_color\n  | `RGB (r,g,b) -> 16 + b + g * 6 + r * 36\n  | `Gray i -> 232 + i\n\n(* part 1 *)\nlet extended_color_to_int : extended_color -> int = function\n  | `RGBA (r,g,b,a) -> 256 + a + b * 6 + g * 36 + r * 216\n  | #color as color -> color_to_int color\n"
  },
  {
    "path": "code/variants-termcol-fixed/terminal_color.mli",
    "content": "open Core.Std\n\ntype basic_color =\n  [ `Black   | `Blue | `Cyan  | `Green\n  | `Magenta | `Red  | `White | `Yellow ]\n\ntype color =\n  [ `Basic of basic_color * [ `Bold | `Regular ]\n  | `Gray of int\n  | `RGB  of int * int * int ]\n\ntype extended_color =\n  [ color\n  | `RGBA of int * int * int * int ]\n\nval color_to_int          : color -> int\nval extended_color_to_int : extended_color -> int\n"
  }
]