Repository: realworldocaml/examples Branch: master Commit: 32ea926861a0 Files: 597 Total size: 412.3 KB Directory structure: gitextract_jkpspzh6/ ├── .gitignore ├── INSTALL.sh ├── Makefile ├── README.md ├── UNLICENSE └── code/ ├── Makefile ├── async/ │ ├── #build_other_searches.sh# │ ├── #main.topscript# │ ├── better_echo.ml │ ├── build_echo.sh │ ├── build_other_searches.sh │ ├── echo.ml │ ├── main-35.rawscript │ ├── main-38.rawscript │ ├── main-44.rawscript │ ├── main-45.rawscript │ ├── main-46.rawscript │ ├── main-47.rawscript │ ├── main.topscript │ ├── native_code_log_delays.ml │ ├── pipe_write_break.rawscript │ ├── pipe_write_break.rawtopscript │ ├── run_echo.rawsh │ ├── run_native_code_log_delays.rawsh │ ├── run_native_code_log_delays_orig.sh │ ├── run_search.rawsh │ ├── run_search_orig.sh │ ├── run_search_with_configurable_server.rawsh │ ├── run_search_with_configurable_server_orig.errsh │ ├── run_search_with_error_handling.rawsh │ ├── run_search_with_error_handling_orig.sh │ ├── run_search_with_timeout_no_leak.rawsh │ ├── run_search_with_timeout_no_leak_orig.sh │ ├── run_thread.sh │ ├── search.ml │ ├── search_out_of_order.ml │ ├── search_with_configurable_server.ml │ ├── search_with_error_handling.ml │ ├── search_with_error_handling_deprecated.ml │ ├── search_with_timeout.ml │ ├── search_with_timeout_choice.ml │ ├── search_with_timeout_no_leak.ml │ ├── search_with_timeout_no_leak_simple.ml │ ├── search_with_timeout_simple.ml │ ├── test.txt │ ├── thread_exp_async_busy_loop.ml │ ├── thread_exp_async_busy_loop_in_thread.ml │ ├── thread_exp_async_noalloc_busy_loop.ml │ ├── thread_exp_async_noalloc_busy_loop_in_thread.ml │ ├── thread_exp_async_only.ml │ ├── thread_exp_common.ml │ ├── thread_experiments.ml │ └── timeout_search.ml ├── back-end/ │ ├── alternate_list.ml │ ├── asm_from_compare_mono.sh │ ├── cmp.S │ ├── compare_mono.ml │ ├── compare_mono.s │ ├── compare_poly.ml │ ├── compare_poly_asm.S │ ├── gdb_alternate0.rawsh │ ├── gdb_alternate1.rawsh │ ├── gdb_alternate2.rawsh │ ├── gdb_alternate3.rawsh │ ├── instr_for_pattern_monomorphic_small.sh │ ├── lambda_for_pattern_monomorphic_large.sh │ ├── lambda_for_pattern_monomorphic_small.sh │ ├── lambda_for_pattern_polymorphic.sh │ ├── opam_switch.rawsh │ ├── pattern_monomorphic_large.ml │ ├── pattern_monomorphic_small.ml │ ├── pattern_polymorphic.ml │ ├── perf_record.rawsh │ └── perf_report.rawsh ├── back-end-bench/ │ ├── bench_patterns.ml │ ├── bench_poly_and_mono.ml │ ├── run_alternate_list.sh │ ├── run_bench_patterns.sh │ └── run_bench_poly_and_mono.sh ├── back-end-embed/ │ ├── build_embed.sh │ ├── build_embed_binary.rawsh │ ├── build_embed_c.sh │ ├── build_embed_native.rawsh │ ├── embed_me1.ml │ ├── embed_me2.ml │ ├── embed_out.c │ ├── hello.ml │ ├── link_custom.rawsh │ ├── link_dllib.rawsh │ ├── main.c │ ├── run_debug_hello.sh │ ├── xbuild_embed_binary.sh │ └── xbuild_embed_native.sh ├── classes/ │ ├── Iterator.java │ ├── binary.topscript │ ├── binary_larger.ml │ ├── binary_module.ml │ ├── build_doc.sh │ ├── citerator.cpp │ ├── class_types_stack.ml │ ├── doc.ml │ ├── initializer.topscript │ ├── istack.topscript │ ├── iter.topscript │ └── stack.topscript ├── classes-async/ │ ├── build_shapes.sh │ ├── multiple_inheritance.ml │ ├── multiple_inheritance_wrong.ml │ ├── shapes.ml │ └── verbose_shapes.ml ├── command-line-parsing/ │ ├── _tags │ ├── basic.topscript │ ├── basic_md5.ml │ ├── basic_md5_as_filename.ml │ ├── basic_md5_sequence.ml │ ├── basic_md5_succinct.ml │ ├── basic_md5_with_custom_arg.ml │ ├── basic_md5_with_default_file.ml │ ├── basic_md5_with_flags.ml │ ├── basic_md5_with_opt_flags.ml │ ├── basic_md5_with_optional_file.ml │ ├── basic_md5_with_optional_file_broken.ml │ ├── build_and_run_cal_add_interactive.rawsh │ ├── build_basic_md5.sh │ ├── build_basic_md5_as_filename.sh │ ├── build_basic_md5_sequence.sh │ ├── build_basic_md5_with_custom_arg.sh │ ├── build_basic_md5_with_default_file.sh │ ├── build_basic_md5_with_flags.sh │ ├── build_basic_md5_with_opt_flags.sh │ ├── build_basic_md5_with_optional_file.sh │ ├── build_basic_md5_with_optional_file_broken.errsh │ ├── build_cal_add_days.sh │ ├── build_cal_add_sub_days.sh │ ├── build_cal_append.sh │ ├── build_cal_append_broken.errsh │ ├── cal.cmd │ ├── cal_add_days.ml │ ├── cal_add_interactive.ml │ ├── cal_add_labels.ml │ ├── cal_add_sub_days.ml │ ├── cal_append.ml │ ├── cal_append_broken.ml │ ├── cal_completion.rawsh │ ├── command_types.topscript │ ├── get_basic_md5_help.errsh │ ├── get_basic_md5_version.sh │ ├── group.topscript │ ├── md5_completion.sh │ ├── opam.rawsh │ ├── run_basic_and_default_md5.sh │ ├── run_basic_md5.sh │ ├── run_basic_md5_as_filename.errsh │ ├── run_basic_md5_flags_help.sh │ ├── run_basic_md5_with_custom_arg.errsh │ ├── run_cal_add_sub_days.sh │ ├── single_anon_filename.topscript │ └── step.topscript ├── corebuild ├── ctypes/ │ ├── ctypes.mli │ └── ctypes_impl.ml ├── error-handling/ │ ├── blow_up.ml │ ├── build_blow_up.errsh │ ├── build_blow_up_notrace.errsh │ ├── exn_cost.ml │ ├── main.topscript │ ├── result.ml │ ├── result.mli │ ├── run_exn_cost.sh │ ├── run_exn_cost_notrace.sh │ ├── sexpr.scm │ └── try_with.syntax ├── exec_script.sh ├── exec_topscript.sh ├── fcm/ │ ├── build_query_handler.sh │ ├── build_query_handler_loader.sh │ ├── fcm.syntax │ ├── loader_cli1.rawsh │ ├── loader_cli2.rawsh │ ├── loader_cli3.rawsh │ ├── loader_cli4.rawsh │ ├── main.topscript │ ├── pack.syntax │ ├── query-syntax.scm │ ├── query_example.rawscript │ ├── query_handler.ml │ ├── query_handler.topscript │ ├── query_handler_core.ml │ ├── query_handler_loader.ml │ └── unpack.syntax ├── ffi/ │ ├── build_datetime.sh │ ├── build_hello.sh │ ├── build_qsort.sh │ ├── datetime.ml │ ├── hello.ml │ ├── infer_ncurses.sh │ ├── input.txt │ ├── install.rawsh │ ├── ncurses.h │ ├── ncurses.inferred.mli │ ├── ncurses.ml │ ├── ncurses.mli │ ├── posix.topscript │ ├── posix_headers.h │ ├── qsort.h │ ├── qsort.ml │ ├── qsort.mli │ ├── qsort.topscript │ ├── qsort_typedef.h │ ├── return_c_frag.c │ ├── return_c_frag.h │ ├── return_c_uncurried.c │ ├── return_frag.ml │ └── timeval_headers.h ├── files-modules-and-programs/ │ ├── abstract_username.ml │ ├── build_session_info.errsh │ ├── common.ml │ ├── confusing_username_and_host.ml │ ├── ext_list.ml │ ├── ext_list.mli │ ├── freq.ml │ ├── intro.topscript │ ├── main.topscript │ ├── module.syntax │ ├── session_info.ml │ └── val.syntax ├── files-modules-and-programs-freq/ │ ├── freq.ml │ ├── simple_build.sh │ └── simple_build_fail.errsh ├── files-modules-and-programs-freq-cyclic1/ │ ├── build.errsh │ ├── counter.ml │ ├── counter.mli │ └── freq.ml ├── files-modules-and-programs-freq-cyclic2/ │ ├── build.errsh │ ├── counter.ml │ ├── counter.mli │ └── freq.ml ├── files-modules-and-programs-freq-fast/ │ ├── build.sh │ ├── counter.ml │ ├── counter.mli │ └── freq.ml ├── files-modules-and-programs-freq-median/ │ ├── build.sh │ ├── build_use_median.sh │ ├── counter.ml │ ├── counter.mli │ ├── freq.ml │ ├── use_median_1.ml │ └── use_median_2.ml ├── files-modules-and-programs-freq-obuild/ │ ├── build.sh │ └── test.sh ├── files-modules-and-programs-freq-with-counter/ │ ├── build.sh │ ├── counter.ml │ ├── freq.ml │ └── infer_mli.sh ├── files-modules-and-programs-freq-with-missing-def/ │ ├── build.errsh │ ├── counter.ml │ ├── counter.mli │ └── freq.ml ├── files-modules-and-programs-freq-with-sig/ │ ├── build.sh │ ├── counter.ml │ ├── counter.mli │ └── freq.ml ├── files-modules-and-programs-freq-with-sig-abstract/ │ ├── build.errsh │ ├── counter.ml │ ├── counter.mli │ └── freq.ml ├── files-modules-and-programs-freq-with-sig-abstract-fixed/ │ ├── build.sh │ ├── counter.ml │ ├── counter.mli │ └── freq.ml ├── files-modules-and-programs-freq-with-sig-mismatch/ │ ├── build.errsh │ ├── counter.ml │ ├── counter.mli │ └── freq.ml ├── files-modules-and-programs-freq-with-type-mismatch/ │ ├── build.errsh │ ├── counter.ml │ ├── counter.mli │ └── freq.ml ├── front-end/ │ ├── alice.ml │ ├── alice.mli │ ├── alice_combined.ml │ ├── broken_module.ml │ ├── broken_poly.ml │ ├── broken_poly_with_annot.ml │ ├── build_broken_module.errsh │ ├── build_broken_poly.errsh │ ├── build_broken_poly_with_annot.errsh │ ├── build_follow_on_function.errsh │ ├── build_non_principal.sh │ ├── build_ocamldoc.rawsh │ ├── build_principal.sh │ ├── build_type_conv_with_camlp4.rawsh │ ├── build_type_conv_without_camlp4.errsh │ ├── camlp4_dump.cmd │ ├── camlp4_toplevel.topscript │ ├── comparelib_test.ml │ ├── comparelib_test.mli │ ├── conflicting_interfaces.errsh │ ├── doc.ml │ ├── fixed_module.ml │ ├── follow_on_function.ml │ ├── follow_on_function_fixed.ml │ ├── html/ │ │ ├── Doc.html │ │ ├── index.html │ │ ├── index_attributes.html │ │ ├── index_class_types.html │ │ ├── index_classes.html │ │ ├── index_exceptions.html │ │ ├── index_methods.html │ │ ├── index_module_types.html │ │ ├── index_modules.html │ │ ├── index_types.html │ │ ├── index_values.html │ │ ├── style.css │ │ └── type_Doc.html │ ├── inconsistent_compilation_units.rawsh │ ├── indent_follow_on_function.sh │ ├── indent_follow_on_function_fixed.sh │ ├── infer_typedef.sh │ ├── install_ocp_index.rawsh │ ├── let_notunit.ml │ ├── let_unit.syntax │ ├── man/ │ │ └── man3/ │ │ ├── Doc.3o │ │ ├── My_exception.3o │ │ ├── Rain.3o │ │ ├── Sun.3o │ │ ├── weather.3o │ │ └── what_is_the_weather_in.3o │ ├── non_principal.ml │ ├── parsetree_typedef.sh │ ├── pipeline.ascii │ ├── principal.ml │ ├── process_comparelib_interface.sh │ ├── process_comparelib_test.sh │ ├── short_paths_1.rawsh │ ├── short_paths_2.rawsh │ ├── short_paths_3.rawsh │ ├── test.ml │ ├── test.mli │ ├── type_conv_example.ml │ ├── typedef.ml │ ├── typedef_objinfo.sh │ ├── typedtree_typedef.sh │ ├── unused_var.ml │ └── xbuild_type_conv_with_camlp4.sh ├── functors/ │ ├── build_extended_fqueue.sh │ ├── build_fqueue.sh │ ├── compare_example.ml │ ├── destructive_sub.syntax │ ├── extended_fqueue.ml │ ├── extended_fqueue.mli │ ├── foldable.ml │ ├── fqueue.ml │ ├── fqueue.mli │ ├── main-15.rawscript │ ├── main-18.rawscript │ ├── main-21.rawscript │ ├── main-25.rawscript │ ├── main.topscript │ ├── multi_sharing_constraint.syntax │ ├── sexpable.ml │ └── sharing_constraint.syntax ├── gc/ │ ├── barrier_bench.ml │ ├── finalizer.ml │ ├── minor_heap.ascii │ ├── run_barrier_bench.sh │ ├── run_finalizer.sh │ ├── show_barrier_bench_help.sh │ └── tune.topscript ├── guided-tour/ │ ├── build_sum.sh │ ├── local_let.topscript │ ├── main.topscript │ ├── recursion.ml │ ├── run_sum.sh │ ├── sum.ml │ └── sum.rawsh ├── imperative-programming/ │ ├── .gitignore │ ├── array-get.syntax │ ├── array-set.syntax │ ├── bigarray.syntax │ ├── build_all.sh │ ├── dictionary.ml │ ├── dictionary.mli │ ├── dictionary2.ml │ ├── dlist.ml │ ├── dlist.mli │ ├── edit_distance.ascii │ ├── edit_distance2.ascii │ ├── examples.topscript │ ├── fib.topscript │ ├── file.topscript │ ├── file2.topscript │ ├── for.topscript │ ├── lazy.topscript │ ├── let-unit.syntax │ ├── let_rec.ml │ ├── letrec.topscript │ ├── memo.topscript │ ├── order.topscript │ ├── printf.topscript │ ├── ref.topscript │ ├── remember_type.ml │ ├── semicolon-syntax.syntax │ ├── semicolon.syntax │ ├── string.syntax │ ├── time_converter.ml │ ├── time_converter.rawsh │ ├── time_converter2.ml │ ├── time_converter2.rawsh │ ├── value_restriction-13.rawscript │ ├── value_restriction.topscript │ └── weak.topscript ├── installation/ │ ├── arch_install.rawsh │ ├── arch_opam.rawsh │ ├── brew_install.rawsh │ ├── brew_opam_install.rawsh │ ├── debian_apt.rawsh │ ├── debian_apt_opam.rawsh │ ├── emacsrc.scm │ ├── fedora_install.rawsh │ ├── macports_install.rawsh │ ├── macports_opam_install.rawsh │ ├── ocaml_src_install.rawsh │ ├── ocaml_user_conf.rawsh │ ├── opam_eval.rawsh │ ├── opam_init.rawsh │ ├── opam_install.rawsh │ ├── opam_install_utop.rawsh │ ├── opam_list.rawsh │ ├── opam_switch.rawsh │ ├── open_core.ml │ ├── show_ocamlinit.rawsh │ └── ubuntu_opam_ppa.rawsh ├── json/ │ ├── _tags │ ├── book.json │ ├── build_github_atd.sh │ ├── build_github_org.sh │ ├── build_json.topscript │ ├── generate_github_org_json.sh │ ├── generate_github_org_types.sh │ ├── github.atd │ ├── github_j.ml │ ├── github_j.mli │ ├── github_j_excerpt.mli │ ├── github_org.atd │ ├── github_org_info.ml │ ├── github_org_j.ml │ ├── github_org_j.mli │ ├── github_org_t.ml │ ├── github_org_t.mli │ ├── github_t.ml │ ├── github_t.mli │ ├── install.topscript │ ├── install_atdgen.rawsh │ ├── list_excerpt.mli │ ├── parse_book.ml │ ├── parse_book.topscript │ ├── read_json.ml │ ├── run_github_org.sh │ ├── run_parse_book.sh │ ├── run_read_json.sh │ ├── yojson_basic.mli │ ├── yojson_basic_simple.mli │ └── yojson_safe.mli ├── lists-and-patterns/ │ ├── example.ml │ ├── example.mli │ ├── lists_layout.ascii │ └── main.topscript ├── maps-and-hash-tables/ │ ├── comparable.ml │ ├── core_phys_equal.topscript │ ├── main-22.rawscript │ ├── main-23.rawscript │ ├── main-24.rawscript │ ├── main-30.rawscript │ ├── main.topscript │ ├── map_vs_hash.ml │ ├── map_vs_hash2.ml │ ├── phys_equal.rawscript │ ├── run_map_vs_hash.sh │ └── run_map_vs_hash2.sh ├── memory-repr/ │ ├── block.ascii │ ├── custom_ops.c │ ├── float_array_layout.ascii │ ├── reprs.topscript │ ├── simple_record.topscript │ ├── string_block.ascii │ ├── string_size_calc.ascii │ └── tuple_layout.ascii ├── objects/ │ ├── IsBarbell.java │ ├── Shape.java │ ├── immutable.topscript │ ├── is_barbell.ml │ ├── narrowing.ml │ ├── polymorphism.topscript │ ├── row_polymorphism.topscript │ ├── stack.topscript │ ├── subtyping.ml │ └── subtyping.topscript ├── ocp-index/ │ └── index_ncurses.sh ├── packing/ │ ├── A.ml │ ├── B.ml │ ├── X.mlpack │ ├── _tags │ ├── build_test.sh │ ├── show_files.sh │ └── test.ml ├── parsing/ │ ├── basic_parser.mly │ ├── build_short_parser.sh │ ├── example.json │ ├── json.ml │ ├── lex.syntax │ ├── lexer.mll │ ├── lexer_int_fragment.mll │ ├── manual_token_type.ml │ ├── parsed_example.ml │ ├── parser.mly │ ├── production.syntax │ ├── prog.mli │ ├── quadratic_rule.mly │ ├── right_rec_rule.mly │ ├── short_parser.mly │ ├── tokenized_example.ml │ ├── tokens.ml │ └── yacc.syntax ├── parsing-test/ │ ├── build_json_parser.sh │ ├── build_test.sh │ ├── run_broken_test.errsh │ ├── test.ml │ ├── test1.json │ └── test2.json ├── principal/ │ └── build_principal.sh ├── records/ │ ├── functional_update.syntax │ ├── main-29.rawscript │ ├── main.topscript │ ├── record.syntax │ └── warn_help.sh ├── sexpr/ │ ├── auto_making_sexp.topscript │ ├── basic.scm │ ├── build_read_foo.errsh │ ├── build_read_foo_better_errors.errsh │ ├── build_test_interval.sh │ ├── build_test_interval_manual_sexp.sh │ ├── build_test_interval_nosexp.errsh │ ├── comment_heavy.scm │ ├── example.scm │ ├── example_broken.scm │ ├── example_load.topscript │ ├── foo_broken_example.scm │ ├── inline_sexp.topscript │ ├── int_interval.ml │ ├── int_interval.mli │ ├── int_interval_manual_sexp.ml │ ├── int_interval_manual_sexp.mli │ ├── int_interval_nosexp.ml │ ├── int_interval_nosexp.mli │ ├── list_top_packages.sh │ ├── manually_making_sexp.topscript │ ├── print_sexp.topscript │ ├── read_foo.ml │ ├── read_foo_better_errors.ml │ ├── sexp.mli │ ├── sexp_default.topscript │ ├── sexp_list.topscript │ ├── sexp_opaque.topscript │ ├── sexp_option.topscript │ ├── sexp_override.ml │ ├── sexp_printer.topscript │ ├── test_interval.ml │ ├── test_interval_manual_sexp.ml │ ├── test_interval_nosexp.ml │ └── to_from_sexp.topscript ├── variables-and-functions/ │ ├── abs_diff.mli │ ├── htable_sig1.ml │ ├── htable_sig2.ml │ ├── let.syntax │ ├── let_in.syntax │ ├── main.topscript │ ├── numerical_deriv_alt_sig.mli │ ├── operators.syntax │ ├── substring_sig1.ml │ └── substring_sig2.ml ├── variants/ │ ├── blang.topscript │ ├── catch_all.topscript │ ├── logger.topscript │ ├── main-2.rawscript │ ├── main-5.rawscript │ ├── main.topscript │ └── variant.syntax ├── variants-termcol/ │ ├── build.sh │ ├── terminal_color.ml │ └── terminal_color.mli ├── variants-termcol-annotated/ │ ├── build.errsh │ ├── terminal_color.ml │ └── terminal_color.mli └── variants-termcol-fixed/ ├── build.sh ├── terminal_color.ml └── terminal_color.mli ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ *.out *.out.full *.a a.out .*.swp *.aux *.aux *.byte *.cmo *.cmi *.cmx *.cmxa *.cma *.idx *.log *.native *.byte *.o *.omakedb.lock *.omc *.tmp *.toc *~ .*.swp .DS_Store .bzr .bzrignore .project .pydevproject .settings /commenting-build _build ================================================ FILE: INSTALL.sh ================================================ #!/bin/sh opam install -j 4 --yes \ core \ core_extended \ cryptokit \ core_bench \ atdgen \ async \ yojson \ textwrap \ cohttp \ async_graphics \ menhir \ utop \ cmdliner \ cow \ ocp-indent \ ctypes \ ocp-index echo You also need Pygments installed. echo This is python-pygments in Debian ================================================ FILE: Makefile ================================================ .PHONY: all depend clean distclean all: cd code && $(MAKE) -j1 depend: ./INSTALL.sh clean: rm -rf scripts/_build cd code && $(MAKE) clean distclean: clean cd code && $(MAKE) distclean ================================================ FILE: README.md ================================================ This repository contains all the code samples from Real World OCaml. The repository tags represent a particular release of the book. ================================================ FILE: UNLICENSE ================================================ This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to ================================================ FILE: code/Makefile ================================================ #OCAMLPARAM=_,we=+A #export OCAMLPARAM dirs= json \ command-line-parsing guided-tour \ variables-and-functions \ lists-and-patterns \ sexpr \ parsing \ parsing-test \ maps-and-hash-tables \ files-modules-and-programs \ files-modules-and-programs-freq \ files-modules-and-programs-freq-obuild \ files-modules-and-programs-freq-with-counter \ files-modules-and-programs-freq-with-sig \ files-modules-and-programs-freq-with-sig-abstract \ files-modules-and-programs-freq-with-sig-abstract-fixed \ files-modules-and-programs-freq-fast \ files-modules-and-programs-freq-median \ files-modules-and-programs-freq-with-sig-mismatch \ files-modules-and-programs-freq-with-missing-def \ files-modules-and-programs-freq-with-type-mismatch \ files-modules-and-programs-freq-cyclic1 \ files-modules-and-programs-freq-cyclic2 \ records \ variants \ variants-termcol \ variants-termcol-annotated \ variants-termcol-fixed \ objects \ classes \ classes-async \ imperative-programming \ error-handling \ memory-repr \ gc \ front-end \ packing \ principal \ back-end \ back-end-bench \ back-end-embed \ functors \ fcm \ async \ ffi \ ctypes \ ocp-index \ installation # html/xml files directory OBJ= _build # All the source files ml_src= $(wildcard $(dirs:%=%/*.ml)) mli_src= $(wildcard $(dirs:%=%/*.mli)) mll_src= $(wildcard $(dirs:%=%/*.mll)) mly_src= $(wildcard $(dirs:%=%/*.mly)) json_src= $(wildcard $(dirs:%=%/*.json)) java_src= $(wildcard $(dirs:%=%/*.java)) c_src= $(wildcard $(dirs:%=%/*.c)) h_src= $(wildcard $(dirs:%=%/*.h)) asm_src= $(wildcard $(dirs:%=%/*.S)) cmd_src= $(wildcard $(dirs:%=%/*.cmd)) cpp_src= $(wildcard $(dirs:%=%/*.cpp)) atd_src= $(wildcard $(dirs:%=%/*.atd)) scm_src= $(wildcard $(dirs:%=%/*.scm)) syn_src= $(wildcard $(dirs:%=%/*.syntax)) ascii_src= $(wildcard $(dirs:%=%/*.ascii)) scripts= $(wildcard $(dirs:%=%/*.sh)) rawscripts= $(wildcard $(dirs:%=%/*.rawsh)) errscripts= $(wildcard $(dirs:%=%/*.errsh)) topscripts= $(wildcard $(dirs:%=%/*.topscript)) rawtscripts= $(wildcard $(dirs:%=%/*.rawscript)) all_src= $(ml_src) $(mli_src) $(json_src) $(java_src) $(c_src) \ $(cmd_src) $(cpp_src) $(atd_src) $(scm_src) $(syn_src) \ $(ascii_src) $(asm_src) $(mll_src) $(mly_src) $(h_src) all_scripts= $(scripts:%.sh=%.out) $(errscripts:%.errsh=%.out) \ $(topscripts) $(rawtscripts) $(rawscripts:%.rawsh=%.out) # The source files all map to %..html and %..xml all_src_html= $(all_src:%=$(OBJ)/%.0.html) $(all_scripts:%=$(OBJ)/%.0.html) all_src_md= $(all_src:%=$(OBJ)/%.0.xml) $(all_scripts:%=$(OBJ)/%.0.xml) # Binaries we run runtop= rwo-run-toplevel highlight= rwo-syntax-highlight .PHONY: all all: $(all_src_html) $(all_src_md) @ : print-%: @echo $($*) json/run_github_org.out:: json/build_github_org.out command-line-parsing/run_basic_md5.out:: command-line-parsing/build_basic_md5.out command-line-parsing/get_basic_md5_version.out:: command-line-parsing/build_basic_md5.out command-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 command-line-parsing/run_cal_add_sub_days.out:: command-line-parsing/build_cal_add_sub_days.out command-line-parsing/md5_completion.out:: command-line-parsing/build_basic_md5_with_flags.out command-line-parsing/cal_completion.out:: command-line-parsing/build_cal_add_sub_days.out parsing-test/run_broken_test.out:: parsing-test/build_test.out $(OBJ)/%.mli.0.html $(OBJ)/%.mli.0.xml: %.mli @mkdir -p $(@D) $(highlight) -builddir $(OBJ) -cow $< || (cat $@ && rm -f $@) $(OBJ)/%.ml.0.html $(OBJ)/%.ml.0.xml: %.ml @mkdir -p $(@D) $(highlight) -builddir $(OBJ) -cow $< || (cat $@ && rm -f $@) $(OBJ)/%.mll.0.html $(OBJ)/%.mll.0.xml: %.mll @mkdir -p $(@D) $(highlight) -builddir $(OBJ) -cow $< || (cat $@ && rm -f $@) $(OBJ)/%.mly.0.html $(OBJ)/%.mly.0.xml: %.mly @mkdir -p $(@D) $(highlight) -builddir $(OBJ) -cow $< || (cat $@ && rm -f $@) $(OBJ)/%.json.0.html $(OBJ)/%.json.0.xml: %.json @mkdir -p $(@D) $(highlight) -builddir $(OBJ) -pygments json $< || (cat $@ && rm -f $@) $(OBJ)/%.syntax.0.html $(OBJ)/%.syntax.0.xml: %.syntax @mkdir -p $(@D) $(highlight) -builddir $(OBJ) -raw ocamlsyntax $< || (cat $@ && rm -f $@) $(OBJ)/%.cmd.0.html $(OBJ)/%.cmd.0.xml: %.cmd @mkdir -p $(@D) $(highlight) -builddir $(OBJ) -pygments bash $< || (cat $@ && rm -f $@) $(OBJ)/%.atd.0.html $(OBJ)/%.atd.0.xml: %.atd @mkdir -p $(@D) $(highlight) -builddir $(OBJ) -cow $< || (cat $@ && rm -f $@) $(OBJ)/%.ascii.0.html $(OBJ)/%.ascii.0.xml: %.ascii @mkdir -p $(@D) $(highlight) -builddir $(OBJ) -raw ascii $< || (cat $@ && rm -f $@) $(OBJ)/%.java.0.html $(OBJ)/%.java.0.xml: %.java @mkdir -p $(@D) $(highlight) -builddir $(OBJ) -pygments java $< || (cat $@ && rm -f $@) $(OBJ)/%.S.0.html $(OBJ)/%.S.0.xml: %.S @mkdir -p $(@D) $(highlight) -builddir $(OBJ) -pygments gas $< || (cat $@ && rm -f $@) $(OBJ)/%.c.0.html $(OBJ)/%.c.0.xml: %.c @mkdir -p $(@D) $(highlight) -builddir $(OBJ) -pygments c $< || (cat $@ && rm -f $@) $(OBJ)/%.h.0.html $(OBJ)/%.h.0.xml: %.h @mkdir -p $(@D) $(highlight) -builddir $(OBJ) -pygments c $< || (cat $@ && rm -f $@) $(OBJ)/%.cpp.0.html $(OBJ)/%.cpp.0.xml: %.cpp @mkdir -p $(@D) $(highlight) -builddir $(OBJ) -pygments cpp $< || (cat $@ && rm -f $@) $(OBJ)/%.scm.0.html $(OBJ)/%.scm.0.xml: %.scm @mkdir -p $(@D) $(highlight) -builddir $(OBJ) -pygments scheme $< || (cat $@ && rm -f $@) $(OBJ)/%.topscript.0.xml $(OBJ)/%.topscript.0.html: %.topscript @mkdir -p $(@D) cd $(*D) && $(runtop) $(*F).topscript -fullfile "$<" -builddir "../$(@D)" $(OBJ)/%.rawscript.0.xml $(OBJ)/%.rawscript.0.html: %.rawscript @mkdir -p $(@D) $(highlight) -builddir $(OBJ) -rawscript $< $(OBJ)/%.out.0.html $(OBJ)/%.out.0.xml: %.out @mkdir -p $(@D) $(highlight) -builddir $(OBJ) -console $< # The outputs of the shell scripts should be checked in. %.out.full: %.sh ./exec_script.sh $< > $@ 2>&1 || (cat $@ && rm -f $@) %.out: %.out.full egrep -v '(^ocamlfind |^\+|^menhir --|added to search path$$)' < $< > $@ %.out.full: %.errsh ! ./exec_script.sh $< > $@ 2>&1 || (cat $@ && rm -f $@) %.out: %.rawsh cp $< $@ clean: find . -name \*.out | xargs rm -f rm -rf $(OBJ) clean-%: find $* -name \*.out | xargs rm -f rm -rf $*/_build rm -rf _build/$* distclean: for i in $(dirs); do $(MAKE) clean-$$i; done .PRECIOUS: $(all_src) $(all_scripts) ================================================ FILE: code/async/#build_other_searches.sh# ================================================ corebuild -pkg cohttp.async,yojson,textwrap search_out_of_order.native ================================================ FILE: code/async/#main.topscript# ================================================ let x = 3;; #part 1 In_channel.read_all;; Out_channel.write_all "test.txt" ~data:"This is only a test.";; In_channel.read_all "test.txt";; #part 2 let x = 3;; #part 3 #require "async";; open Async.Std;; Reader.file_contents;; #part 4 let contents = Reader.file_contents "test.txt";; Deferred.peek contents;; #part 5 contents;; #part 6 Deferred.peek contents;; #part 7 Deferred.bind ;; #part 8 let uppercase_file filename = Deferred.bind (Reader.file_contents filename) (fun text -> Writer.save filename ~contents:(String.uppercase text)) ;; uppercase_file "test.txt";; Reader.file_contents "test.txt";; #part 9 let uppercase_file filename = Reader.file_contents filename >>= fun text -> Writer.save filename ~contents:(String.uppercase text) ;; #part 10 let count_lines filename = Reader.file_contents filename >>= fun text -> List.length (String.split text ~on:'\n') ;; #part 11 return;; let three = return 3;; three;; #part 12 let count_lines filename = Reader.file_contents filename >>= fun text -> return (List.length (String.split text ~on:'\n')) ;; #part 13 Deferred.map;; #part 14 let count_lines filename = Reader.file_contents filename >>| fun text -> List.length (String.split text ~on:'\n') ;; count_lines "/etc/hosts";; #part 15 let ivar = Ivar.create ();; let def = Ivar.read ivar;; Deferred.peek def;; Ivar.fill ivar "Hello";; Deferred.peek def;; #part 16 module type Delayer_intf = sig type t val create : Time.Span.t -> t val schedule : t -> (unit -> 'a Deferred.t) -> 'a Deferred.t end;; #part 17 upon;; #part 18 module Delayer : Delayer_intf = struct type t = { delay: Time.Span.t; jobs: (unit -> unit) Queue.t; } let create delay = { delay; jobs = Queue.create () } let schedule t thunk = let ivar = Ivar.create () in Queue.enqueue t.jobs (fun () -> upon (thunk ()) (fun x -> Ivar.fill ivar x)); upon (after t.delay) (fun () -> let job = Queue.dequeue_exn t.jobs in job ()); Ivar.read ivar end;; #part 19 let rec loop_forever () = loop_forever ();; let always_fail () = assert false;; #part 20 let do_stuff n = let x = 3 in if n > 0 then loop_forever (); x + n ;; #part 21 let rec loop_forever () : never_returns = loop_forever ();; #part 22 let do_stuff n = let x = 3 in if n > 0 then loop_forever (); x + n ;; #part 23 never_returns;; let do_stuff n = let x = 3 in if n > 0 then never_returns (loop_forever ()); x + n ;; #part 24 let (r,w) = Pipe.create ();; #part 25 let (r,w) = Pipe.create ();; let write_complete = Pipe.write w "Hello World!";; Pipe.read r;; write_complete;; #part 26 Pipe.transfer;; #part 27 Command.async_basic;; #part 28 #require "cohttp.async";; Cohttp_async.Client.get;; #part 29 Deferred.all;; #part 30 Deferred.all_unit;; #part 31 let maybe_raise = let should_fail = ref false in fun () -> let will_fail = !should_fail in should_fail := not will_fail; after (Time.Span.of_sec 0.5) >>= fun () -> if will_fail then raise Exit else return () ;; maybe_raise ();; maybe_raise ();; #part 32 let handle_error () = try maybe_raise () >>| fun () -> "success" with _ -> return "failure" ;; handle_error ();; handle_error ();; #part 33 let handle_error () = try_with (fun () -> maybe_raise ()) >>| function | Ok () -> "success" | Error _ -> "failure" ;; handle_error ();; handle_error ();; #part 34 let blow_up () = let monitor = Monitor.create ~name:"blow up monitor" () in within' ~monitor maybe_raise ;; blow_up ();; blow_up ();; #part 35 let swallow_error () = let monitor = Monitor.create () in Stream.iter (Monitor.errors monitor) ~f:(fun _exn -> printf "an error happened\n"); within' ~monitor (fun () -> after (Time.Span.of_sec 0.5) >>= fun () -> failwith "Kaboom!") ;; (* swallow_error ();; *) #part 36 exception Ignore_me;; let swallow_some_errors exn_to_raise = let child_monitor = Monitor.create () in let parent_monitor = Monitor.current () in Stream.iter (Monitor.errors child_monitor) ~f:(fun error -> match Monitor.extract_exn error with | Ignore_me -> printf "ignoring exn\n" | _ -> Monitor.send_exn parent_monitor error); within' ~monitor:child_monitor (fun () -> after (Time.Span.of_sec 0.5) >>= fun () -> raise exn_to_raise) ;; #part 37 swallow_some_errors Not_found;; #part 38 (* swallow_some_errors Ignore_me;; *) #part 39 let string_and_float = Deferred.both (after (sec 0.5) >>| fun () -> "A") (after (sec 0.25) >>| fun () -> 32.33);; string_and_float;; #part 40 Deferred.any [ (after (sec 0.5) >>| fun () -> "half a second") ; (after (sec 10.) >>| fun () -> "ten seconds") ] ;; #part 41 choice;; choose;; #part 42 let def = In_thread.run (fun () -> List.range 1 10);; def;; #part 43 let log_delays thunk = let start = Time.now () in let print_time () = let diff = Time.diff (Time.now ()) start in printf "%s, " (Time.Span.to_string diff) in let d = thunk () in Clock.every (sec 0.1) ~stop:d print_time; d >>| fun () -> print_time (); printf "\n" ;; #part 44 log_delays (fun () -> after (sec 1.));; #part 45 let busy_loop () = let x = ref None in for i = 1 to 100_000_000 do x := Some i done ;; log_delays ( >>| fun () -> busy_loop 100);; #part 46 log_delays (In_thread.run (fun () -> busy_loop 100));; #part 47 let noalloc_busy_loop n = let rec loop n = if n <= 0 then () else loop (n-1) in loop (n * 100_000) ;; log_delays (In_thread.run (fun () -> noalloc_busy_loop 500));; ================================================ FILE: code/async/better_echo.ml ================================================ open Core.Std open Async.Std let run ~uppercase ~port = let host_and_port = Tcp.Server.create ~on_handler_error:`Raise (Tcp.on_port port) (fun _addr r w -> Pipe.transfer (Reader.pipe r) (Writer.pipe w) ~f:(if uppercase then String.uppercase else Fn.id)) in ignore (host_and_port : (Socket.Address.Inet.t, int) Tcp.Server.t Deferred.t); Deferred.never () let () = Command.async_basic ~summary:"Start an echo server" Command.Spec.( empty +> flag "-uppercase" no_arg ~doc:" Convert to uppercase before echoing back" +> flag "-port" (optional_with_default 8765 int) ~doc:" Port to listen on (default 8765)" ) (fun uppercase port () -> run ~uppercase ~port) |> Command.run ================================================ FILE: code/async/build_echo.sh ================================================ corebuild -pkg async echo.native corebuild -pkg async better_echo.native ================================================ FILE: code/async/build_other_searches.sh ================================================ corebuild -pkg cohttp.async,yojson,textwrap search_out_of_order.native ================================================ FILE: code/async/echo.ml ================================================ open Core.Std open Async.Std (* Copy data from the reader to the writer, using the provided buffer as scratch space *) let rec copy_blocks buffer r w = Reader.read r buffer >>= function | `Eof -> return () | `Ok bytes_read -> Writer.write w buffer ~len:bytes_read; Writer.flushed w >>= fun () -> copy_blocks buffer r w (* part 1 *) (** Starts a TCP server, which listens on the specified port, invoking copy_blocks every time a client connects. *) let run () = let host_and_port = Tcp.Server.create ~on_handler_error:`Raise (Tcp.on_port 8765) (fun _addr r w -> let buffer = String.create (16 * 1024) in copy_blocks buffer r w) in ignore (host_and_port : (Socket.Address.Inet.t, int) Tcp.Server.t Deferred.t) (* part 2 *) (* Call [run], and then start the scheduler *) let () = run (); never_returns (Scheduler.go ()) ================================================ FILE: code/async/main-35.rawscript ================================================ # let swallow_error () = let monitor = Monitor.create () in Stream.iter (Monitor.errors monitor) ~f:(fun _exn -> printf "an error happened\n"); within' ~monitor (fun () -> after (Time.Span.of_sec 0.5) >>= fun () -> failwith "Kaboom!") ;; val swallow_error : unit -> 'a Deferred.t = # swallow_error ();; an error happened ================================================ FILE: code/async/main-38.rawscript ================================================ # swallow_some_errors Ignore_me;; ignoring exn ================================================ FILE: code/async/main-44.rawscript ================================================ # log_delays (fun () -> after (sec 0.5));; 0.154972ms, 102.126ms, 203.658ms, 305.73ms, 407.903ms, 501.563ms, - : unit = () ================================================ FILE: code/async/main-45.rawscript ================================================ # let busy_loop n = let x = ref None in for i = 1 to 100_000_000 do x := Some i done ;; val busy_loop : 'a -> unit = # log_delays (fun () -> return (busy_loop ()));; 19.2185s, - : unit = () ================================================ FILE: code/async/main-46.rawscript ================================================ # log_delays (fun () -> In_thread.run busy_loop);; 0.332117ms, 16.6319s, 18.8722s, - : unit = () ================================================ FILE: code/async/main-47.rawscript ================================================ # let noalloc_busy_loop () = for i = 0 to 100_000_000 do () done ;; val noalloc_busy_loop : unit -> unit = # log_delays (fun () -> In_thread.run noalloc_busy_loop);; 0.169039ms, 4.58345s, 4.77866s, 4.87957s, 12.4723s, 15.0134s, - : unit = () ================================================ FILE: code/async/main.topscript ================================================ let x = 3;; #part 1 In_channel.read_all;; Out_channel.write_all "test.txt" ~data:"This is only a test.";; In_channel.read_all "test.txt";; #part 2 let x = 3;; #part 3 #require "async";; open Async.Std;; Reader.file_contents;; #part 4 let contents = Reader.file_contents "test.txt";; Deferred.peek contents;; #part 5 contents;; #part 6 Deferred.peek contents;; #part 7 Deferred.bind ;; #part 8 let uppercase_file filename = Deferred.bind (Reader.file_contents filename) (fun text -> Writer.save filename ~contents:(String.uppercase text)) ;; uppercase_file "test.txt";; Reader.file_contents "test.txt";; #part 9 let uppercase_file filename = Reader.file_contents filename >>= fun text -> Writer.save filename ~contents:(String.uppercase text) ;; #part 10 let count_lines filename = Reader.file_contents filename >>= fun text -> List.length (String.split text ~on:'\n') ;; #part 11 return;; let three = return 3;; three;; #part 12 let count_lines filename = Reader.file_contents filename >>= fun text -> return (List.length (String.split text ~on:'\n')) ;; #part 13 Deferred.map;; #part 14 let count_lines filename = Reader.file_contents filename >>| fun text -> List.length (String.split text ~on:'\n') ;; count_lines "/etc/hosts";; #part 15 let ivar = Ivar.create ();; let def = Ivar.read ivar;; Deferred.peek def;; Ivar.fill ivar "Hello";; Deferred.peek def;; #part 16 module type Delayer_intf = sig type t val create : Time.Span.t -> t val schedule : t -> (unit -> 'a Deferred.t) -> 'a Deferred.t end;; #part 17 upon;; #part 18 module Delayer : Delayer_intf = struct type t = { delay: Time.Span.t; jobs: (unit -> unit) Queue.t; } let create delay = { delay; jobs = Queue.create () } let schedule t thunk = let ivar = Ivar.create () in Queue.enqueue t.jobs (fun () -> upon (thunk ()) (fun x -> Ivar.fill ivar x)); upon (after t.delay) (fun () -> let job = Queue.dequeue_exn t.jobs in job ()); Ivar.read ivar end;; #part 19 let rec loop_forever () = loop_forever ();; let always_fail () = assert false;; #part 20 let do_stuff n = let x = 3 in if n > 0 then loop_forever (); x + n ;; #part 21 let rec loop_forever () : never_returns = loop_forever ();; #part 22 let do_stuff n = let x = 3 in if n > 0 then loop_forever (); x + n ;; #part 23 never_returns;; let do_stuff n = let x = 3 in if n > 0 then never_returns (loop_forever ()); x + n ;; #part 24 let (r,w) = Pipe.create ();; #part 25 let (r,w) = Pipe.create ();; let write_complete = Pipe.write w "Hello World!";; Pipe.read r;; write_complete;; #part 26 Pipe.transfer;; #part 27 Command.async_basic;; #part 28 #require "cohttp.async";; Cohttp_async.Client.get;; #part 29 Deferred.all;; #part 30 Deferred.all_unit;; #part 31 let maybe_raise = let should_fail = ref false in fun () -> let will_fail = !should_fail in should_fail := not will_fail; after (Time.Span.of_sec 0.5) >>= fun () -> if will_fail then raise Exit else return () ;; maybe_raise ();; maybe_raise ();; #part 32 let handle_error () = try maybe_raise () >>| fun () -> "success" with _ -> return "failure" ;; handle_error ();; handle_error ();; #part 33 let handle_error () = try_with (fun () -> maybe_raise ()) >>| function | Ok () -> "success" | Error _ -> "failure" ;; handle_error ();; handle_error ();; #part 34 let blow_up () = let monitor = Monitor.create ~name:"blow up monitor" () in within' ~monitor maybe_raise ;; blow_up ();; blow_up ();; #part 35 let swallow_error () = let monitor = Monitor.create () in Stream.iter (Monitor.errors monitor) ~f:(fun _exn -> printf "an error happened\n"); within' ~monitor (fun () -> after (Time.Span.of_sec 0.5) >>= fun () -> failwith "Kaboom!") ;; (* swallow_error ();; *) #part 36 exception Ignore_me;; let swallow_some_errors exn_to_raise = let child_monitor = Monitor.create () in let parent_monitor = Monitor.current () in Stream.iter (Monitor.errors child_monitor) ~f:(fun error -> match Monitor.extract_exn error with | Ignore_me -> printf "ignoring exn\n" | _ -> Monitor.send_exn parent_monitor error); within' ~monitor:child_monitor (fun () -> after (Time.Span.of_sec 0.5) >>= fun () -> raise exn_to_raise) ;; #part 37 swallow_some_errors Not_found;; #part 38 (* swallow_some_errors Ignore_me;; *) #part 39 let string_and_float = Deferred.both (after (sec 0.5) >>| fun () -> "A") (after (sec 0.25) >>| fun () -> 32.33);; string_and_float;; #part 40 Deferred.any [ (after (sec 0.5) >>| fun () -> "half a second") ; (after (sec 10.) >>| fun () -> "ten seconds") ] ;; #part 41 choice;; choose;; #part 42 let def = In_thread.run (fun () -> List.range 1 10);; def;; #part 43 let log_delays thunk = let start = Time.now () in let print_time () = let diff = Time.diff (Time.now ()) start in printf "%s, " (Time.Span.to_string diff) in let d = thunk () in Clock.every (sec 0.1) ~stop:d print_time; d >>| fun () -> print_time (); printf "\n" ;; #part 44 log_delays (fun () -> after (sec 0.5));; #part 45 let busy_loop n = let x = ref None in for i = 1 to 100_000_000 do x := Some i done ;; log_delays (fun () -> return (busy_loop ()));; #part 46 log_delays (fun () -> In_thread.run busy_loop);; #part 47 let noalloc_busy_loop () = for i = 0 to 100_000_000 do () done ;; log_delays (fun () -> In_thread.run noalloc_busy_loop);; ================================================ FILE: code/async/native_code_log_delays.ml ================================================ open Core.Std open Async.Std let log_delays thunk = let start = Time.now () in let print_time () = let diff = Time.diff (Time.now ()) start in printf "%s, " (Time.Span.to_string diff) in let d = thunk () in Clock.every (sec 0.1) ~stop:d print_time; d >>| fun () -> print_time (); printf "\n" let noalloc_busyloop () = for _i = 1 to 25_000_000_000 do () done; Deferred.unit let () = Command.async_basic ~summary:"run logger without busy loop" Command.Spec.(empty) (fun () -> log_delays noalloc_busyloop) |> Command.run ================================================ FILE: code/async/pipe_write_break.rawscript ================================================ # Pipe.write w "Hello World!";; Interrupted. ================================================ FILE: code/async/pipe_write_break.rawtopscript ================================================ # Pipe.write w "Hello World!";; Interrupted. ================================================ FILE: code/async/run_echo.rawsh ================================================ $ ./echo.native & $ nc 127.0.0.1 8765 This is an echo server This is an echo server It repeats whatever I write. It repeats whatever I write. ================================================ FILE: code/async/run_native_code_log_delays.rawsh ================================================ $ corebuild -pkg async native_code_log_delays.native $ ./native_code_log_delays.native 15.5686s, $ ================================================ FILE: code/async/run_native_code_log_delays_orig.sh ================================================ corebuild -pkg async native_code_log_delays.native ./native_code_log_delays.native ================================================ FILE: code/async/run_search.rawsh ================================================ $ corebuild -pkg cohttp.async,yojson,textwrap search.native $ ./search.native "Concurrent Programming" "OCaml" Concurrent Programming ---------------------- "Concurrent computing is a form of computing in which programs are designed as collections of interacting computational processes that may be executed in parallel." OCaml ----- "OCaml, originally known as Objective Caml, is the main implementation of the Caml programming language, created by Xavier Leroy, Jérôme Vouillon, Damien Doligez, Didier Rémy and others in 1996." ================================================ FILE: code/async/run_search_orig.sh ================================================ corebuild -pkg cohttp.async,yojson,textwrap search.native ./search.native "Concurrent Programming" "OCaml" ================================================ FILE: code/async/run_search_with_configurable_server.rawsh ================================================ $ corebuild -pkg cohttp.async,yojson,textwrap \ search_with_configurable_server.native $ ./search_with_configurable_server.native \ -servers localhost,api.duckduckgo.com \ "Concurrent Programming" OCaml ("unhandled exception" ((lib/monitor.ml.Error_ ((exn (Unix.Unix_error "Connection refused" connect 127.0.0.1:80)) (backtrace ("Raised by primitive operation at file \"lib/unix_syscalls.ml\", line 797, characters 12-69" "Called from file \"lib/deferred.ml\", line 20, characters 62-65" "Called from file \"lib/scheduler.ml\", line 125, characters 6-17" "Called from file \"lib/jobs.ml\", line 65, characters 8-13" "")) (monitor (((name Tcp.close_sock_on_error) (here ()) (id 5) (has_seen_error true) (someone_is_listening true) (kill_index 0)) ((name main) (here ()) (id 1) (has_seen_error true) (someone_is_listening false) (kill_index 0)))))) (Pid 15971))) ================================================ FILE: code/async/run_search_with_configurable_server_orig.errsh ================================================ corebuild -pkg cohttp.async,yojson,textwrap search_with_configurable_server.native ./search_with_configurable_server.native -servers localhost,api.duckduckgo.com "Concurrent Programming" OCaml ================================================ FILE: code/async/run_search_with_error_handling.rawsh ================================================ $ corebuild -pkg cohttp.async,yojson,textwrap \ search_with_error_handling.native $ ./search_with_error_handling.native \ -servers localhost,api.duckduckgo.com \ "Concurrent Programming" OCaml Concurrent Programming ---------------------- DuckDuckGo query failed: Unexpected failure OCaml ----- "OCaml, originally known as Objective Caml, is the main implementation of the Caml programming language, created by Xavier Leroy, Jérôme Vouillon, Damien Doligez, Didier Rémy and others in 1996." ================================================ FILE: code/async/run_search_with_error_handling_orig.sh ================================================ corebuild -pkg cohttp.async,yojson,textwrap search_with_error_handling.native ./search_with_error_handling.native -servers localhost,api.duckduckgo.com "Concurrent Programming" OCaml ================================================ FILE: code/async/run_search_with_timeout_no_leak.rawsh ================================================ $ corebuild -pkg cohttp.async,yojson,textwrap \ search_with_timeout_no_leak.native $ ./search_with_timeout_no_leak.native \ "concurrent programming" ocaml -timeout 0.2s concurrent programming ---------------------- DuckDuckGo query failed: Timed out ocaml ----- "OCaml or Objective Caml, is the main implementation of the Caml programming language, created by Xavier Leroy, Jérôme Vouillon, Damien Doligez, Didier Rémy and others in 1996." ================================================ FILE: code/async/run_search_with_timeout_no_leak_orig.sh ================================================ corebuild -pkg cohttp.async,yojson,textwrap search_with_timeout_no_leak.native ./search_with_timeout_no_leak.native "concurrent programming" ocaml -timeout 0.2s ================================================ FILE: code/async/run_thread.sh ================================================ corebuild -pkg async thread_exp_async_only.native ./thread_exp_async_only.native ================================================ FILE: code/async/search.ml ================================================ open Core.Std open Async.Std (* Generate a DuckDuckGo search URI from a query string *) let query_uri query = let base_uri = Uri.of_string "http://api.duckduckgo.com/?format=json" in Uri.add_query_param base_uri ("q", [query]) (* part 1 *) (* Extract the "Definition" or "Abstract" field from the DuckDuckGo results *) let get_definition_from_json json = match Yojson.Safe.from_string json with | `Assoc kv_list -> let find key = begin match List.Assoc.find kv_list key with | None | Some (`String "") -> None | Some s -> Some (Yojson.Safe.to_string s) end in begin match find "Abstract" with | Some _ as x -> x | None -> find "Definition" end | _ -> None (* part 2 *) (* Execute the DuckDuckGo search *) let get_definition word = Cohttp_async.Client.get (query_uri word) >>= fun (_, body) -> Pipe.to_list (Cohttp_async.Body.to_pipe body) >>| fun strings -> (word, get_definition_from_json (String.concat strings)) (* part 3 *) (* Print out a word/definition pair *) let print_result (word,definition) = printf "%s\n%s\n\n%s\n\n" word (String.init (String.length word) ~f:(fun _ -> '-')) (match definition with | None -> "No definition found" | Some def -> String.concat ~sep:"\n" (Wrapper.wrap (Wrapper.make 70) def)) (* part 4 *) (* Run many searches in parallel, printing out the results after they're all done. *) let search_and_print words = Deferred.all (List.map words ~f:get_definition) >>| fun results -> List.iter results ~f:print_result (* part 5 *) let () = Command.async_basic ~summary:"Retrieve definitions from duckduckgo search engine" Command.Spec.( empty +> anon (sequence ("word" %: string)) ) (fun words () -> search_and_print words) |> Command.run ================================================ FILE: code/async/search_out_of_order.ml ================================================ open Core.Std open Async.Std (* Generate a DuckDuckGo search URI from a query string *) let query_uri = let base_uri = Uri.of_string "http://api.duckduckgo.com/?format=json" in fun query -> Uri.add_query_param base_uri ("q", [query]) (* Extract the "Definition" or "Abstract" field from the DuckDuckGo results *) let get_definition_from_json json = match Yojson.Safe.from_string json with | `Assoc kv_list -> let find key = begin match List.Assoc.find kv_list key with | None | Some (`String "") -> None | Some s -> Some (Yojson.Safe.to_string s) end in begin match find "Abstract" with | Some _ as x -> x | None -> find "Definition" end | _ -> None (* Execute the DuckDuckGo search *) let get_definition word = Cohttp_async.Client.get (query_uri word) >>= fun (_,body) -> Pipe.to_list body >>| fun strings -> (word, get_definition_from_json (String.concat strings)) (* Print out a word/definition pair *) let print_result (word,definition) = printf "%s\n%s\n\n%s\n\n" word (String.init (String.length word) ~f:(fun _ -> '-')) (match definition with | None -> "No definition found" | Some def -> String.concat ~sep:"\n" (Wrapper.wrap (Wrapper.make 70) def)) (* part 1 *) (* Run many searches in parallel, printing out the results as you go *) let search_and_print words = Deferred.all_unit (List.map words ~f:(fun word -> get_definition word >>| print_result)) (* part 2 *) let () = Command.async_basic ~summary:"Retrieve definitions from duckduckgo search engine" Command.Spec.( empty +> anon (sequence ("word" %: string)) ) (fun words () -> search_and_print words) |> Command.run ================================================ FILE: code/async/search_with_configurable_server.ml ================================================ open Core.Std open Async.Std (* part 1 *) (* Generate a DuckDuckGo search URI from a query string *) let query_uri ~server query = let base_uri = Uri.of_string (String.concat ["http://";server;"/?format=json"]) in Uri.add_query_param base_uri ("q", [query]) (* part 2 *) (* Extract the "Definition" or "Abstract" field from the DuckDuckGo results *) let get_definition_from_json json = match Yojson.Safe.from_string json with | `Assoc kv_list -> let find key = begin match List.Assoc.find kv_list key with | None | Some (`String "") -> None | Some s -> Some (Yojson.Safe.to_string s) end in begin match find "Abstract" with | Some _ as x -> x | None -> find "Definition" end | _ -> None (* Execute the DuckDuckGo search *) let get_definition ~server word = Cohttp_async.Client.get (query_uri ~server word) >>= fun (_, body) -> Pipe.to_list body >>| fun strings -> (word, get_definition_from_json (String.concat strings)) (* Print out a word/definition pair *) let print_result (word,definition) = printf "%s\n%s\n\n%s\n\n" word (String.init (String.length word) ~f:(fun _ -> '-')) (match definition with | None -> "No definition found" | Some def -> String.concat ~sep:"\n" (Wrapper.wrap (Wrapper.make 70) def)) (* Run many searches in parallel, printing out the results after they're all done. *) let search_and_print ~servers words = let servers = Array.of_list servers in Deferred.all (List.mapi words ~f:(fun i word -> let server = servers.(i mod Array.length servers) in get_definition ~server word)) >>| fun results -> List.iter results ~f:print_result let () = Command.async_basic ~summary:"Retrieve definitions from duckduckgo search engine" Command.Spec.( let string_list = Arg_type.create (String.split ~on:',') in empty +> anon (sequence ("word" %: string)) +> flag "-servers" (optional_with_default ["api.duckduckgo.com"] string_list) ~doc:" Specify server to connect to" ) (fun words servers () -> search_and_print ~servers words) |> Command.run ================================================ FILE: code/async/search_with_error_handling.ml ================================================ open Core.Std open Async.Std (* Generate a DuckDuckGo search URI from a query string *) let query_uri ~server query = let base_uri = Uri.of_string (String.concat ["http://";server;"/?format=json"]) in Uri.add_query_param base_uri ("q", [query]) (* Extract the "Definition" or "Abstract" field from the DuckDuckGo results *) let get_definition_from_json json = match Yojson.Safe.from_string json with | `Assoc kv_list -> let find key = begin match List.Assoc.find kv_list key with | None | Some (`String "") -> None | Some s -> Some (Yojson.Safe.to_string s) end in begin match find "Abstract" with | Some _ as x -> x | None -> find "Definition" end | _ -> None (* part 1 *) (* Execute the DuckDuckGo search *) let get_definition ~server word = try_with (fun () -> Cohttp_async.Client.get (query_uri ~server word) >>= fun (_, body) -> Pipe.to_list (Cohttp_async.Body.to_pipe body) >>| fun strings -> (word, get_definition_from_json (String.concat strings))) >>| function | Ok (word,result) -> (word, Ok result) | Error _ -> (word, Error "Unexpected failure") (* part 2 *) (* Print out a word/definition pair *) let print_result (word,definition) = printf "%s\n%s\n\n%s\n\n" word (String.init (String.length word) ~f:(fun _ -> '-')) (match definition with | Error s -> "DuckDuckGo query failed: " ^ s | Ok None -> "No definition found" | Ok (Some def) -> String.concat ~sep:"\n" (Wrapper.wrap (Wrapper.make 70) def)) (* part 3 *) (* Run many searches in parallel, printing out the results after they're all done. *) let search_and_print ~servers words = let servers = Array.of_list servers in Deferred.all (List.mapi words ~f:(fun i word -> let server = servers.(i mod Array.length servers) in get_definition ~server word)) >>| fun results -> List.iter results ~f:print_result let () = Command.async_basic ~summary:"Retrieve definitions from duckduckgo search engine" Command.Spec.( let string_list = Arg_type.create (String.split ~on:',') in empty +> anon (sequence ("word" %: string)) +> flag "-servers" (optional_with_default ["api.duckduckgo.com"] string_list) ~doc:" Specify server to connect to" ) (fun words servers () -> search_and_print ~servers words) |> Command.run ================================================ FILE: code/async/search_with_error_handling_deprecated.ml ================================================ open Core.Std open Async.Std (* Generate a DuckDuckGo search URI from a query string *) let query_uri ~server query = let base_uri = Uri.of_string (String.concat ["http://";server;"/?format=json"]) in Uri.add_query_param base_uri ("q", [query]) (* Extract the "Definition" or "Abstract" field from the DuckDuckGo results *) let get_definition_from_json json = match Yojson.Safe.from_string json with | `Assoc kv_list -> let find key = begin match List.Assoc.find kv_list key with | None | Some (`String "") -> None | Some s -> Some (Yojson.Safe.to_string s) end in begin match find "Abstract" with | Some _ as x -> x | None -> find "Definition" end | _ -> None (* Execute the DuckDuckGo search *) let get_definition ~server word = try_with (fun () -> Cohttp_async.Client.get (query_uri ~server word) >>= fun (_, body) -> Pipe.to_list body >>| fun strings -> (word, get_definition_from_json (String.concat strings))) >>| function | Ok (word,result) -> (word, Ok result) | Error exn -> (word, Error exn) (* Print out a word/definition pair *) let print_result (word,definition) = printf "%s\n%s\n\n%s\n\n" word (String.init (String.length word) ~f:(fun _ -> '-')) (match definition with | Error _ -> "DuckDuckGo query failed unexpectedly" | Ok None -> "No definition found" | Ok (Some def) -> String.concat ~sep:"\n" (Wrapper.wrap (Wrapper.make 70) def)) (* Run many searches in parallel, printing out the results after they're all done. *) let search_and_print ~server words = Deferred.all (List.map ~f:(get_definition ~server) words) >>| fun results -> List.iter results ~f:print_result let () = Command.async_basic ~summary:"Retrieve definitions from duckduckgo search engine" Command.Spec.( empty +> anon (sequence ("word" %: string)) +> flag "-server" (optional_with_default "api.duckduckgo.com" string) ~doc:" Specify server to connect to" ) (fun words server () -> search_and_print ~server words) |> Command.run ================================================ FILE: code/async/search_with_timeout.ml ================================================ open Core.Std open Async.Std (* Generate a DuckDuckGo search URI from a query string *) let query_uri ~server query = let base_uri = Uri.of_string (String.concat ["http://";server;"/?format=json"]) in Uri.add_query_param base_uri ("q", [query]) (* Extract the "Definition" or "Abstract" field from the DuckDuckGo results *) let get_definition_from_json json = match Yojson.Safe.from_string json with | `Assoc kv_list -> let find key = begin match List.Assoc.find kv_list key with | None | Some (`String "") -> None | Some s -> Some (Yojson.Safe.to_string s) end in begin match find "Abstract" with | Some _ as x -> x | None -> find "Definition" end | _ -> None (* Execute the DuckDuckGo search *) let get_definition ~server word = try_with (fun () -> Cohttp_async.Client.get (query_uri ~server word) >>= fun (_, body) -> Pipe.to_list body >>| fun strings -> (word, get_definition_from_json (String.concat strings))) >>| function | Ok (word,result) -> (word, Ok result) | Error exn -> (word, Error exn) (* part 1 *) let get_definition_with_timeout ~server ~timeout word = Deferred.any [ (after timeout >>| fun () -> (word,Error "Timed out")) ; (get_definition ~server word >>| fun (word,result) -> let result' = match result with | Ok _ as x -> x | Error _ -> Error "Unexpected failure" in (word,result') ) ] (* part 2 *) (* Print out a word/definition pair *) let print_result (word,definition) = printf "%s\n%s\n\n%s\n\n" word (String.init (String.length word) ~f:(fun _ -> '-')) (match definition with | Error s -> "DuckDuckGo query failed: " ^ s | Ok None -> "No definition found" | Ok (Some def) -> String.concat ~sep:"\n" (Wrapper.wrap (Wrapper.make 70) def)) (* Run many searches in parallel, printing out the results after they're all done. *) let search_and_print ~servers ~timeout words = let servers = Array.of_list servers in Deferred.all (List.mapi words ~f:(fun i word -> let server = servers.(i mod Array.length servers) in get_definition_with_timeout ~server ~timeout word)) >>| fun results -> List.iter results ~f:print_result let () = Command.async_basic ~summary:"Retrieve definitions from duckduckgo search engine" Command.Spec.( let string_list = Arg_type.create (String.split ~on:',') in empty +> anon (sequence ("word" %: string)) +> flag "-servers" (optional_with_default ["api.duckduckgo.com"] string_list) ~doc:" Specify server to connect to" +> flag "-timeout" (optional_with_default (sec 5.) time_span) ~doc:" Abandon queries that take longer than this time" ) (fun words servers timeout () -> search_and_print ~servers ~timeout words) |> Command.run ================================================ FILE: code/async/search_with_timeout_choice.ml ================================================ open Core.Std open Async.Std (* Generate a DuckDuckGo search URI from a query string *) let query_uri ~server query = let base_uri = Uri.of_string (String.concat ["http://";server;"/?format=json"]) in Uri.add_query_param base_uri ("q", [query]) (* Extract the "Definition" or "Abstract" field from the DuckDuckGo results *) let get_definition_from_json json = match Yojson.Safe.from_string json with | `Assoc kv_list -> let find key = begin match List.Assoc.find kv_list key with | None | Some (`String "") -> None | Some s -> Some (Yojson.Safe.to_string s) end in begin match find "Abstract" with | Some _ as x -> x | None -> find "Definition" end | _ -> None (* Execute the DuckDuckGo search *) let get_definition ~server ~interrupt word = try_with (fun () -> Cohttp_async.Client.get ~interrupt (query_uri ~server word) >>= fun (_, body) -> Pipe.to_list body >>| fun strings -> (word, get_definition_from_json (String.concat strings))) >>| function | Ok (word,result) -> (word, Ok result) | Error exn -> (word, Error exn) let get_definition_with_timeout ~server ~timeout word = let interrupt = Ivar.create () in choose [ choice (after timeout) (fun () -> Ivar.fill interrupt (); (word,Error "Timed out")) ; choice (get_definition ~server ~interrupt:(Ivar.read interrupt) word) (fun (word,result) -> let result' = match result with | Ok _ as x -> x | Error _ -> Error "Unexpected failure" in (word,result') ) ] (* Print out a word/definition pair *) let print_result (word,definition) = printf "%s\n%s\n\n%s\n\n" word (String.init (String.length word) ~f:(fun _ -> '-')) (match definition with | Error _ -> "DuckDuckGo query failed unexpectedly" | Ok None -> "No definition found" | Ok (Some def) -> String.concat ~sep:"\n" (Wrapper.wrap (Wrapper.make 70) def)) (* Run many searches in parallel, printing out the results after they're all done. *) let search_and_print ~servers ~timeout words = let servers = Array.of_list servers in Deferred.all (List.mapi words ~f:(fun i word -> let server = servers.(i mod Array.length servers) in get_definition_with_timeout ~server ~timeout word)) >>| fun results -> List.iter results ~f:print_result let () = Command.async_basic ~summary:"Retrieve definitions from duckduckgo search engine" Command.Spec.( let string_list = Arg_type.create (String.split ~on:',') in empty +> anon (sequence ("word" %: string)) +> flag "-servers" (optional_with_default ["api.duckduckgo.com"] string_list) ~doc:" Specify server to connect to" +> flag "-timeout" (optional_with_default (sec 5.) time_span) ~doc:" Abandon queries that take longer than this time" ) (fun words servers timeout () -> search_and_print ~servers ~timeout words) |> Command.run ================================================ FILE: code/async/search_with_timeout_no_leak.ml ================================================ open Core.Std open Async.Std (* Generate a DuckDuckGo search URI from a query string *) let query_uri ~server query = let base_uri = Uri.of_string (String.concat ["http://";server;"/?format=json"]) in Uri.add_query_param base_uri ("q", [query]) (* Extract the "Definition" or "Abstract" field from the DuckDuckGo results *) let get_definition_from_json json = match Yojson.Safe.from_string json with | `Assoc kv_list -> let find key = begin match List.Assoc.find kv_list key with | None | Some (`String "") -> None | Some s -> Some (Yojson.Safe.to_string s) end in begin match find "Abstract" with | Some _ as x -> x | None -> find "Definition" end | _ -> None (* part 1 *) (* Execute the DuckDuckGo search *) let get_definition ~server ~interrupt word = try_with (fun () -> Cohttp_async.Client.get ~interrupt (query_uri ~server word) >>= fun (_, body) -> Pipe.to_list (Cohttp_async.Body.to_pipe body) >>| fun strings -> (word, get_definition_from_json (String.concat strings))) >>| function | Ok (word,result) -> (word, Ok result) | Error exn -> (word, Error exn) (* part 2 *) let get_definition_with_timeout ~server ~timeout word = let interrupt = Ivar.create () in choose [ choice (after timeout) (fun () -> Ivar.fill interrupt (); (word,Error "Timed out")) ; choice (get_definition ~server ~interrupt:(Ivar.read interrupt) word) (fun (word,result) -> let result' = match result with | Ok _ as x -> x | Error _ -> Error "Unexpected failure" in (word,result') ) ] (* part 3 *) (* Print out a word/definition pair *) let print_result (word,definition) = printf "%s\n%s\n\n%s\n\n" word (String.init (String.length word) ~f:(fun _ -> '-')) (match definition with | Error s -> "DuckDuckGo query failed: " ^ s | Ok None -> "No definition found" | Ok (Some def) -> String.concat ~sep:"\n" (Wrapper.wrap (Wrapper.make 70) def)) (* Run many searches in parallel, printing out the results after they're all done. *) let search_and_print ~servers ~timeout words = let servers = Array.of_list servers in Deferred.all (List.mapi words ~f:(fun i word -> let server = servers.(i mod Array.length servers) in get_definition_with_timeout ~server ~timeout word)) >>| fun results -> List.iter results ~f:print_result let () = Command.async_basic ~summary:"Retrieve definitions from duckduckgo search engine" Command.Spec.( let string_list = Arg_type.create (String.split ~on:',') in empty +> anon (sequence ("word" %: string)) +> flag "-servers" (optional_with_default ["api.duckduckgo.com"] string_list) ~doc:" Specify server to connect to" +> flag "-timeout" (optional_with_default (sec 5.) time_span) ~doc:" Abandon queries that take longer than this time" ) (fun words servers timeout () -> search_and_print ~servers ~timeout words) |> Command.run ================================================ FILE: code/async/search_with_timeout_no_leak_simple.ml ================================================ open Core.Std open Async.Std (* Generate a DuckDuckGo search URI from a query string *) let query_uri ~server query = let base_uri = Uri.of_string (String.concat ["http://";server;"/?format=json"]) in Uri.add_query_param base_uri ("q", [query]) (* Extract the "Definition" or "Abstract" field from the DuckDuckGo results *) let get_definition_from_json json = match Yojson.Safe.from_string json with | `Assoc kv_list -> let find key = begin match List.Assoc.find kv_list key with | None | Some (`String "") -> None | Some s -> Some (Yojson.Safe.to_string s) end in begin match find "Abstract" with | Some _ as x -> x | None -> find "Definition" end | _ -> None (* part 1 *) (* Execute the DuckDuckGo search *) let get_definition ~server ~interrupt word = try_with (fun () -> Cohttp_async.Client.get ~interrupt (query_uri ~server word) >>= fun (_, body) -> Pipe.to_list body >>| fun strings -> (word, get_definition_from_json (String.concat strings))) >>| function | Ok (word,result) -> (word, Ok result) | Error exn -> (word, Error exn) (* part 2 *) let get_definition_with_timeout ~server ~timeout word = get_definition ~server ~interrupt:(after timeout) word >>| fun (word,result) -> let result' = match result with | Ok _ as x -> x | Error _ -> Error "Unexpected failure" in (word,result') (* part 3 *) (* Print out a word/definition pair *) let print_result (word,definition) = printf "%s\n%s\n\n%s\n\n" word (String.init (String.length word) ~f:(fun _ -> '-')) (match definition with | Error _ -> "DuckDuckGo query failed unexpectedly" | Ok None -> "No definition found" | Ok (Some def) -> String.concat ~sep:"\n" (Wrapper.wrap (Wrapper.make 70) def)) (* Run many searches in parallel, printing out the results after they're all done. *) let search_and_print ~servers ~timeout words = let servers = Array.of_list servers in Deferred.all (List.mapi words ~f:(fun i word -> let server = servers.(i mod Array.length servers) in get_definition_with_timeout ~server ~timeout word)) >>| fun results -> List.iter results ~f:print_result let () = Command.async_basic ~summary:"Retrieve definitions from duckduckgo search engine" Command.Spec.( let string_list = Arg_type.create (String.split ~on:',') in empty +> anon (sequence ("word" %: string)) +> flag "-servers" (optional_with_default ["api.duckduckgo.com"] string_list) ~doc:" Specify server to connect to" +> flag "-timeout" (optional_with_default (sec 5.) time_span) ~doc:" Abandon queries that take longer than this time" ) (fun words servers timeout () -> search_and_print ~servers ~timeout words) |> Command.run ================================================ FILE: code/async/search_with_timeout_simple.ml ================================================ open Core.Std open Async.Std (* Generate a DuckDuckGo search URI from a query string *) let query_uri ~server query = let base_uri = Uri.of_string (String.concat ["http://";server;"/?format=json"]) in Uri.add_query_param base_uri ("q", [query]) (* Extract the "Definition" or "Abstract" field from the DuckDuckGo results *) let get_definition_from_json json = match Yojson.Safe.from_string json with | `Assoc kv_list -> let find key = begin match List.Assoc.find kv_list key with | None | Some (`String "") -> None | Some s -> Some (Yojson.Safe.to_string s) end in begin match find "Abstract" with | Some _ as x -> x | None -> find "Definition" end | _ -> None (* Execute the DuckDuckGo search *) let get_definition ~server word = try_with (fun () -> Cohttp_async.Client.get (query_uri ~server word) >>= fun (_, body) -> Pipe.to_list body >>| fun strings -> (word, get_definition_from_json (String.concat strings))) >>| function | Ok (word,result) -> (word, Ok result) | Error exn -> (word, Error exn) let get_definition_with_timeout ~server ~timeout word = choose [ choice (after timeout) (fun () -> (word,Error "Timed out")) ; choice (get_definition ~server word) (fun (word,result) -> let result' = match result with | Ok x -> Ok x | Error _ -> Error "Unexpected failure" in (word,result') ) ] (* Print out a word/definition pair *) let print_result (word,definition) = printf "%s\n%s\n\n%s\n\n" word (String.init (String.length word) ~f:(fun _ -> '-')) (match definition with | Error msg -> "ERROR: " ^ msg | Ok None -> "No definition found" | Ok (Some def) -> String.concat ~sep:"\n" (Wrapper.wrap (Wrapper.make 70) def)) (* Run many searches in parallel, printing out the results after they're all done. *) let search_and_print ~server ~timeout words = Deferred.all (List.map words ~f:(get_definition_with_timeout ~timeout ~server)) >>| fun results -> List.iter results ~f:print_result let () = Command.async_basic ~summary:"Retrieve definitions from duckduckgo search engine" Command.Spec.( empty +> anon (sequence ("word" %: string)) +> flag "-server" (optional_with_default "api.duckduckgo.com" string) ~doc:" Specify server to connect to" +> flag "-timeout" (optional_with_default (sec 5.) time_span) ~doc:" Abandon queries that take longer than this time" ) (fun words server timeout () -> search_and_print ~server ~timeout words) |> Command.run ================================================ FILE: code/async/test.txt ================================================ This is only a test. ================================================ FILE: code/async/thread_exp_async_busy_loop.ml ================================================ open Core.Std open Async.Std open Thread_exp_common (* part 1 *) let busy_loop n = let x = ref None in for i = 1 to 100_000_000 do x := Some i done let () = don't_wait_for (log_delays (Deferred.unit >>= busy_loop)) (* part 2 *) let () = finish () ================================================ FILE: code/async/thread_exp_async_busy_loop_in_thread.ml ================================================ open Core.Std open Async.Std open Thread_exp_common (* part 1 *) let busy_loop n = let x = ref None in for i = 1 to 100_000_000 do x := Some i done let () = don't_wait_for (log_delays (In_thread.run busy_loop)) (* part 2 *) let () = finish () ================================================ FILE: code/async/thread_exp_async_noalloc_busy_loop.ml ================================================ open Core.Std open Async.Std open Thread_exp_common (* part 1 *) let busy_loop () = for i = 1 to 200_000_000 do () done let () = don't_wait_for (log_delays (In_thread.run busy_loop)) (* part 2 *) let () = finish () ================================================ FILE: code/async/thread_exp_async_noalloc_busy_loop_in_thread.ml ================================================ open Core.Std open Async.Std open Thread_exp_common (* part 1 *) let busy_loop () = for i = 1 to 200_000_000 do () done let () = don't_wait_for (log_delays (In_thread.run busy_loop)) (* part 2 *) let () = finish () ================================================ FILE: code/async/thread_exp_async_only.ml ================================================ open Core.Std open Async.Std open Thread_exp_common let () = Command.async_basic ~summary:"run logger without busy loop" Command.Spec.(empty) (fun () -> log_delays (after (sec 1.)) ) |> Command.run ================================================ FILE: code/async/thread_exp_common.ml ================================================ open Core.Std open Async.Std let log_delays d = let start = Time.now () in let rec loop stamps = let delay = Time.diff (Time.now ()) start in match Deferred.peek d with | Some () -> return (delay :: stamps) | None -> after (sec 0.1) >>= fun () -> loop (delay :: stamps) in loop [] >>| fun delays -> let sexp = <:sexp_of> (List.rev delays) in printf "%s\n" (Sexp.to_string sexp) let finish () = shutdown 0; never_returns (Scheduler.go ()) ================================================ FILE: code/async/thread_experiments.ml ================================================ open Core.Std open Async.Std let log_delays thunk = let start = Time.now () in let print_time () = let diff = Time.diff (Time.now ()) start in Caml.Printf.printf ".%!"; printf "%s, " (Time.Span.to_string diff) in let d = thunk () in Clock.every (sec 0.1) ~stop:d print_time; d >>| fun () -> print_time (); printf "\n" type how_to_wait = | After | Busyloop | Busyloop_in_thread | Noalloc_busyloop_in_thread | Noalloc_busyloop_in_thread_2 with sexp let busyloop () = let x = ref None in for i = 1 to 50_000_000 do x := Some i done let noalloc_busyloop () = for _i = 1 to 50_000_000 do () done let noalloc_busyloop_2 () = let rec loop i = if i = 0 then () else loop (i-1) in loop 50_000_000 let wait_and_log how_to_wait = let until = match how_to_wait with | After -> (fun () -> after (sec 1.)) | Busyloop -> (fun () -> busyloop (); return ()) | Busyloop_in_thread -> (fun () -> In_thread.run busyloop) | Noalloc_busyloop_in_thread -> (fun () -> In_thread.run noalloc_busyloop) | Noalloc_busyloop_in_thread_2 -> (fun () -> In_thread.run noalloc_busyloop_2) in log_delays until let how_to_wait = Command.Spec.Arg_type.create (fun s -> Sexp.of_string s |> how_to_wait_of_sexp) let () = Command.async_basic ~summary:"run logger without busy loop" Command.Spec.( empty +> anon ("how-to-wait" %: how_to_wait) ) (fun how () -> wait_and_log how) |> Command.run ================================================ FILE: code/async/timeout_search.ml ================================================ open Core.Std open Async.Std module Cohttp = Cohttp_async (* Generate a DuckDuckGo search URI from a query string *) let query_uri = let base_uri = Uri.of_string "http://api.duckduckgo.com/?format=json" in fun query -> Uri.add_query_param base_uri ("q", [query]) (* Extract the "Definition" field from the DuckDuckGo results *) let get_definition_from_json json = match Yojson.Safe.from_string json with | `Assoc kv_list -> begin match List.Assoc.find kv_list "Definition" with | None | Some (`String "") -> Or_error.error_string "No definition found" | Some s -> Ok (Yojson.Safe.to_string s) end | _ -> Or_error.error_string "malformed reply" (* Execute the DuckDuckGo search *) let get_definition ~timeout word = let get = Cohttp.Client.call `GET (query_uri word) >>= fun (_, body) -> Pipe.to_list body >>| fun strings -> get_definition_from_json (String.concat strings) in match timeout with | None -> get | Some timeout -> let timeout = Clock.after timeout in choose [ choice get Fn.id ; choice timeout (fun () -> Or_error.error_string "timed out") ] (* Run a single search and print out the results *) let run_one_search ~timeout search_string = get_definition ~timeout search_string >>| fun result -> printf "%-10s : %s\n" search_string (match result with | Ok x -> x | Error err -> "{" ^ Error.to_string_hum err ^ "}") (* Run many searches in parallel, printing out the results as you go *) let run_many_searches ~parallel ~timeout search_strings = Deferred.List.iter search_strings ~f:(run_one_search ~timeout) ~how:(if parallel then `Parallel else `Sequential) let () = Command.async_basic ~summary:"Retrieve definitions from duckduckgo search engine" Command.Spec.( empty +> flag "-timeout" (optional time_span) ~doc:" Whether to run queries in parallel" +> flag "-parallel" no_arg ~doc:" Run queries in parallel" +> anon (sequence ("search term" %: string)) ) (fun timeout parallel search_strings () -> run_many_searches ~parallel ~timeout search_strings) |> Command.run ================================================ FILE: code/back-end/alternate_list.ml ================================================ open Core.Std let rec take = function |[] -> [] |hd::tl -> hd :: (skip tl) and skip = function |[] -> [] |_::tl -> take tl let () = take [1;2;3;4;5;6;7;8;9] |> List.map ~f:string_of_int |> String.concat ~sep:"," |> print_endline ================================================ FILE: code/back-end/asm_from_compare_mono.sh ================================================ ocamlopt -inline 20 -nodynlink -S compare_mono.ml ================================================ FILE: code/back-end/cmp.S ================================================ _camlCompare_mono__cmp_1008: .cfi_startproc .L101: cmpq %rbx, %rax jle .L100 ret .align 2 .L100: movq %rbx, %rax ret .cfi_endproc ================================================ FILE: code/back-end/compare_mono.ml ================================================ let cmp (a:int) (b:int) = if a > b then a else b ================================================ FILE: code/back-end/compare_mono.s ================================================ .data .globl _camlCompare_mono__data_begin _camlCompare_mono__data_begin: .text .globl _camlCompare_mono__code_begin _camlCompare_mono__code_begin: nop .data .quad 1024 .globl _camlCompare_mono _camlCompare_mono: .space 8 .data .quad 3319 _camlCompare_mono__1: .quad _caml_curry2 .quad 5 .quad _camlCompare_mono__cmp_1008 .text .align 4 .globl _camlCompare_mono__cmp_1008 _camlCompare_mono__cmp_1008: .cfi_startproc .L101: cmpq %rbx, %rax jle .L100 ret .align 2 .L100: movq %rbx, %rax ret .cfi_endproc .text .align 4 .globl _camlCompare_mono__entry _camlCompare_mono__entry: .cfi_startproc .L102: leaq _camlCompare_mono__1(%rip), %rax movq %rax, _camlCompare_mono(%rip) movq $1, %rax ret .cfi_endproc .data .text nop .globl _camlCompare_mono__code_end _camlCompare_mono__code_end: .data .globl _camlCompare_mono__data_end _camlCompare_mono__data_end: .long 0 .globl _camlCompare_mono__frametable _camlCompare_mono__frametable: .quad 0 ================================================ FILE: code/back-end/compare_poly.ml ================================================ let cmp a b = if a > b then a else b ================================================ FILE: code/back-end/compare_poly_asm.S ================================================ _camlCompare_poly__cmp_1008: .cfi_startproc subq $24, %rsp .cfi_adjust_cfa_offset 24 .L101: movq %rax, 8(%rsp) movq %rbx, 0(%rsp) movq %rax, %rdi movq %rbx, %rsi leaq _caml_greaterthan(%rip), %rax call _caml_c_call .L102: leaq _caml_young_ptr(%rip), %r11 movq (%r11), %r15 cmpq $1, %rax je .L100 movq 8(%rsp), %rax addq $24, %rsp .cfi_adjust_cfa_offset -24 ret .cfi_adjust_cfa_offset 24 .align 2 .L100: movq 0(%rsp), %rax addq $24, %rsp .cfi_adjust_cfa_offset -24 ret .cfi_adjust_cfa_offset 24 .cfi_endproc ================================================ FILE: code/back-end/gdb_alternate0.rawsh ================================================ $ gdb ./alternate_list.native GNU gdb (GDB) 7.4.1-debian Copyright (C) 2012 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". For bug reporting instructions, please see: ... Reading symbols from /home/avsm/alternate_list.native...done. (gdb) ================================================ FILE: code/back-end/gdb_alternate1.rawsh ================================================ (gdb) break camlAlternate_list__take_69242 Breakpoint 1 at 0x5658d0: file alternate_list.ml, line 5. ================================================ FILE: code/back-end/gdb_alternate2.rawsh ================================================ (gdb) run Starting program: /home/avsm/alternate_list.native [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". Breakpoint 1, camlAlternate_list__take_69242 () at alternate_list.ml:5 4 function ================================================ FILE: code/back-end/gdb_alternate3.rawsh ================================================ (gdb) cont Continuing. Breakpoint 1, camlAlternate_list__take_69242 () at alternate_list.ml:5 4 function (gdb) cont Continuing. Breakpoint 1, camlAlternate_list__take_69242 () at alternate_list.ml:5 4 function (gdb) bt #0 camlAlternate_list__take_69242 () at alternate_list.ml:4 #1 0x00000000005658e7 in camlAlternate_list__take_69242 () at alternate_list.ml:6 #2 0x00000000005658e7 in camlAlternate_list__take_69242 () at alternate_list.ml:6 #3 0x00000000005659f7 in camlAlternate_list__entry () at alternate_list.ml:14 #4 0x0000000000560029 in caml_program () #5 0x000000000080984a in caml_start_program () #6 0x00000000008099a0 in ?? () #7 0x0000000000000000 in ?? () (gdb) clear camlAlternate_list__take_69242 Deleted breakpoint 1 (gdb) cont Continuing. 1,3,5,7,9 [Inferior 1 (process 3546) exited normally] ================================================ FILE: code/back-end/instr_for_pattern_monomorphic_small.sh ================================================ ocamlc -dinstr pattern_monomorphic_small.ml 2>&1 ================================================ FILE: code/back-end/lambda_for_pattern_monomorphic_large.sh ================================================ ocamlc -dlambda -c pattern_monomorphic_large.ml 2>&1 ================================================ FILE: code/back-end/lambda_for_pattern_monomorphic_small.sh ================================================ ocamlc -dlambda -c pattern_monomorphic_small.ml 2>&1 ================================================ FILE: code/back-end/lambda_for_pattern_polymorphic.sh ================================================ ocamlc -dlambda -c pattern_polymorphic.ml 2>&1 ================================================ FILE: code/back-end/opam_switch.rawsh ================================================ $ opam switch 4.01.0dev+fp ================================================ FILE: code/back-end/pattern_monomorphic_large.ml ================================================ type t = | Alice | Bob | Charlie | David let test v = match v with | Alice -> 100 | Bob -> 101 | Charlie -> 102 | David -> 103 ================================================ FILE: code/back-end/pattern_monomorphic_small.ml ================================================ type t = | Alice | Bob let test v = match v with | Alice -> 100 | Bob -> 101 ================================================ FILE: code/back-end/pattern_polymorphic.ml ================================================ let test v = match v with | `Alice -> 100 | `Bob -> 101 | `Charlie -> 102 | `David -> 103 | `Eve -> 104 ================================================ FILE: code/back-end/perf_record.rawsh ================================================ $ perf record -g ./barrier_bench.native Estimated testing time 20s (change using -quota SECS). Name Time (ns) Time 95ci Percentage ---- --------- --------- ---------- mutable 7_306_219 7_250_234-7_372_469 96.83 immutable 7_545_126 7_537_837-7_551_193 100.00 [ perf record: Woken up 11 times to write data ] [ perf record: Captured and wrote 2.722 MB perf.data (~118926 samples) ] perf record -g ./barrier.native Estimated testing time 20s (change using -quota SECS). Name Time (ns) Time 95ci Percentage ---- --------- --------- ---------- mutable 7_306_219 7_250_234-7_372_469 96.83 immutable 7_545_126 7_537_837-7_551_193 100.00 [ perf record: Woken up 11 times to write data ] [ perf record: Captured and wrote 2.722 MB perf.data (~118926 samples) ] ================================================ FILE: code/back-end/perf_report.rawsh ================================================ $ perf report -g + 48.86% barrier.native barrier.native [.] camlBarrier__test_immutable_69282 + 30.22% barrier.native barrier.native [.] camlBarrier__test_mutable_69279 + 20.22% barrier.native barrier.native [.] caml_modify ================================================ FILE: code/back-end-bench/bench_patterns.ml ================================================ open Core.Std open Core_bench.Std type t = | Alice | Bob type s = | A | B | C | D | E let polymorphic_pattern () = let test v = match v with | `Alice -> 100 | `Bob -> 101 | `Charlie -> 102 | `David -> 103 | `Eve -> 104 in List.iter ~f:(fun v -> ignore(test v)) [`Alice; `Bob; `Charlie; `David] let monomorphic_pattern_small () = let test v = match v with | Alice -> 100 | Bob -> 101 in List.iter ~f:(fun v -> ignore(test v)) [ Alice; Bob ] let monomorphic_pattern_large () = let test v = match v with | A -> 100 | B -> 101 | C -> 102 | D -> 103 | E -> 104 in List.iter ~f:(fun v -> ignore(test v)) [ A; B; C; D ] let tests = [ "Polymorphic pattern", polymorphic_pattern; "Monomorphic larger pattern", monomorphic_pattern_large; "Monomorphic small pattern", monomorphic_pattern_small; ] let () = List.map tests ~f:(fun (name,test) -> Bench.Test.create ~name test) |> Bench.make_command |> Command.run ================================================ FILE: code/back-end-bench/bench_poly_and_mono.ml ================================================ open Core.Std open Core_bench.Std let polymorphic_compare () = let cmp a b = if a > b then a else b in for i = 0 to 1000 do ignore(cmp 0 i) done let monomorphic_compare () = let cmp (a:int) (b:int) = if a > b then a else b in for i = 0 to 1000 do ignore(cmp 0 i) done let tests = [ "Polymorphic comparison", polymorphic_compare; "Monomorphic comparison", monomorphic_compare ] let () = List.map tests ~f:(fun (name,test) -> Bench.Test.create ~name test) |> Bench.make_command |> Command.run ================================================ FILE: code/back-end-bench/run_alternate_list.sh ================================================ corebuild -tag debug alternate_list.native ./alternate_list.native -ascii ================================================ FILE: code/back-end-bench/run_bench_patterns.sh ================================================ corebuild -pkg core_bench bench_patterns.native ./bench_patterns.native -ascii ================================================ FILE: code/back-end-bench/run_bench_poly_and_mono.sh ================================================ corebuild -pkg core_bench bench_poly_and_mono.native ./bench_poly_and_mono.native -ascii ================================================ FILE: code/back-end-embed/build_embed.sh ================================================ rm -f embed_out.c ocamlc -output-obj -o embed_out.o embed_me1.ml embed_me2.ml ================================================ FILE: code/back-end-embed/build_embed_binary.rawsh ================================================ $ gcc -fPIC -Wall -I`ocamlc -where` -L`ocamlc -where` -ltermcap -lm -ldl \ -o finalbc.native main.c embed_out.o -lcamlrun $ ./finalbc.native Before calling OCaml hello embedded world 1 hello embedded world 2 After calling OCaml ================================================ FILE: code/back-end-embed/build_embed_c.sh ================================================ ocamlc -output-obj -o embed_out.c embed_me1.ml embed_me2.ml ================================================ FILE: code/back-end-embed/build_embed_native.rawsh ================================================ $ ocamlopt -output-obj -o embed_native.o embed_me1.ml embed_me2.ml $ gcc -Wall -I `ocamlc -where` -o final.native embed_native.o main.c \ -L `ocamlc -where` -lasmrun -ltermcap -lm -ldl $ ./final.native Before calling OCaml hello embedded world 1 hello embedded world 2 After calling OCaml ================================================ FILE: code/back-end-embed/embed_me1.ml ================================================ let () = print_endline "hello embedded world 1" ================================================ FILE: code/back-end-embed/embed_me2.ml ================================================ let () = print_endline "hello embedded world 2" ================================================ FILE: code/back-end-embed/embed_out.c ================================================ #ifdef __cplusplus extern "C" { #endif #include CAMLextern void caml_startup_code( code_t code, asize_t code_size, char *data, asize_t data_size, char *section_table, asize_t section_table_size, char **argv); static int caml_code[] = { 0x00000054, 0x000003e3, 0x00000029, 0x0000002a, 0x00000001, 0x00000000, 0x00000056, 0x0000000e, 0x00000000, 0x00000044, 0x0000000b, 0x00000043, 0x0000000d, 0x0000000c, 0x00000032, 0x00000022, 0x0000000b, 0x00000040, 0x00000000, 0x00000028, 0x00000004, 0x00000001, 0x00000028, 0x00000002, 0x00000029, 0x0000002a, 0x00000003, 0x00000003, 0x00000085, 0x00000000, 0x00000004, 0x00000063, 0x00000028, 0x00000004, 0x00000003, 0x0000000d, 0x0000000d, 0x0000000d, 0x00000060, 0x0000009f, 0x0000000a, 0x00000084, 0x00000000, 0x00000006, 0x00000035, 0x00000004, 0x0000003f, 0x00000000, 0x0000005b, 0x00000000, 0x0000000f, 0x0000006f, 0x0000000b, 0x0000000f, 0x0000006e, 0x0000000e, 0x0000000e, 0x00000032, 0x00000024, 0x00000004, 0x00000009, 0x00000000, 0x0000005d, 0x0000009d, 0x00000028, 0x00000001, 0x00000029, 0x0000002a, 0x00000001, 0x00000001, 0x0000000b, 0x0000005e, 0x000000a7, 0x00000028, 0x00000002, 0x00000029, 0x0000002a, 0x00000001, 0x00000001, 0x0000000b, 0x0000005e, 0x000000a7, 0x00000028, 0x00000002, 0x00000029, 0x0000002a, 0x00000001, 0x00000001, 0x0000000b, 0x0000005e, 0x000000a8, 0x00000028, 0x00000002, 0x00000029, 0x0000002a, 0x00000001, 0x00000001, 0x0000000b, 0x0000005e, 0x000000b0, 0x00000028, 0x00000002, 0x00000000, 0x0000005d, 0x000000ac, 0x00000028, 0x00000001, 0x00000000, 0x0000005d, 0x0000009a, 0x00000028, 0x00000001, 0x00000029, 0x0000002a, 0x00000001, 0x00000001, 0x0000000b, 0x0000005e, 0x000000b2, 0x00000028, 0x00000002, 0x00000000, 0x0000005d, 0x000000a0, 0x00000028, 0x00000001, 0x00000000, 0x0000005d, 0x000000a0, 0x00000028, 0x00000001, 0x00000000, 0x0000005d, 0x000000a1, 0x00000028, 0x00000001, 0x00000000, 0x0000005d, 0x00000052, 0x00000028, 0x00000001, 0x00000029, 0x0000002a, 0x00000001, 0x00000001, 0x0000000b, 0x0000005e, 0x000000ae, 0x00000028, 0x00000002, 0x00000000, 0x0000005d, 0x000000aa, 0x00000028, 0x00000001, 0x00000000, 0x0000005d, 0x0000009a, 0x00000028, 0x00000001, 0x00000000, 0x0000005d, 0x0000009c, 0x00000028, 0x00000001, 0x00000029, 0x0000002a, 0x00000001, 0x00000001, 0x0000000b, 0x0000005e, 0x000000b2, 0x00000028, 0x00000002, 0x00000029, 0x0000002a, 0x00000001, 0x00000001, 0x0000000b, 0x0000005e, 0x000000b1, 0x00000028, 0x00000002, 0x00000000, 0x0000005d, 0x000000ad, 0x00000028, 0x00000001, 0x00000000, 0x0000005d, 0x0000009b, 0x00000028, 0x00000001, 0x00000029, 0x0000002a, 0x00000001, 0x00000001, 0x0000000b, 0x0000005e, 0x000000af, 0x00000028, 0x00000002, 0x00000000, 0x0000005d, 0x000000ab, 0x00000028, 0x00000001, 0x00000000, 0x0000005d, 0x0000009b, 0x00000028, 0x00000001, 0x00000063, 0x0000001a, 0x00000021, 0x00000000, 0x0000005d, 0x00000100, 0x00000028, 0x00000001, 0x00000063, 0x0000001a, 0x00000043, 0x00000025, 0x00000002, 0x00000063, 0x0000001a, 0x00000021, 0x00000063, 0x0000001b, 0x00000025, 0x00000002, 0x00000015, 0x00000043, 0x0000000a, 0x0000000c, 0x0000002b, 0x00000002, 0xfffffff3, 0x0000001a, 0x00000049, 0x00000028, 0x00000002, 0x00000000, 0x0000000a, 0x0000005d, 0x000000b3, 0x0000000a, 0x0000005d, 0x00000023, 0x0000000b, 0x00000068, 0x0000000c, 0x00000068, 0x00000010, 0x00000061, 0x00000019, 0x00000000, 0x00000028, 0x00000004, 0x00000029, 0x0000002a, 0x00000001, 0x00000001, 0x00000036, 0x0000000c, 0x0000001a, 0x00000022, 0x0000000b, 0x0000001a, 0x00000026, 0x00000004, 0x00000063, 0x0000001a, 0x00000021, 0x0000005d, 0x00000034, 0x00000028, 0x00000001, 0x00000063, 0x0000001a, 0x00000021, 0x0000005d, 0x00000087, 0x00000028, 0x00000001, 0x00000016, 0x0000005d, 0x0000009d, 0x00000015, 0x0000001c, 0x00000025, 0x00000002, 0x00000067, 0x0000000a, 0x0000001a, 0x0000005e, 0x000000a7, 0x00000015, 0x0000005d, 0x0000009d, 0x00000028, 0x00000001, 0x00000000, 0x0000001a, 0x0000001b, 0x00000022, 0x00000067, 0x0000000a, 0x0000001a, 0x0000005e, 0x000000a7, 0x00000015, 0x0000005d, 0x0000009d, 0x00000028, 0x00000001, 0x00000000, 0x0000001a, 0x00000021, 0x0000001b, 0x0000001c, 0x00000026, 0x00000003, 0x00000000, 0x0000001a, 0x00000021, 0x0000001b, 0x0000001c, 0x00000026, 0x00000003, 0x00000000, 0x0000001a, 0x0000001b, 0x00000026, 0x00000003, 0x00000000, 0x0000001a, 0x0000005e, 0x000000a7, 0x00000028, 0x00000001, 0x00000067, 0x0000000a, 0x0000001a, 0x0000005e, 0x000000a7, 0x00000015, 0x0000005d, 0x0000009d, 0x00000028, 0x00000001, 0x00000000, 0x0000001a, 0x0000001b, 0x00000022, 0x00000067, 0x0000000a, 0x0000001a, 0x0000005e, 0x000000a7, 0x00000015, 0x0000005d, 0x0000009d, 0x00000028, 0x00000001, 0x00000000, 0x0000001a, 0x00000021, 0x0000001b, 0x0000001c, 0x00000026, 0x00000003, 0x00000000, 0x0000001a, 0x00000021, 0x0000001b, 0x0000001c, 0x00000026, 0x00000003, 0x00000000, 0x0000001a, 0x0000001b, 0x00000026, 0x00000003, 0x00000000, 0x0000001a, 0x0000005e, 0x000000a7, 0x00000028, 0x00000001, 0x00000059, 0x00000007, 0x00000004, 0x0000005d, 0x0000009c, 0x0000005a, 0x00000028, 0x00000001, 0x00000068, 0x00000028, 0x00000002, 0x00000029, 0x0000002a, 0x00000002, 0x00000002, 0x00000056, 0x00000019, 0x00000002, 0x00000044, 0x0000000d, 0x00000043, 0x0000000a, 0x0000005d, 0x000000b3, 0x0000000a, 0x0000000b, 0x00000010, 0x0000006f, 0x0000000f, 0x00000068, 0x0000000f, 0x00000061, 0x00000019, 0x00000002, 0x0000000b, 0x00000010, 0x0000006f, 0x0000000f, 0x00000032, 0x00000027, 0x00000009, 0x00000000, 0x00000028, 0x00000003, 0x00000029, 0x0000002a, 0x00000001, 0x00000015, 0x0000005d, 0x000000a2, 0x0000000a, 0x00000084, 0x00000000, 0x00000011, 0x00000001, 0x00000056, 0x00000009, 0x00000001, 0x0000000d, 0x0000000e, 0x0000005d, 0x00000023, 0x0000001b, 0x00000027, 0x00000006, 0x00000035, 0x00000004, 0x0000003f, 0x00000000, 0x0000005b, 0x00000000, 0x00000088, 0x00000000, 0x00000029, 0x00000000, 0x0000007f, 0xffffffff, 0x0000005d, 0x00000023, 0x0000000b, 0x0000007f, 0xffffffff, 0x00000068, 0x0000000c, 0x0000001a, 0x00000060, 0x0000009f, 0x00000063, 0x00000015, 0x0000005d, 0x000000a0, 0x00000063, 0x00000002, 0x00000056, 0x00000011, 0x00000001, 0x0000000e, 0x0000006e, 0x0000007f, 0xffffffff, 0x0000000d, 0x0000000c, 0x00000040, 0x00000000, 0x0000000b, 0x0000000c, 0x0000005d, 0x00000023, 0x0000001b, 0x00000027, 0x00000008, 0x00000000, 0x00000028, 0x00000004, 0x00000000, 0x0000006d, 0x0000005d, 0x00000023, 0x0000000b, 0x0000006d, 0x00000068, 0x0000000c, 0x0000001a, 0x00000060, 0x0000009f, 0x00000063, 0x00000001, 0x0000000e, 0x0000006f, 0x0000000d, 0x0000000c, 0x00000040, 0x00000000, 0x00000032, 0x00000026, 0x00000006, 0x0000002c, 0x00000001, 0x00000000, 0xffffff81, 0x00000000, 0x0000000c, 0x0000002c, 0x00000001, 0x00000002, 0xffffff9c, 0x00000063, 0x00000068, 0x0000000c, 0x00000026, 0x00000005, 0x00000029, 0x0000002a, 0x00000003, 0x00000002, 0x00000087, 0x00000000, 0x0000000e, 0x00000003, 0x00000087, 0x00000000, 0x0000000a, 0x00000003, 0x0000000c, 0x0000005d, 0x000000b3, 0x0000006f, 0x0000000d, 0x0000007d, 0x00000056, 0x00000006, 0x00000035, 0x0000000d, 0x0000001a, 0x00000025, 0x00000005, 0x00000003, 0x0000000d, 0x0000000d, 0x0000000d, 0x0000001b, 0x00000024, 0x00000004, 0x00000008, 0x00000029, 0x0000002a, 0x00000003, 0x00000002, 0x00000087, 0x00000000, 0x0000000e, 0x00000003, 0x00000087, 0x00000000, 0x0000000a, 0x00000003, 0x0000000c, 0x0000005d, 0x000000b3, 0x0000006f, 0x0000000d, 0x0000007d, 0x00000056, 0x00000006, 0x00000035, 0x0000000e, 0x0000001a, 0x00000025, 0x00000005, 0x00000003, 0x0000000d, 0x0000000d, 0x0000000d, 0x00000060, 0x0000009f, 0x00000028, 0x00000004, 0x00000000, 0x00000068, 0x00000036, 0x0000000f, 0x0000001a, 0x00000027, 0x00000004, 0x00000000, 0x00000068, 0x00000036, 0x00000010, 0x0000001a, 0x00000027, 0x00000004, 0x00000029, 0x0000002a, 0x00000002, 0x00000001, 0x0000000b, 0x0000000e, 0x0000005f, 0x00000107, 0x0000005d, 0x000000a3, 0x00000028, 0x00000003, 0x00000059, 0x00000007, 0x00000004, 0x0000005d, 0x0000009d, 0x0000005a, 0x00000054, 0x00000004, 0x00000068, 0x00000013, 0x00000001, 0x00000059, 0x00000007, 0x00000004, 0x0000005d, 0x0000009c, 0x0000005a, 0x00000028, 0x00000001, 0x00000068, 0x00000028, 0x00000002, 0x00000000, 0x0000005d, 0x0000009d, 0x00000000, 0x0000005d, 0x0000009c, 0x00000028, 0x00000001, 0x00000029, 0x0000002a, 0x00000001, 0x00000063, 0x0000000c, 0x0000000c, 0x0000005f, 0x000000d7, 0x00000028, 0x00000002, 0x00000029, 0x0000002a, 0x00000003, 0x00000002, 0x00000087, 0x00000000, 0x0000000e, 0x00000003, 0x00000087, 0x00000000, 0x0000000a, 0x00000003, 0x0000000c, 0x0000005d, 0x000000b3, 0x0000006f, 0x0000000d, 0x0000007d, 0x00000056, 0x00000006, 0x00000035, 0x00000011, 0x0000001a, 0x00000025, 0x00000005, 0x00000003, 0x0000000d, 0x0000000d, 0x0000000d, 0x00000060, 0x000000a6, 0x00000028, 0x00000004, 0x00000029, 0x0000002a, 0x00000001, 0x00000001, 0x0000005d, 0x000000b3, 0x00000068, 0x0000000d, 0x0000000d, 0x00000060, 0x000000a6, 0x00000028, 0x00000002, 0x00000000, 0x00000056, 0x00000015, 0x00000000, 0x00000044, 0x0000000b, 0x00000043, 0x00000009, 0x00000059, 0x00000007, 0x00000004, 0x0000005d, 0x0000009d, 0x0000005a, 0x00000054, 0x00000004, 0x00000068, 0x00000013, 0x00000001, 0x00000001, 0x00000032, 0x00000025, 0x00000004, 0x00000063, 0x00000028, 0x00000001, 0x0000002c, 0x00000001, 0x00000000, 0xffffffe3, 0x00000063, 0x0000005d, 0x000000a5, 0x0000000b, 0x00000025, 0x00000003, 0x00000000, 0x0000006c, 0x000001b6, 0x00000036, 0x00000012, 0x0000001a, 0x00000027, 0x00000004, 0x00000000, 0x0000006c, 0x000001b6, 0x00000036, 0x00000013, 0x0000001a, 0x00000027, 0x00000004, 0x00000029, 0x0000002a, 0x00000002, 0x00000001, 0x0000000b, 0x0000000e, 0x0000005f, 0x00000107, 0x0000005d, 0x000000a4, 0x00000028, 0x00000003, 0x00000000, 0x00000036, 0x00000014, 0x0000005e, 0x00000037, 0x0000001a, 0x00000025, 0x00000002, 0x00000017, 0x0000000b, 0x0000007e, 0x00000056, 0x00000007, 0x00000035, 0x00000015, 0x0000001b, 0x0000001a, 0x00000026, 0x00000003, 0x00000000, 0x0000001b, 0x0000005e, 0x000000eb, 0x0000000a, 0x00000087, 0x00000030, 0x00000007, 0x00000000, 0x00000086, 0x0000003a, 0x00000009, 0x00000054, 0x0000000a, 0x00000000, 0x00000084, 0x0000002d, 0x00000003, 0x00000054, 0x00000004, 0x00000016, 0x00000028, 0x00000002, 0x00000001, 0x0000007f, 0x00000001, 0x00000032, 0x00000025, 0x00000003, 0x00000000, 0x0000005d, 0x000000b3, 0x0000000a, 0x0000000c, 0x0000001a, 0x0000002c, 0x00000001, 0x00000003, 0xffffffcf, 0x00000063, 0x0000000b, 0x00000025, 0x00000004, 0x00000000, 0x00000036, 0x00000016, 0x0000005e, 0x00000038, 0x00000028, 0x00000001, 0x00000035, 0x00000017, 0x0000000b, 0x0000005e, 0x000000f3, 0x00000056, 0x00000010, 0x00000035, 0x00000018, 0x0000000b, 0x0000005e, 0x000000f3, 0x00000056, 0x00000006, 0x00000035, 0x00000019, 0x0000001a, 0x00000025, 0x00000002, 0x00000064, 0x00000028, 0x00000001, 0x00000063, 0x00000028, 0x00000001, 0x00000000, 0x00000056, 0x00000005, 0x00000035, 0x0000001a, 0x00000028, 0x00000001, 0x00000035, 0x0000001b, 0x00000028, 0x00000001, 0x00000000, 0x00000087, 0x00000000, 0x00000005, 0x00000000, 0x00000088, 0x000000ff, 0x00000006, 0x00000035, 0x0000001c, 0x0000001a, 0x00000025, 0x00000002, 0x00000000, 0x00000028, 0x00000001, 0x00000029, 0x0000002a, 0x00000001, 0x00000000, 0x0000005d, 0x000000b3, 0x0000000c, 0x0000005d, 0x000000b3, 0x0000000a, 0x0000000c, 0x0000006e, 0x0000005d, 0x00000023, 0x0000000c, 0x00000068, 0x0000000c, 0x00000068, 0x00000011, 0x00000061, 0x00000019, 0x00000001, 0x0000000d, 0x0000000c, 0x00000068, 0x00000012, 0x00000008, 0x00000061, 0x00000019, 0x00000000, 0x00000028, 0x00000005, 0x00000067, 0xffffffff, 0x0000000b, 0x00000075, 0x00000028, 0x00000001, 0x00000000, 0x00000087, 0x00000000, 0x00000004, 0x00000000, 0x00000028, 0x00000001, 0x00000000, 0x0000006d, 0x00000028, 0x00000001, 0x00000029, 0x0000002a, 0x00000001, 0x00000001, 0x0000000b, 0x0000005e, 0x0000004c, 0x00000056, 0x00000004, 0x00000000, 0x00000028, 0x00000002, 0x00000001, 0x00000028, 0x00000002, 0x00000029, 0x0000002a, 0x00000001, 0x00000001, 0x0000000b, 0x0000005e, 0x0000008e, 0x00000056, 0x00000004, 0x00000000, 0x00000028, 0x00000002, 0x00000001, 0x00000028, 0x00000002, 0x00000000, 0x00000036, 0x00000003, 0x00000040, 0x00000000, 0x0000005b, 0x00000000, 0x00000036, 0x00000002, 0x00000040, 0x00000000, 0x0000005b, 0x0000002b, 0x00000000, 0xfffffff8, 0x00000009, 0x0000002b, 0x00000000, 0xffffffee, 0x00000036, 0x0000001d, 0x0000003f, 0x00000000, 0x00000009, 0x0000002b, 0x00000000, 0xffffffd8, 0x00000009, 0x0000002b, 0x00000000, 0xffffffc5, 0x00000009, 0x0000002b, 0x00000000, 0xffffffb5, 0x00000009, 0x0000002b, 0x00000000, 0xffffffab, 0x0000006c, 0x0000001f, 0x00000069, 0x00000076, 0x00000084, 0x00000000, 0x00000005, 0x00000067, 0x0000001e, 0x00000054, 0x00000003, 0x00000067, 0x0000003e, 0x00000069, 0x00000076, 0x0000000a, 0x0000007f, 0xffffffff, 0x00000036, 0x0000001e, 0x0000005d, 0x00000071, 0x00000036, 0x0000001f, 0x0000005d, 0x00000071, 0x00000036, 0x00000020, 0x0000005d, 0x00000071, 0x00000036, 0x00000021, 0x0000005d, 0x00000071, 0x00000036, 0x00000022, 0x0000005d, 0x00000071, 0x00000036, 0x00000023, 0x0000005d, 0x00000071, 0x00000009, 0x0000002b, 0x00000000, 0xffffff5e, 0x00000012, 0x0000000e, 0x0000002b, 0x00000001, 0xffffff48, 0x00000009, 0x0000002b, 0x00000000, 0xffffff39, 0x00000012, 0x00000010, 0x0000002b, 0x00000001, 0xffffff1b, 0x00000009, 0x0000002b, 0x00000000, 0xffffff10, 0x00000009, 0x0000003a, 0x0000000f, 0x0000002b, 0x00000001, 0xfffffefc, 0x0000000a, 0x0000002b, 0x00000001, 0xfffffec8, 0x00000009, 0x0000002c, 0x00000001, 0x00000000, 0xfffffbb6, 0x00000063, 0x0000005d, 0x000000a3, 0x00000069, 0x0000005d, 0x000000a4, 0x0000006a, 0x0000005d, 0x000000a4, 0x00000009, 0x0000002b, 0x00000000, 0xfffffeab, 0x0000000a, 0x0000002b, 0x00000001, 0xfffffe9e, 0x0000000b, 0x0000002b, 0x00000001, 0xfffffe92, 0x00000009, 0x0000002b, 0x00000000, 0xfffffe84, 0x00000009, 0x0000002b, 0x00000000, 0xfffffe5a, 0x00000012, 0x0000001e, 0x0000002b, 0x00000001, 0xfffffe34, 0x00000009, 0x0000002b, 0x00000000, 0xfffffe26, 0x00000009, 0x0000002b, 0x00000000, 0xfffffe19, 0x00000009, 0x0000002b, 0x00000000, 0xfffffdff, 0x00000009, 0x0000002b, 0x00000000, 0xfffffdf0, 0x0000000a, 0x0000002b, 0x00000001, 0xfffffde4, 0x0000000b, 0x0000002b, 0x00000001, 0xfffffdd9, 0x00000012, 0x00000025, 0x0000002b, 0x00000001, 0xfffffdb4, 0x00000009, 0x0000002c, 0x00000001, 0x00000000, 0xfffffb88, 0x00000000, 0x00000012, 0x00000028, 0x0000002b, 0x00000002, 0xfffffd88, 0x00000009, 0x0000002b, 0x00000000, 0xfffffd74, 0x00000009, 0x0000002b, 0x00000000, 0xfffffce8, 0x00000012, 0x00000012, 0x0000002b, 0x00000001, 0xfffffcdd, 0x00000012, 0x0000000d, 0x00000012, 0x00000014, 0x0000002b, 0x00000002, 0xfffffcd1, 0x00000012, 0x0000000e, 0x00000012, 0x00000015, 0x00000012, 0x0000001c, 0x0000002b, 0x00000003, 0xfffffcc1, 0x00000012, 0x0000000f, 0x00000012, 0x00000016, 0x00000012, 0x0000001a, 0x0000002b, 0x00000003, 0xfffffcb1, 0x00000012, 0x00000010, 0x00000012, 0x00000017, 0x0000002b, 0x00000002, 0xfffffc9c, 0x00000012, 0x00000017, 0x0000002b, 0x00000001, 0xfffffc8d, 0x00000012, 0x00000017, 0x0000002b, 0x00000001, 0xfffffc82, 0x00000012, 0x00000013, 0x00000012, 0x00000019, 0x0000002b, 0x00000002, 0xfffffc76, 0x00000012, 0x00000014, 0x00000012, 0x0000001a, 0x00000012, 0x00000022, 0x0000002b, 0x00000003, 0xfffffc66, 0x00000012, 0x00000015, 0x00000012, 0x0000001b, 0x00000012, 0x00000020, 0x0000002b, 0x00000003, 0xfffffc56, 0x00000012, 0x00000016, 0x00000012, 0x0000001c, 0x0000002b, 0x00000002, 0xfffffc41, 0x00000012, 0x0000001c, 0x0000002b, 0x00000001, 0xfffffc32, 0x00000012, 0x0000000d, 0x00000012, 0x0000001f, 0x00000012, 0x00000021, 0x0000002b, 0x00000003, 0xfffffc22, 0x0000000a, 0x0000002b, 0x00000001, 0xfffffc17, 0x0000000b, 0x0000002b, 0x00000001, 0xfffffc0c, 0x00000009, 0x0000003a, 0x00000012, 0x0000002c, 0x0000002b, 0x00000001, 0xfffffbfa, 0x00000009, 0x0000002b, 0x00000000, 0xfffffbe4, 0x00000012, 0x0000001f, 0x0000003f, 0x00000000, 0x0000000a, 0x0000002b, 0x00000001, 0xfffffbd1, 0x0000000b, 0x0000002b, 0x00000001, 0xfffffbc1, 0x0000000a, 0x0000002b, 0x00000001, 0xfffffbb5, 0x0000000b, 0x00000036, 0x00000024, 0x0000005e, 0x000000df, 0x00000001, 0x00000012, 0x0000001a, 0x00000012, 0x0000002e, 0x0000000f, 0x0000000e, 0x00000012, 0x0000000a, 0x00000012, 0x0000000a, 0x00000009, 0x0000002b, 0x00000000, 0xfffffb9c, 0x00000009, 0x0000002b, 0x00000000, 0xfffffb93, 0x00000009, 0x0000002b, 0x00000000, 0xfffffb87, 0x00000009, 0x0000002b, 0x00000000, 0xfffffb7d, 0x00000009, 0x0000002b, 0x00000000, 0xfffffb74, 0x00000009, 0x0000002b, 0x00000000, 0xfffffb68, 0x0000003e, 0x00000006, 0x00000000, 0x00000009, 0x0000002b, 0x00000000, 0xfffffb58, 0x00000012, 0x0000001f, 0x00000009, 0x0000002b, 0x00000000, 0xfffffb4c, 0x00000009, 0x0000002b, 0x00000000, 0xfffffb43, 0x00000009, 0x0000002b, 0x00000000, 0xfffffb3a, 0x00000009, 0x0000002b, 0x00000000, 0xfffffb2e, 0x00000009, 0x0000002b, 0x00000000, 0xfffffb24, 0x00000009, 0x0000002b, 0x00000000, 0xfffffb1b, 0x00000009, 0x0000002b, 0x00000000, 0xfffffb12, 0x00000012, 0x00000029, 0x00000012, 0x0000002c, 0x00000012, 0x0000002a, 0x00000009, 0x0000002b, 0x00000000, 0xfffffb03, 0x00000012, 0x00000032, 0x00000012, 0x00000031, 0x00000012, 0x00000033, 0x00000009, 0x0000002b, 0x00000000, 0xfffffaf1, 0x00000012, 0x00000037, 0x00000012, 0x00000039, 0x00000009, 0x0000002b, 0x00000000, 0xfffffae3, 0x00000009, 0x0000002b, 0x00000000, 0xfffffada, 0x00000009, 0x0000002b, 0x00000000, 0xffffface, 0x00000012, 0x0000003e, 0x00000009, 0x0000002b, 0x00000000, 0xfffffabf, 0x00000009, 0x0000002b, 0x00000000, 0xfffffab2, 0x00000012, 0x00000042, 0x00000012, 0x00000044, 0x00000009, 0x0000002b, 0x00000000, 0xfffffaa1, 0x00000012, 0x00000047, 0x00000009, 0x0000002b, 0x00000000, 0xfffffa95, 0x00000012, 0x0000004c, 0x00000012, 0x0000004b, 0x00000012, 0x0000004d, 0x00000012, 0x00000030, 0x00000012, 0x00000032, 0x00000012, 0x00000034, 0x00000012, 0x00000036, 0x00000012, 0x00000038, 0x00000012, 0x0000003a, 0x00000012, 0x0000003c, 0x00000012, 0x0000003e, 0x00000012, 0x00000040, 0x00000012, 0x00000042, 0x00000012, 0x00000044, 0x00000012, 0x00000046, 0x00000012, 0x00000048, 0x00000012, 0x0000004a, 0x00000012, 0x0000004c, 0x00000012, 0x0000005f, 0x00000012, 0x00000061, 0x00000012, 0x00000063, 0x00000012, 0x00000065, 0x00000012, 0x00000067, 0x00000012, 0x0000006b, 0x00000012, 0x0000006d, 0x00000012, 0x0000006f, 0x00000012, 0x00000071, 0x00000012, 0x00000073, 0x00000012, 0x00000075, 0x00000012, 0x00000077, 0x00000012, 0x00000079, 0x00000012, 0x0000007b, 0x00000012, 0x0000007d, 0x00000012, 0x0000007f, 0x00000012, 0x00000083, 0x00000012, 0x00000083, 0x00000012, 0x00000083, 0x00000012, 0x00000087, 0x00000012, 0x00000089, 0x00000012, 0x0000008b, 0x00000012, 0x0000008d, 0x00000012, 0x00000090, 0x00000012, 0x00000090, 0x0000003e, 0x00000051, 0x00000000, 0x00000013, 0x00000042, 0x00000039, 0x00000025, 0x00000035, 0x00000026, 0x00000038, 0x00000025, 0x0000001d, 0x00000021, 0x00000009, 0x0000003a, 0x00000013, 0x00000001, 0x00000039, 0x00000027, 0x00000035, 0x00000028, 0x00000038, 0x00000025, 0x0000001d, 0x00000021, 0x00000009, 0x0000003a, 0x00000013, 0x00000001, 0x00000039, 0x00000029, 0x8f}; static char caml_data[] = { 132, 149, 166, 190, 0, 0, 1, 211, 0, 0, 0, 60, 0, 0, 0, 254, 0, 0, 0, 204, 8, 0, 0, 168, 0, 144, 45, 79, 117, 116, 95, 111, 102, 95, 109, 101, 109, 111, 114, 121, 144, 41, 83, 121, 115, 95, 101, 114, 114, 111, 114, 144, 39, 70, 97, 105, 108, 117, 114, 101, 144, 48, 73, 110, 118, 97, 108, 105, 100, 95, 97, 114, 103, 117, 109, 101, 110, 116, 144, 43, 69, 110, 100, 95, 111, 102, 95, 102, 105, 108, 101, 144, 48, 68, 105, 118, 105, 115, 105, 111, 110, 95, 98, 121, 95, 122, 101, 114, 111, 144, 41, 78, 111, 116, 95, 102, 111, 117, 110, 100, 144, 45, 77, 97, 116, 99, 104, 95, 102, 97, 105, 108, 117, 114, 101, 144, 46, 83, 116, 97, 99, 107, 95, 111, 118, 101, 114, 102, 108, 111, 119, 144, 46, 83, 121, 115, 95, 98, 108, 111, 99, 107, 101, 100, 95, 105, 111, 144, 46, 65, 115, 115, 101, 114, 116, 95, 102, 97, 105, 108, 117, 114, 101, 144, 58, 85, 110, 100, 101, 102, 105, 110, 101, 100, 95, 114, 101, 99, 117, 114, 115, 105, 118, 101, 95, 109, 111, 100, 117, 108, 101, 34, 37, 44, 44, 114, 101, 97, 108, 108, 121, 95, 105, 110, 112, 117, 116, 37, 105, 110, 112, 117, 116, 160, 64, 160, 70, 64, 160, 64, 160, 71, 64, 38, 111, 117, 116, 112, 117, 116, 160, 65, 160, 67, 160, 68, 160, 70, 64, 160, 65, 160, 67, 160, 68, 160, 71, 64, 37, 37, 46, 49, 50, 103, 33, 46, 34, 37, 100, 37, 102, 97, 108, 115, 101, 36, 116, 114, 117, 101, 46, 98, 111, 111, 108, 95, 111, 102, 95, 115, 116, 114, 105, 110, 103, 36, 116, 114, 117, 101, 37, 102, 97, 108, 115, 101, 43, 99, 104, 97, 114, 95, 111, 102, 95, 105, 110, 116, 47, 80, 101, 114, 118, 97, 115, 105, 118, 101, 115, 46, 69, 120, 105, 116, 18, 95, 106, 0, 127, 240, 0, 0, 0, 0, 0, 0, 18, 95, 106, 0, 255, 240, 0, 0, 0, 0, 0, 0, 18, 95, 106, 0, 127, 240, 0, 0, 0, 0, 0, 1, 18, 95, 106, 0, 127, 239, 255, 255, 255, 255, 255, 255, 18, 95, 106, 0, 0, 16, 0, 0, 0, 0, 0, 0, 18, 95, 106, 0, 60, 176, 0, 0, 0, 0, 0, 0, 53, 80, 101, 114, 118, 97, 115, 105, 118, 101, 115, 46, 100, 111, 95, 97, 116, 95, 101, 120, 105, 116, 64, 54, 104, 101, 108, 108, 111, 32, 101, 109, 98, 101, 100, 100, 101, 100, 32, 119, 111, 114, 108, 100, 32, 49, 64, 54, 104, 101, 108, 108, 111, 32, 101, 109, 98, 101, 100, 100, 101, 100, 32, 119, 111, 114, 108, 100, 32, 50, 64, }; static char caml_sections[] = { 132, 149, 166, 190, 0, 0, 22, 254, 0, 0, 0, 66, 0, 0, 6, 126, 0, 0, 3, 176, 160, 160, 36, 83, 89, 77, 66, 160, 106, 208, 208, 208, 208, 64, 176, 64, 41, 69, 109, 98, 101, 100, 95, 109, 101, 49, 65, 103, 208, 64, 176, 64, 41, 69, 109, 98, 101, 100, 95, 109, 101, 50, 65, 105, 64, 65, 66, 176, 64, 42, 80, 101, 114, 118, 97, 115, 105, 118, 101, 115, 65, 101, 208, 208, 64, 176, 80, 45, 77, 97, 116, 99, 104, 95, 102, 97, 105, 108, 117, 114, 101, 67, 71, 64, 65, 176, 81, 45, 79, 117, 116, 95, 111, 102, 95, 109, 101, 109, 111, 114, 121, 67, 64, 208, 64, 176, 82, 48, 73, 110, 118, 97, 108, 105, 100, 95, 97, 114, 103, 117, 109, 101, 110, 116, 67, 67, 64, 65, 66, 67, 176, 83, 39, 70, 97, 105, 108, 117, 114, 101, 67, 66, 208, 208, 64, 176, 84, 41, 78, 111, 116, 95, 102, 111, 117, 110, 100, 67, 70, 64, 65, 176, 85, 41, 83, 121, 115, 95, 101, 114, 114, 111, 114, 67, 65, 64, 66, 68, 176, 86, 43, 69, 110, 100, 95, 111, 102, 95, 102, 105, 108, 101, 67, 68, 208, 208, 64, 176, 87, 48, 68, 105, 118, 105, 115, 105, 111, 110, 95, 98, 121, 95, 122, 101, 114, 111, 67, 69, 64, 65, 176, 88, 46, 83, 116, 97, 99, 107, 95, 111, 118, 101, 114, 102, 108, 111, 119, 67, 72, 208, 208, 64, 176, 89, 46, 83, 121, 115, 95, 98, 108, 111, 99, 107, 101, 100, 95, 105, 111, 67, 73, 64, 65, 176, 90, 46, 65, 115, 115, 101, 114, 116, 95, 102, 97, 105, 108, 117, 114, 101, 67, 74, 208, 64, 176, 91, 58, 85, 110, 100, 101, 102, 105, 110, 101, 100, 95, 114, 101, 99, 117, 114, 115, 105, 118, 101, 95, 109, 111, 100, 117, 108, 101, 67, 75, 64, 65, 66, 67, 69, 160, 160, 36, 80, 82, 73, 77, 10, 0, 0, 21, 97, 99, 97, 109, 108, 95, 97, 98, 115, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 97, 99, 111, 115, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 97, 100, 100, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 97, 108, 108, 111, 99, 95, 100, 117, 109, 109, 121, 0, 99, 97, 109, 108, 95, 97, 108, 108, 111, 99, 95, 100, 117, 109, 109, 121, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 97, 114, 114, 97, 121, 95, 97, 112, 112, 101, 110, 100, 0, 99, 97, 109, 108, 95, 97, 114, 114, 97, 121, 95, 98, 108, 105, 116, 0, 99, 97, 109, 108, 95, 97, 114, 114, 97, 121, 95, 99, 111, 110, 99, 97, 116, 0, 99, 97, 109, 108, 95, 97, 114, 114, 97, 121, 95, 103, 101, 116, 0, 99, 97, 109, 108, 95, 97, 114, 114, 97, 121, 95, 103, 101, 116, 95, 97, 100, 100, 114, 0, 99, 97, 109, 108, 95, 97, 114, 114, 97, 121, 95, 103, 101, 116, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 97, 114, 114, 97, 121, 95, 115, 101, 116, 0, 99, 97, 109, 108, 95, 97, 114, 114, 97, 121, 95, 115, 101, 116, 95, 97, 100, 100, 114, 0, 99, 97, 109, 108, 95, 97, 114, 114, 97, 121, 95, 115, 101, 116, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 97, 114, 114, 97, 121, 95, 115, 117, 98, 0, 99, 97, 109, 108, 95, 97, 114, 114, 97, 121, 95, 117, 110, 115, 97, 102, 101, 95, 103, 101, 116, 0, 99, 97, 109, 108, 95, 97, 114, 114, 97, 121, 95, 117, 110, 115, 97, 102, 101, 95, 103, 101, 116, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 97, 114, 114, 97, 121, 95, 117, 110, 115, 97, 102, 101, 95, 115, 101, 116, 0, 99, 97, 109, 108, 95, 97, 114, 114, 97, 121, 95, 117, 110, 115, 97, 102, 101, 95, 115, 101, 116, 95, 97, 100, 100, 114, 0, 99, 97, 109, 108, 95, 97, 114, 114, 97, 121, 95, 117, 110, 115, 97, 102, 101, 95, 115, 101, 116, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 97, 115, 105, 110, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 97, 116, 97, 110, 50, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 97, 116, 97, 110, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 98, 97, 99, 107, 116, 114, 97, 99, 101, 95, 115, 116, 97, 116, 117, 115, 0, 99, 97, 109, 108, 95, 98, 105, 116, 118, 101, 99, 116, 95, 116, 101, 115, 116, 0, 99, 97, 109, 108, 95, 98, 108, 105, 116, 95, 115, 116, 114, 105, 110, 103, 0, 99, 97, 109, 108, 95, 98, 115, 119, 97, 112, 49, 54, 0, 99, 97, 109, 108, 95, 99, 101, 105, 108, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 99, 104, 97, 110, 110, 101, 108, 95, 100, 101, 115, 99, 114, 105, 112, 116, 111, 114, 0, 99, 97, 109, 108, 95, 99, 108, 97, 115, 115, 105, 102, 121, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 99, 111, 109, 112, 97, 114, 101, 0, 99, 97, 109, 108, 95, 99, 111, 110, 118, 101, 114, 116, 95, 114, 97, 119, 95, 98, 97, 99, 107, 116, 114, 97, 99, 101, 0, 99, 97, 109, 108, 95, 99, 111, 112, 121, 115, 105, 103, 110, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 99, 111, 115, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 99, 111, 115, 104, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 99, 114, 101, 97, 116, 101, 95, 115, 116, 114, 105, 110, 103, 0, 99, 97, 109, 108, 95, 100, 105, 118, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 100, 121, 110, 108, 105, 110, 107, 95, 97, 100, 100, 95, 112, 114, 105, 109, 105, 116, 105, 118, 101, 0, 99, 97, 109, 108, 95, 100, 121, 110, 108, 105, 110, 107, 95, 99, 108, 111, 115, 101, 95, 108, 105, 98, 0, 99, 97, 109, 108, 95, 100, 121, 110, 108, 105, 110, 107, 95, 103, 101, 116, 95, 99, 117, 114, 114, 101, 110, 116, 95, 108, 105, 98, 115, 0, 99, 97, 109, 108, 95, 100, 121, 110, 108, 105, 110, 107, 95, 108, 111, 111, 107, 117, 112, 95, 115, 121, 109, 98, 111, 108, 0, 99, 97, 109, 108, 95, 100, 121, 110, 108, 105, 110, 107, 95, 111, 112, 101, 110, 95, 108, 105, 98, 0, 99, 97, 109, 108, 95, 101, 110, 115, 117, 114, 101, 95, 115, 116, 97, 99, 107, 95, 99, 97, 112, 97, 99, 105, 116, 121, 0, 99, 97, 109, 108, 95, 101, 113, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 101, 113, 117, 97, 108, 0, 99, 97, 109, 108, 95, 101, 120, 112, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 101, 120, 112, 109, 49, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 102, 105, 108, 108, 95, 115, 116, 114, 105, 110, 103, 0, 99, 97, 109, 108, 95, 102, 105, 110, 97, 108, 95, 114, 101, 103, 105, 115, 116, 101, 114, 0, 99, 97, 109, 108, 95, 102, 105, 110, 97, 108, 95, 114, 101, 108, 101, 97, 115, 101, 0, 99, 97, 109, 108, 95, 102, 108, 111, 97, 116, 95, 99, 111, 109, 112, 97, 114, 101, 0, 99, 97, 109, 108, 95, 102, 108, 111, 97, 116, 95, 111, 102, 95, 105, 110, 116, 0, 99, 97, 109, 108, 95, 102, 108, 111, 97, 116, 95, 111, 102, 95, 115, 116, 114, 105, 110, 103, 0, 99, 97, 109, 108, 95, 102, 108, 111, 111, 114, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 102, 109, 111, 100, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 102, 111, 114, 109, 97, 116, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 102, 111, 114, 109, 97, 116, 95, 105, 110, 116, 0, 99, 97, 109, 108, 95, 102, 114, 101, 120, 112, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 103, 99, 95, 99, 111, 109, 112, 97, 99, 116, 105, 111, 110, 0, 99, 97, 109, 108, 95, 103, 99, 95, 99, 111, 117, 110, 116, 101, 114, 115, 0, 99, 97, 109, 108, 95, 103, 99, 95, 102, 117, 108, 108, 95, 109, 97, 106, 111, 114, 0, 99, 97, 109, 108, 95, 103, 99, 95, 103, 101, 116, 0, 99, 97, 109, 108, 95, 103, 99, 95, 109, 97, 106, 111, 114, 0, 99, 97, 109, 108, 95, 103, 99, 95, 109, 97, 106, 111, 114, 95, 115, 108, 105, 99, 101, 0, 99, 97, 109, 108, 95, 103, 99, 95, 109, 105, 110, 111, 114, 0, 99, 97, 109, 108, 95, 103, 99, 95, 113, 117, 105, 99, 107, 95, 115, 116, 97, 116, 0, 99, 97, 109, 108, 95, 103, 99, 95, 115, 101, 116, 0, 99, 97, 109, 108, 95, 103, 99, 95, 115, 116, 97, 116, 0, 99, 97, 109, 108, 95, 103, 101, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 103, 101, 116, 95, 99, 117, 114, 114, 101, 110, 116, 95, 99, 97, 108, 108, 115, 116, 97, 99, 107, 0, 99, 97, 109, 108, 95, 103, 101, 116, 95, 99, 117, 114, 114, 101, 110, 116, 95, 101, 110, 118, 105, 114, 111, 110, 109, 101, 110, 116, 0, 99, 97, 109, 108, 95, 103, 101, 116, 95, 101, 120, 99, 101, 112, 116, 105, 111, 110, 95, 98, 97, 99, 107, 116, 114, 97, 99, 101, 0, 99, 97, 109, 108, 95, 103, 101, 116, 95, 101, 120, 99, 101, 112, 116, 105, 111, 110, 95, 114, 97, 119, 95, 98, 97, 99, 107, 116, 114, 97, 99, 101, 0, 99, 97, 109, 108, 95, 103, 101, 116, 95, 103, 108, 111, 98, 97, 108, 95, 100, 97, 116, 97, 0, 99, 97, 109, 108, 95, 103, 101, 116, 95, 112, 117, 98, 108, 105, 99, 95, 109, 101, 116, 104, 111, 100, 0, 99, 97, 109, 108, 95, 103, 101, 116, 95, 115, 101, 99, 116, 105, 111, 110, 95, 116, 97, 98, 108, 101, 0, 99, 97, 109, 108, 95, 103, 114, 101, 97, 116, 101, 114, 101, 113, 117, 97, 108, 0, 99, 97, 109, 108, 95, 103, 114, 101, 97, 116, 101, 114, 116, 104, 97, 110, 0, 99, 97, 109, 108, 95, 103, 116, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 104, 97, 115, 104, 0, 99, 97, 109, 108, 95, 104, 97, 115, 104, 95, 117, 110, 105, 118, 95, 112, 97, 114, 97, 109, 0, 99, 97, 109, 108, 95, 104, 121, 112, 111, 116, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 105, 110, 112, 117, 116, 95, 118, 97, 108, 117, 101, 0, 99, 97, 109, 108, 95, 105, 110, 112, 117, 116, 95, 118, 97, 108, 117, 101, 95, 102, 114, 111, 109, 95, 115, 116, 114, 105, 110, 103, 0, 99, 97, 109, 108, 95, 105, 110, 115, 116, 97, 108, 108, 95, 115, 105, 103, 110, 97, 108, 95, 104, 97, 110, 100, 108, 101, 114, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 97, 100, 100, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 97, 110, 100, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 98, 105, 116, 115, 95, 111, 102, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 98, 115, 119, 97, 112, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 99, 111, 109, 112, 97, 114, 101, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 100, 105, 118, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 102, 108, 111, 97, 116, 95, 111, 102, 95, 98, 105, 116, 115, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 102, 111, 114, 109, 97, 116, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 109, 111, 100, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 109, 117, 108, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 110, 101, 103, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 111, 102, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 111, 102, 95, 105, 110, 116, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 111, 102, 95, 115, 116, 114, 105, 110, 103, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 111, 114, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 115, 104, 105, 102, 116, 95, 108, 101, 102, 116, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 115, 104, 105, 102, 116, 95, 114, 105, 103, 104, 116, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 115, 104, 105, 102, 116, 95, 114, 105, 103, 104, 116, 95, 117, 110, 115, 105, 103, 110, 101, 100, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 115, 117, 98, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 116, 111, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 116, 111, 95, 105, 110, 116, 0, 99, 97, 109, 108, 95, 105, 110, 116, 51, 50, 95, 120, 111, 114, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 97, 100, 100, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 97, 110, 100, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 98, 105, 116, 115, 95, 111, 102, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 98, 115, 119, 97, 112, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 99, 111, 109, 112, 97, 114, 101, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 100, 105, 118, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 102, 108, 111, 97, 116, 95, 111, 102, 95, 98, 105, 116, 115, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 102, 111, 114, 109, 97, 116, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 109, 111, 100, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 109, 117, 108, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 110, 101, 103, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 111, 102, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 111, 102, 95, 105, 110, 116, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 111, 102, 95, 105, 110, 116, 51, 50, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 111, 102, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 111, 102, 95, 115, 116, 114, 105, 110, 103, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 111, 114, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 115, 104, 105, 102, 116, 95, 108, 101, 102, 116, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 115, 104, 105, 102, 116, 95, 114, 105, 103, 104, 116, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 115, 104, 105, 102, 116, 95, 114, 105, 103, 104, 116, 95, 117, 110, 115, 105, 103, 110, 101, 100, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 115, 117, 98, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 116, 111, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 116, 111, 95, 105, 110, 116, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 116, 111, 95, 105, 110, 116, 51, 50, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 116, 111, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 0, 99, 97, 109, 108, 95, 105, 110, 116, 54, 52, 95, 120, 111, 114, 0, 99, 97, 109, 108, 95, 105, 110, 116, 95, 99, 111, 109, 112, 97, 114, 101, 0, 99, 97, 109, 108, 95, 105, 110, 116, 95, 111, 102, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 105, 110, 116, 95, 111, 102, 95, 115, 116, 114, 105, 110, 103, 0, 99, 97, 109, 108, 95, 105, 110, 118, 111, 107, 101, 95, 116, 114, 97, 99, 101, 100, 95, 102, 117, 110, 99, 116, 105, 111, 110, 0, 99, 97, 109, 108, 95, 105, 115, 95, 112, 114, 105, 110, 116, 97, 98, 108, 101, 0, 99, 97, 109, 108, 95, 108, 97, 122, 121, 95, 102, 111, 108, 108, 111, 119, 95, 102, 111, 114, 119, 97, 114, 100, 0, 99, 97, 109, 108, 95, 108, 97, 122, 121, 95, 109, 97, 107, 101, 95, 102, 111, 114, 119, 97, 114, 100, 0, 99, 97, 109, 108, 95, 108, 100, 101, 120, 112, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 108, 101, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 108, 101, 115, 115, 101, 113, 117, 97, 108, 0, 99, 97, 109, 108, 95, 108, 101, 115, 115, 116, 104, 97, 110, 0, 99, 97, 109, 108, 95, 108, 101, 120, 95, 101, 110, 103, 105, 110, 101, 0, 99, 97, 109, 108, 95, 108, 111, 103, 49, 48, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 108, 111, 103, 49, 112, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 108, 111, 103, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 108, 116, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 109, 97, 107, 101, 95, 97, 114, 114, 97, 121, 0, 99, 97, 109, 108, 95, 109, 97, 107, 101, 95, 118, 101, 99, 116, 0, 99, 97, 109, 108, 95, 109, 97, 114, 115, 104, 97, 108, 95, 100, 97, 116, 97, 95, 115, 105, 122, 101, 0, 99, 97, 109, 108, 95, 109, 100, 53, 95, 99, 104, 97, 110, 0, 99, 97, 109, 108, 95, 109, 100, 53, 95, 115, 116, 114, 105, 110, 103, 0, 99, 97, 109, 108, 95, 109, 108, 95, 99, 104, 97, 110, 110, 101, 108, 95, 115, 105, 122, 101, 0, 99, 97, 109, 108, 95, 109, 108, 95, 99, 104, 97, 110, 110, 101, 108, 95, 115, 105, 122, 101, 95, 54, 52, 0, 99, 97, 109, 108, 95, 109, 108, 95, 99, 108, 111, 115, 101, 95, 99, 104, 97, 110, 110, 101, 108, 0, 99, 97, 109, 108, 95, 109, 108, 95, 102, 108, 117, 115, 104, 0, 99, 97, 109, 108, 95, 109, 108, 95, 102, 108, 117, 115, 104, 95, 112, 97, 114, 116, 105, 97, 108, 0, 99, 97, 109, 108, 95, 109, 108, 95, 105, 110, 112, 117, 116, 0, 99, 97, 109, 108, 95, 109, 108, 95, 105, 110, 112, 117, 116, 95, 99, 104, 97, 114, 0, 99, 97, 109, 108, 95, 109, 108, 95, 105, 110, 112, 117, 116, 95, 105, 110, 116, 0, 99, 97, 109, 108, 95, 109, 108, 95, 105, 110, 112, 117, 116, 95, 115, 99, 97, 110, 95, 108, 105, 110, 101, 0, 99, 97, 109, 108, 95, 109, 108, 95, 111, 112, 101, 110, 95, 100, 101, 115, 99, 114, 105, 112, 116, 111, 114, 95, 105, 110, 0, 99, 97, 109, 108, 95, 109, 108, 95, 111, 112, 101, 110, 95, 100, 101, 115, 99, 114, 105, 112, 116, 111, 114, 95, 111, 117, 116, 0, 99, 97, 109, 108, 95, 109, 108, 95, 111, 117, 116, 95, 99, 104, 97, 110, 110, 101, 108, 115, 95, 108, 105, 115, 116, 0, 99, 97, 109, 108, 95, 109, 108, 95, 111, 117, 116, 112, 117, 116, 0, 99, 97, 109, 108, 95, 109, 108, 95, 111, 117, 116, 112, 117, 116, 95, 99, 104, 97, 114, 0, 99, 97, 109, 108, 95, 109, 108, 95, 111, 117, 116, 112, 117, 116, 95, 105, 110, 116, 0, 99, 97, 109, 108, 95, 109, 108, 95, 111, 117, 116, 112, 117, 116, 95, 112, 97, 114, 116, 105, 97, 108, 0, 99, 97, 109, 108, 95, 109, 108, 95, 112, 111, 115, 95, 105, 110, 0, 99, 97, 109, 108, 95, 109, 108, 95, 112, 111, 115, 95, 105, 110, 95, 54, 52, 0, 99, 97, 109, 108, 95, 109, 108, 95, 112, 111, 115, 95, 111, 117, 116, 0, 99, 97, 109, 108, 95, 109, 108, 95, 112, 111, 115, 95, 111, 117, 116, 95, 54, 52, 0, 99, 97, 109, 108, 95, 109, 108, 95, 115, 101, 101, 107, 95, 105, 110, 0, 99, 97, 109, 108, 95, 109, 108, 95, 115, 101, 101, 107, 95, 105, 110, 95, 54, 52, 0, 99, 97, 109, 108, 95, 109, 108, 95, 115, 101, 101, 107, 95, 111, 117, 116, 0, 99, 97, 109, 108, 95, 109, 108, 95, 115, 101, 101, 107, 95, 111, 117, 116, 95, 54, 52, 0, 99, 97, 109, 108, 95, 109, 108, 95, 115, 101, 116, 95, 98, 105, 110, 97, 114, 121, 95, 109, 111, 100, 101, 0, 99, 97, 109, 108, 95, 109, 108, 95, 115, 116, 114, 105, 110, 103, 95, 108, 101, 110, 103, 116, 104, 0, 99, 97, 109, 108, 95, 109, 111, 100, 102, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 109, 117, 108, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 97, 100, 100, 0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 97, 110, 100, 0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 98, 115, 119, 97, 112, 0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 99, 111, 109, 112, 97, 114, 101, 0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 100, 105, 118, 0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 102, 111, 114, 109, 97, 116, 0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 109, 111, 100, 0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 109, 117, 108, 0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 110, 101, 103, 0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 111, 102, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 111, 102, 95, 105, 110, 116, 0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 111, 102, 95, 105, 110, 116, 51, 50, 0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 111, 102, 95, 115, 116, 114, 105, 110, 103, 0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 111, 114, 0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 115, 104, 105, 102, 116, 95, 108, 101, 102, 116, 0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 115, 104, 105, 102, 116, 95, 114, 105, 103, 104, 116, 0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 115, 104, 105, 102, 116, 95, 114, 105, 103, 104, 116, 95, 117, 110, 115, 105, 103, 110, 101, 100, 0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 115, 117, 98, 0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 116, 111, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 116, 111, 95, 105, 110, 116, 0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 116, 111, 95, 105, 110, 116, 51, 50, 0, 99, 97, 109, 108, 95, 110, 97, 116, 105, 118, 101, 105, 110, 116, 95, 120, 111, 114, 0, 99, 97, 109, 108, 95, 110, 101, 103, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 110, 101, 113, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 110, 101, 119, 95, 108, 101, 120, 95, 101, 110, 103, 105, 110, 101, 0, 99, 97, 109, 108, 95, 110, 111, 116, 101, 113, 117, 97, 108, 0, 99, 97, 109, 108, 95, 111, 98, 106, 95, 97, 100, 100, 95, 111, 102, 102, 115, 101, 116, 0, 99, 97, 109, 108, 95, 111, 98, 106, 95, 98, 108, 111, 99, 107, 0, 99, 97, 109, 108, 95, 111, 98, 106, 95, 100, 117, 112, 0, 99, 97, 109, 108, 95, 111, 98, 106, 95, 105, 115, 95, 98, 108, 111, 99, 107, 0, 99, 97, 109, 108, 95, 111, 98, 106, 95, 115, 101, 116, 95, 116, 97, 103, 0, 99, 97, 109, 108, 95, 111, 98, 106, 95, 116, 97, 103, 0, 99, 97, 109, 108, 95, 111, 98, 106, 95, 116, 114, 117, 110, 99, 97, 116, 101, 0, 99, 97, 109, 108, 95, 111, 117, 116, 112, 117, 116, 95, 118, 97, 108, 117, 101, 0, 99, 97, 109, 108, 95, 111, 117, 116, 112, 117, 116, 95, 118, 97, 108, 117, 101, 95, 116, 111, 95, 98, 117, 102, 102, 101, 114, 0, 99, 97, 109, 108, 95, 111, 117, 116, 112, 117, 116, 95, 118, 97, 108, 117, 101, 95, 116, 111, 95, 115, 116, 114, 105, 110, 103, 0, 99, 97, 109, 108, 95, 112, 97, 114, 115, 101, 95, 101, 110, 103, 105, 110, 101, 0, 99, 97, 109, 108, 95, 112, 111, 119, 101, 114, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 114, 101, 97, 108, 108, 111, 99, 95, 103, 108, 111, 98, 97, 108, 0, 99, 97, 109, 108, 95, 114, 101, 99, 111, 114, 100, 95, 98, 97, 99, 107, 116, 114, 97, 99, 101, 0, 99, 97, 109, 108, 95, 114, 101, 103, 105, 115, 116, 101, 114, 95, 99, 111, 100, 101, 95, 102, 114, 97, 103, 109, 101, 110, 116, 0, 99, 97, 109, 108, 95, 114, 101, 103, 105, 115, 116, 101, 114, 95, 110, 97, 109, 101, 100, 95, 118, 97, 108, 117, 101, 0, 99, 97, 109, 108, 95, 114, 101, 105, 102, 121, 95, 98, 121, 116, 101, 99, 111, 100, 101, 0, 99, 97, 109, 108, 95, 115, 101, 116, 95, 112, 97, 114, 115, 101, 114, 95, 116, 114, 97, 99, 101, 0, 99, 97, 109, 108, 95, 115, 105, 110, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 115, 105, 110, 104, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 115, 113, 114, 116, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 115, 116, 97, 116, 105, 99, 95, 97, 108, 108, 111, 99, 0, 99, 97, 109, 108, 95, 115, 116, 97, 116, 105, 99, 95, 102, 114, 101, 101, 0, 99, 97, 109, 108, 95, 115, 116, 97, 116, 105, 99, 95, 114, 101, 108, 101, 97, 115, 101, 95, 98, 121, 116, 101, 99, 111, 100, 101, 0, 99, 97, 109, 108, 95, 115, 116, 97, 116, 105, 99, 95, 114, 101, 115, 105, 122, 101, 0, 99, 97, 109, 108, 95, 115, 116, 114, 105, 110, 103, 95, 99, 111, 109, 112, 97, 114, 101, 0, 99, 97, 109, 108, 95, 115, 116, 114, 105, 110, 103, 95, 101, 113, 117, 97, 108, 0, 99, 97, 109, 108, 95, 115, 116, 114, 105, 110, 103, 95, 103, 101, 116, 0, 99, 97, 109, 108, 95, 115, 116, 114, 105, 110, 103, 95, 103, 101, 116, 49, 54, 0, 99, 97, 109, 108, 95, 115, 116, 114, 105, 110, 103, 95, 103, 101, 116, 51, 50, 0, 99, 97, 109, 108, 95, 115, 116, 114, 105, 110, 103, 95, 103, 101, 116, 54, 52, 0, 99, 97, 109, 108, 95, 115, 116, 114, 105, 110, 103, 95, 103, 114, 101, 97, 116, 101, 114, 101, 113, 117, 97, 108, 0, 99, 97, 109, 108, 95, 115, 116, 114, 105, 110, 103, 95, 103, 114, 101, 97, 116, 101, 114, 116, 104, 97, 110, 0, 99, 97, 109, 108, 95, 115, 116, 114, 105, 110, 103, 95, 108, 101, 115, 115, 101, 113, 117, 97, 108, 0, 99, 97, 109, 108, 95, 115, 116, 114, 105, 110, 103, 95, 108, 101, 115, 115, 116, 104, 97, 110, 0, 99, 97, 109, 108, 95, 115, 116, 114, 105, 110, 103, 95, 110, 111, 116, 101, 113, 117, 97, 108, 0, 99, 97, 109, 108, 95, 115, 116, 114, 105, 110, 103, 95, 115, 101, 116, 0, 99, 97, 109, 108, 95, 115, 116, 114, 105, 110, 103, 95, 115, 101, 116, 49, 54, 0, 99, 97, 109, 108, 95, 115, 116, 114, 105, 110, 103, 95, 115, 101, 116, 51, 50, 0, 99, 97, 109, 108, 95, 115, 116, 114, 105, 110, 103, 95, 115, 101, 116, 54, 52, 0, 99, 97, 109, 108, 95, 115, 117, 98, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 99, 104, 100, 105, 114, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 99, 108, 111, 115, 101, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 99, 111, 110, 115, 116, 95, 98, 105, 103, 95, 101, 110, 100, 105, 97, 110, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 99, 111, 110, 115, 116, 95, 111, 115, 116, 121, 112, 101, 95, 99, 121, 103, 119, 105, 110, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 99, 111, 110, 115, 116, 95, 111, 115, 116, 121, 112, 101, 95, 117, 110, 105, 120, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 99, 111, 110, 115, 116, 95, 111, 115, 116, 121, 112, 101, 95, 119, 105, 110, 51, 50, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 99, 111, 110, 115, 116, 95, 119, 111, 114, 100, 95, 115, 105, 122, 101, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 101, 120, 105, 116, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 102, 105, 108, 101, 95, 101, 120, 105, 115, 116, 115, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 103, 101, 116, 95, 97, 114, 103, 118, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 103, 101, 116, 95, 99, 111, 110, 102, 105, 103, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 103, 101, 116, 99, 119, 100, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 103, 101, 116, 101, 110, 118, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 105, 115, 95, 100, 105, 114, 101, 99, 116, 111, 114, 121, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 111, 112, 101, 110, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 114, 97, 110, 100, 111, 109, 95, 115, 101, 101, 100, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 114, 101, 97, 100, 95, 100, 105, 114, 101, 99, 116, 111, 114, 121, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 114, 101, 109, 111, 118, 101, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 114, 101, 110, 97, 109, 101, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 115, 121, 115, 116, 101, 109, 95, 99, 111, 109, 109, 97, 110, 100, 0, 99, 97, 109, 108, 95, 115, 121, 115, 95, 116, 105, 109, 101, 0, 99, 97, 109, 108, 95, 116, 97, 110, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 116, 97, 110, 104, 95, 102, 108, 111, 97, 116, 0, 99, 97, 109, 108, 95, 116, 101, 114, 109, 105, 110, 102, 111, 95, 98, 97, 99, 107, 117, 112, 0, 99, 97, 109, 108, 95, 116, 101, 114, 109, 105, 110, 102, 111, 95, 114, 101, 115, 117, 109, 101, 0, 99, 97, 109, 108, 95, 116, 101, 114, 109, 105, 110, 102, 111, 95, 115, 101, 116, 117, 112, 0, 99, 97, 109, 108, 95, 116, 101, 114, 109, 105, 110, 102, 111, 95, 115, 116, 97, 110, 100, 111, 117, 116, 0, 99, 97, 109, 108, 95, 117, 112, 100, 97, 116, 101, 95, 100, 117, 109, 109, 121, 0, 99, 97, 109, 108, 95, 119, 101, 97, 107, 95, 98, 108, 105, 116, 0, 99, 97, 109, 108, 95, 119, 101, 97, 107, 95, 99, 104, 101, 99, 107, 0, 99, 97, 109, 108, 95, 119, 101, 97, 107, 95, 99, 114, 101, 97, 116, 101, 0, 99, 97, 109, 108, 95, 119, 101, 97, 107, 95, 103, 101, 116, 0, 99, 97, 109, 108, 95, 119, 101, 97, 107, 95, 103, 101, 116, 95, 99, 111, 112, 121, 0, 99, 97, 109, 108, 95, 119, 101, 97, 107, 95, 115, 101, 116, 0, 160, 160, 36, 67, 82, 67, 83, 160, 160, 4, 49, 48, 190, 163, 18, 101, 189, 28, 219, 213, 174, 68, 31, 211, 31, 177, 196, 145, 160, 160, 4, 49, 48, 18, 91, 100, 123, 73, 58, 159, 133, 115, 221, 105, 87, 212, 43, 208, 18, 160, 160, 42, 80, 101, 114, 118, 97, 115, 105, 118, 101, 115, 48, 54, 181, 188, 130, 39, 220, 153, 20, 198, 217, 253, 155, 220, 250, 219, 69, 64, 64, }; extern value caml_abs_float(); extern value caml_acos_float(); extern value caml_add_float(); extern value caml_alloc_dummy(); extern value caml_alloc_dummy_float(); extern value caml_array_append(); extern value caml_array_blit(); extern value caml_array_concat(); extern value caml_array_get(); extern value caml_array_get_addr(); extern value caml_array_get_float(); extern value caml_array_set(); extern value caml_array_set_addr(); extern value caml_array_set_float(); extern value caml_array_sub(); extern value caml_array_unsafe_get(); extern value caml_array_unsafe_get_float(); extern value caml_array_unsafe_set(); extern value caml_array_unsafe_set_addr(); extern value caml_array_unsafe_set_float(); extern value caml_asin_float(); extern value caml_atan2_float(); extern value caml_atan_float(); extern value caml_backtrace_status(); extern value caml_bitvect_test(); extern value caml_blit_string(); extern value caml_bswap16(); extern value caml_ceil_float(); extern value caml_channel_descriptor(); extern value caml_classify_float(); extern value caml_compare(); extern value caml_convert_raw_backtrace(); extern value caml_copysign_float(); extern value caml_cos_float(); extern value caml_cosh_float(); extern value caml_create_string(); extern value caml_div_float(); extern value caml_dynlink_add_primitive(); extern value caml_dynlink_close_lib(); extern value caml_dynlink_get_current_libs(); extern value caml_dynlink_lookup_symbol(); extern value caml_dynlink_open_lib(); extern value caml_ensure_stack_capacity(); extern value caml_eq_float(); extern value caml_equal(); extern value caml_exp_float(); extern value caml_expm1_float(); extern value caml_fill_string(); extern value caml_final_register(); extern value caml_final_release(); extern value caml_float_compare(); extern value caml_float_of_int(); extern value caml_float_of_string(); extern value caml_floor_float(); extern value caml_fmod_float(); extern value caml_format_float(); extern value caml_format_int(); extern value caml_frexp_float(); extern value caml_gc_compaction(); extern value caml_gc_counters(); extern value caml_gc_full_major(); extern value caml_gc_get(); extern value caml_gc_major(); extern value caml_gc_major_slice(); extern value caml_gc_minor(); extern value caml_gc_quick_stat(); extern value caml_gc_set(); extern value caml_gc_stat(); extern value caml_ge_float(); extern value caml_get_current_callstack(); extern value caml_get_current_environment(); extern value caml_get_exception_backtrace(); extern value caml_get_exception_raw_backtrace(); extern value caml_get_global_data(); extern value caml_get_public_method(); extern value caml_get_section_table(); extern value caml_greaterequal(); extern value caml_greaterthan(); extern value caml_gt_float(); extern value caml_hash(); extern value caml_hash_univ_param(); extern value caml_hypot_float(); extern value caml_input_value(); extern value caml_input_value_from_string(); extern value caml_install_signal_handler(); extern value caml_int32_add(); extern value caml_int32_and(); extern value caml_int32_bits_of_float(); extern value caml_int32_bswap(); extern value caml_int32_compare(); extern value caml_int32_div(); extern value caml_int32_float_of_bits(); extern value caml_int32_format(); extern value caml_int32_mod(); extern value caml_int32_mul(); extern value caml_int32_neg(); extern value caml_int32_of_float(); extern value caml_int32_of_int(); extern value caml_int32_of_string(); extern value caml_int32_or(); extern value caml_int32_shift_left(); extern value caml_int32_shift_right(); extern value caml_int32_shift_right_unsigned(); extern value caml_int32_sub(); extern value caml_int32_to_float(); extern value caml_int32_to_int(); extern value caml_int32_xor(); extern value caml_int64_add(); extern value caml_int64_and(); extern value caml_int64_bits_of_float(); extern value caml_int64_bswap(); extern value caml_int64_compare(); extern value caml_int64_div(); extern value caml_int64_float_of_bits(); extern value caml_int64_format(); extern value caml_int64_mod(); extern value caml_int64_mul(); extern value caml_int64_neg(); extern value caml_int64_of_float(); extern value caml_int64_of_int(); extern value caml_int64_of_int32(); extern value caml_int64_of_nativeint(); extern value caml_int64_of_string(); extern value caml_int64_or(); extern value caml_int64_shift_left(); extern value caml_int64_shift_right(); extern value caml_int64_shift_right_unsigned(); extern value caml_int64_sub(); extern value caml_int64_to_float(); extern value caml_int64_to_int(); extern value caml_int64_to_int32(); extern value caml_int64_to_nativeint(); extern value caml_int64_xor(); extern value caml_int_compare(); extern value caml_int_of_float(); extern value caml_int_of_string(); extern value caml_invoke_traced_function(); extern value caml_is_printable(); extern value caml_lazy_follow_forward(); extern value caml_lazy_make_forward(); extern value caml_ldexp_float(); extern value caml_le_float(); extern value caml_lessequal(); extern value caml_lessthan(); extern value caml_lex_engine(); extern value caml_log10_float(); extern value caml_log1p_float(); extern value caml_log_float(); extern value caml_lt_float(); extern value caml_make_array(); extern value caml_make_vect(); extern value caml_marshal_data_size(); extern value caml_md5_chan(); extern value caml_md5_string(); extern value caml_ml_channel_size(); extern value caml_ml_channel_size_64(); extern value caml_ml_close_channel(); extern value caml_ml_flush(); extern value caml_ml_flush_partial(); extern value caml_ml_input(); extern value caml_ml_input_char(); extern value caml_ml_input_int(); extern value caml_ml_input_scan_line(); extern value caml_ml_open_descriptor_in(); extern value caml_ml_open_descriptor_out(); extern value caml_ml_out_channels_list(); extern value caml_ml_output(); extern value caml_ml_output_char(); extern value caml_ml_output_int(); extern value caml_ml_output_partial(); extern value caml_ml_pos_in(); extern value caml_ml_pos_in_64(); extern value caml_ml_pos_out(); extern value caml_ml_pos_out_64(); extern value caml_ml_seek_in(); extern value caml_ml_seek_in_64(); extern value caml_ml_seek_out(); extern value caml_ml_seek_out_64(); extern value caml_ml_set_binary_mode(); extern value caml_ml_string_length(); extern value caml_modf_float(); extern value caml_mul_float(); extern value caml_nativeint_add(); extern value caml_nativeint_and(); extern value caml_nativeint_bswap(); extern value caml_nativeint_compare(); extern value caml_nativeint_div(); extern value caml_nativeint_format(); extern value caml_nativeint_mod(); extern value caml_nativeint_mul(); extern value caml_nativeint_neg(); extern value caml_nativeint_of_float(); extern value caml_nativeint_of_int(); extern value caml_nativeint_of_int32(); extern value caml_nativeint_of_string(); extern value caml_nativeint_or(); extern value caml_nativeint_shift_left(); extern value caml_nativeint_shift_right(); extern value caml_nativeint_shift_right_unsigned(); extern value caml_nativeint_sub(); extern value caml_nativeint_to_float(); extern value caml_nativeint_to_int(); extern value caml_nativeint_to_int32(); extern value caml_nativeint_xor(); extern value caml_neg_float(); extern value caml_neq_float(); extern value caml_new_lex_engine(); extern value caml_notequal(); extern value caml_obj_add_offset(); extern value caml_obj_block(); extern value caml_obj_dup(); extern value caml_obj_is_block(); extern value caml_obj_set_tag(); extern value caml_obj_tag(); extern value caml_obj_truncate(); extern value caml_output_value(); extern value caml_output_value_to_buffer(); extern value caml_output_value_to_string(); extern value caml_parse_engine(); extern value caml_power_float(); extern value caml_realloc_global(); extern value caml_record_backtrace(); extern value caml_register_code_fragment(); extern value caml_register_named_value(); extern value caml_reify_bytecode(); extern value caml_set_parser_trace(); extern value caml_sin_float(); extern value caml_sinh_float(); extern value caml_sqrt_float(); extern value caml_static_alloc(); extern value caml_static_free(); extern value caml_static_release_bytecode(); extern value caml_static_resize(); extern value caml_string_compare(); extern value caml_string_equal(); extern value caml_string_get(); extern value caml_string_get16(); extern value caml_string_get32(); extern value caml_string_get64(); extern value caml_string_greaterequal(); extern value caml_string_greaterthan(); extern value caml_string_lessequal(); extern value caml_string_lessthan(); extern value caml_string_notequal(); extern value caml_string_set(); extern value caml_string_set16(); extern value caml_string_set32(); extern value caml_string_set64(); extern value caml_sub_float(); extern value caml_sys_chdir(); extern value caml_sys_close(); extern value caml_sys_const_big_endian(); extern value caml_sys_const_ostype_cygwin(); extern value caml_sys_const_ostype_unix(); extern value caml_sys_const_ostype_win32(); extern value caml_sys_const_word_size(); extern value caml_sys_exit(); extern value caml_sys_file_exists(); extern value caml_sys_get_argv(); extern value caml_sys_get_config(); extern value caml_sys_getcwd(); extern value caml_sys_getenv(); extern value caml_sys_is_directory(); extern value caml_sys_open(); extern value caml_sys_random_seed(); extern value caml_sys_read_directory(); extern value caml_sys_remove(); extern value caml_sys_rename(); extern value caml_sys_system_command(); extern value caml_sys_time(); extern value caml_tan_float(); extern value caml_tanh_float(); extern value caml_terminfo_backup(); extern value caml_terminfo_resume(); extern value caml_terminfo_setup(); extern value caml_terminfo_standout(); extern value caml_update_dummy(); extern value caml_weak_blit(); extern value caml_weak_check(); extern value caml_weak_create(); extern value caml_weak_get(); extern value caml_weak_get_copy(); extern value caml_weak_set(); typedef value (*primitive)(); primitive caml_builtin_cprim[] = { caml_abs_float, caml_acos_float, caml_add_float, caml_alloc_dummy, caml_alloc_dummy_float, caml_array_append, caml_array_blit, caml_array_concat, caml_array_get, caml_array_get_addr, caml_array_get_float, caml_array_set, caml_array_set_addr, caml_array_set_float, caml_array_sub, caml_array_unsafe_get, caml_array_unsafe_get_float, caml_array_unsafe_set, caml_array_unsafe_set_addr, caml_array_unsafe_set_float, caml_asin_float, caml_atan2_float, caml_atan_float, caml_backtrace_status, caml_bitvect_test, caml_blit_string, caml_bswap16, caml_ceil_float, caml_channel_descriptor, caml_classify_float, caml_compare, caml_convert_raw_backtrace, caml_copysign_float, caml_cos_float, caml_cosh_float, caml_create_string, caml_div_float, caml_dynlink_add_primitive, caml_dynlink_close_lib, caml_dynlink_get_current_libs, caml_dynlink_lookup_symbol, caml_dynlink_open_lib, caml_ensure_stack_capacity, caml_eq_float, caml_equal, caml_exp_float, caml_expm1_float, caml_fill_string, caml_final_register, caml_final_release, caml_float_compare, caml_float_of_int, caml_float_of_string, caml_floor_float, caml_fmod_float, caml_format_float, caml_format_int, caml_frexp_float, caml_gc_compaction, caml_gc_counters, caml_gc_full_major, caml_gc_get, caml_gc_major, caml_gc_major_slice, caml_gc_minor, caml_gc_quick_stat, caml_gc_set, caml_gc_stat, caml_ge_float, caml_get_current_callstack, caml_get_current_environment, caml_get_exception_backtrace, caml_get_exception_raw_backtrace, caml_get_global_data, caml_get_public_method, caml_get_section_table, caml_greaterequal, caml_greaterthan, caml_gt_float, caml_hash, caml_hash_univ_param, caml_hypot_float, caml_input_value, caml_input_value_from_string, caml_install_signal_handler, caml_int32_add, caml_int32_and, caml_int32_bits_of_float, caml_int32_bswap, caml_int32_compare, caml_int32_div, caml_int32_float_of_bits, caml_int32_format, caml_int32_mod, caml_int32_mul, caml_int32_neg, caml_int32_of_float, caml_int32_of_int, caml_int32_of_string, caml_int32_or, caml_int32_shift_left, caml_int32_shift_right, caml_int32_shift_right_unsigned, caml_int32_sub, caml_int32_to_float, caml_int32_to_int, caml_int32_xor, caml_int64_add, caml_int64_and, caml_int64_bits_of_float, caml_int64_bswap, caml_int64_compare, caml_int64_div, caml_int64_float_of_bits, caml_int64_format, caml_int64_mod, caml_int64_mul, caml_int64_neg, caml_int64_of_float, caml_int64_of_int, caml_int64_of_int32, caml_int64_of_nativeint, caml_int64_of_string, caml_int64_or, caml_int64_shift_left, caml_int64_shift_right, caml_int64_shift_right_unsigned, caml_int64_sub, caml_int64_to_float, caml_int64_to_int, caml_int64_to_int32, caml_int64_to_nativeint, caml_int64_xor, caml_int_compare, caml_int_of_float, caml_int_of_string, caml_invoke_traced_function, caml_is_printable, caml_lazy_follow_forward, caml_lazy_make_forward, caml_ldexp_float, caml_le_float, caml_lessequal, caml_lessthan, caml_lex_engine, caml_log10_float, caml_log1p_float, caml_log_float, caml_lt_float, caml_make_array, caml_make_vect, caml_marshal_data_size, caml_md5_chan, caml_md5_string, caml_ml_channel_size, caml_ml_channel_size_64, caml_ml_close_channel, caml_ml_flush, caml_ml_flush_partial, caml_ml_input, caml_ml_input_char, caml_ml_input_int, caml_ml_input_scan_line, caml_ml_open_descriptor_in, caml_ml_open_descriptor_out, caml_ml_out_channels_list, caml_ml_output, caml_ml_output_char, caml_ml_output_int, caml_ml_output_partial, caml_ml_pos_in, caml_ml_pos_in_64, caml_ml_pos_out, caml_ml_pos_out_64, caml_ml_seek_in, caml_ml_seek_in_64, caml_ml_seek_out, caml_ml_seek_out_64, caml_ml_set_binary_mode, caml_ml_string_length, caml_modf_float, caml_mul_float, caml_nativeint_add, caml_nativeint_and, caml_nativeint_bswap, caml_nativeint_compare, caml_nativeint_div, caml_nativeint_format, caml_nativeint_mod, caml_nativeint_mul, caml_nativeint_neg, caml_nativeint_of_float, caml_nativeint_of_int, caml_nativeint_of_int32, caml_nativeint_of_string, caml_nativeint_or, caml_nativeint_shift_left, caml_nativeint_shift_right, caml_nativeint_shift_right_unsigned, caml_nativeint_sub, caml_nativeint_to_float, caml_nativeint_to_int, caml_nativeint_to_int32, caml_nativeint_xor, caml_neg_float, caml_neq_float, caml_new_lex_engine, caml_notequal, caml_obj_add_offset, caml_obj_block, caml_obj_dup, caml_obj_is_block, caml_obj_set_tag, caml_obj_tag, caml_obj_truncate, caml_output_value, caml_output_value_to_buffer, caml_output_value_to_string, caml_parse_engine, caml_power_float, caml_realloc_global, caml_record_backtrace, caml_register_code_fragment, caml_register_named_value, caml_reify_bytecode, caml_set_parser_trace, caml_sin_float, caml_sinh_float, caml_sqrt_float, caml_static_alloc, caml_static_free, caml_static_release_bytecode, caml_static_resize, caml_string_compare, caml_string_equal, caml_string_get, caml_string_get16, caml_string_get32, caml_string_get64, caml_string_greaterequal, caml_string_greaterthan, caml_string_lessequal, caml_string_lessthan, caml_string_notequal, caml_string_set, caml_string_set16, caml_string_set32, caml_string_set64, caml_sub_float, caml_sys_chdir, caml_sys_close, caml_sys_const_big_endian, caml_sys_const_ostype_cygwin, caml_sys_const_ostype_unix, caml_sys_const_ostype_win32, caml_sys_const_word_size, caml_sys_exit, caml_sys_file_exists, caml_sys_get_argv, caml_sys_get_config, caml_sys_getcwd, caml_sys_getenv, caml_sys_is_directory, caml_sys_open, caml_sys_random_seed, caml_sys_read_directory, caml_sys_remove, caml_sys_rename, caml_sys_system_command, caml_sys_time, caml_tan_float, caml_tanh_float, caml_terminfo_backup, caml_terminfo_resume, caml_terminfo_setup, caml_terminfo_standout, caml_update_dummy, caml_weak_blit, caml_weak_check, caml_weak_create, caml_weak_get, caml_weak_get_copy, caml_weak_set, (primitive) 0 }; const char * caml_names_of_builtin_cprim[] = { "caml_abs_float", "caml_acos_float", "caml_add_float", "caml_alloc_dummy", "caml_alloc_dummy_float", "caml_array_append", "caml_array_blit", "caml_array_concat", "caml_array_get", "caml_array_get_addr", "caml_array_get_float", "caml_array_set", "caml_array_set_addr", "caml_array_set_float", "caml_array_sub", "caml_array_unsafe_get", "caml_array_unsafe_get_float", "caml_array_unsafe_set", "caml_array_unsafe_set_addr", "caml_array_unsafe_set_float", "caml_asin_float", "caml_atan2_float", "caml_atan_float", "caml_backtrace_status", "caml_bitvect_test", "caml_blit_string", "caml_bswap16", "caml_ceil_float", "caml_channel_descriptor", "caml_classify_float", "caml_compare", "caml_convert_raw_backtrace", "caml_copysign_float", "caml_cos_float", "caml_cosh_float", "caml_create_string", "caml_div_float", "caml_dynlink_add_primitive", "caml_dynlink_close_lib", "caml_dynlink_get_current_libs", "caml_dynlink_lookup_symbol", "caml_dynlink_open_lib", "caml_ensure_stack_capacity", "caml_eq_float", "caml_equal", "caml_exp_float", "caml_expm1_float", "caml_fill_string", "caml_final_register", "caml_final_release", "caml_float_compare", "caml_float_of_int", "caml_float_of_string", "caml_floor_float", "caml_fmod_float", "caml_format_float", "caml_format_int", "caml_frexp_float", "caml_gc_compaction", "caml_gc_counters", "caml_gc_full_major", "caml_gc_get", "caml_gc_major", "caml_gc_major_slice", "caml_gc_minor", "caml_gc_quick_stat", "caml_gc_set", "caml_gc_stat", "caml_ge_float", "caml_get_current_callstack", "caml_get_current_environment", "caml_get_exception_backtrace", "caml_get_exception_raw_backtrace", "caml_get_global_data", "caml_get_public_method", "caml_get_section_table", "caml_greaterequal", "caml_greaterthan", "caml_gt_float", "caml_hash", "caml_hash_univ_param", "caml_hypot_float", "caml_input_value", "caml_input_value_from_string", "caml_install_signal_handler", "caml_int32_add", "caml_int32_and", "caml_int32_bits_of_float", "caml_int32_bswap", "caml_int32_compare", "caml_int32_div", "caml_int32_float_of_bits", "caml_int32_format", "caml_int32_mod", "caml_int32_mul", "caml_int32_neg", "caml_int32_of_float", "caml_int32_of_int", "caml_int32_of_string", "caml_int32_or", "caml_int32_shift_left", "caml_int32_shift_right", "caml_int32_shift_right_unsigned", "caml_int32_sub", "caml_int32_to_float", "caml_int32_to_int", "caml_int32_xor", "caml_int64_add", "caml_int64_and", "caml_int64_bits_of_float", "caml_int64_bswap", "caml_int64_compare", "caml_int64_div", "caml_int64_float_of_bits", "caml_int64_format", "caml_int64_mod", "caml_int64_mul", "caml_int64_neg", "caml_int64_of_float", "caml_int64_of_int", "caml_int64_of_int32", "caml_int64_of_nativeint", "caml_int64_of_string", "caml_int64_or", "caml_int64_shift_left", "caml_int64_shift_right", "caml_int64_shift_right_unsigned", "caml_int64_sub", "caml_int64_to_float", "caml_int64_to_int", "caml_int64_to_int32", "caml_int64_to_nativeint", "caml_int64_xor", "caml_int_compare", "caml_int_of_float", "caml_int_of_string", "caml_invoke_traced_function", "caml_is_printable", "caml_lazy_follow_forward", "caml_lazy_make_forward", "caml_ldexp_float", "caml_le_float", "caml_lessequal", "caml_lessthan", "caml_lex_engine", "caml_log10_float", "caml_log1p_float", "caml_log_float", "caml_lt_float", "caml_make_array", "caml_make_vect", "caml_marshal_data_size", "caml_md5_chan", "caml_md5_string", "caml_ml_channel_size", "caml_ml_channel_size_64", "caml_ml_close_channel", "caml_ml_flush", "caml_ml_flush_partial", "caml_ml_input", "caml_ml_input_char", "caml_ml_input_int", "caml_ml_input_scan_line", "caml_ml_open_descriptor_in", "caml_ml_open_descriptor_out", "caml_ml_out_channels_list", "caml_ml_output", "caml_ml_output_char", "caml_ml_output_int", "caml_ml_output_partial", "caml_ml_pos_in", "caml_ml_pos_in_64", "caml_ml_pos_out", "caml_ml_pos_out_64", "caml_ml_seek_in", "caml_ml_seek_in_64", "caml_ml_seek_out", "caml_ml_seek_out_64", "caml_ml_set_binary_mode", "caml_ml_string_length", "caml_modf_float", "caml_mul_float", "caml_nativeint_add", "caml_nativeint_and", "caml_nativeint_bswap", "caml_nativeint_compare", "caml_nativeint_div", "caml_nativeint_format", "caml_nativeint_mod", "caml_nativeint_mul", "caml_nativeint_neg", "caml_nativeint_of_float", "caml_nativeint_of_int", "caml_nativeint_of_int32", "caml_nativeint_of_string", "caml_nativeint_or", "caml_nativeint_shift_left", "caml_nativeint_shift_right", "caml_nativeint_shift_right_unsigned", "caml_nativeint_sub", "caml_nativeint_to_float", "caml_nativeint_to_int", "caml_nativeint_to_int32", "caml_nativeint_xor", "caml_neg_float", "caml_neq_float", "caml_new_lex_engine", "caml_notequal", "caml_obj_add_offset", "caml_obj_block", "caml_obj_dup", "caml_obj_is_block", "caml_obj_set_tag", "caml_obj_tag", "caml_obj_truncate", "caml_output_value", "caml_output_value_to_buffer", "caml_output_value_to_string", "caml_parse_engine", "caml_power_float", "caml_realloc_global", "caml_record_backtrace", "caml_register_code_fragment", "caml_register_named_value", "caml_reify_bytecode", "caml_set_parser_trace", "caml_sin_float", "caml_sinh_float", "caml_sqrt_float", "caml_static_alloc", "caml_static_free", "caml_static_release_bytecode", "caml_static_resize", "caml_string_compare", "caml_string_equal", "caml_string_get", "caml_string_get16", "caml_string_get32", "caml_string_get64", "caml_string_greaterequal", "caml_string_greaterthan", "caml_string_lessequal", "caml_string_lessthan", "caml_string_notequal", "caml_string_set", "caml_string_set16", "caml_string_set32", "caml_string_set64", "caml_sub_float", "caml_sys_chdir", "caml_sys_close", "caml_sys_const_big_endian", "caml_sys_const_ostype_cygwin", "caml_sys_const_ostype_unix", "caml_sys_const_ostype_win32", "caml_sys_const_word_size", "caml_sys_exit", "caml_sys_file_exists", "caml_sys_get_argv", "caml_sys_get_config", "caml_sys_getcwd", "caml_sys_getenv", "caml_sys_is_directory", "caml_sys_open", "caml_sys_random_seed", "caml_sys_read_directory", "caml_sys_remove", "caml_sys_rename", "caml_sys_system_command", "caml_sys_time", "caml_tan_float", "caml_tanh_float", "caml_terminfo_backup", "caml_terminfo_resume", "caml_terminfo_setup", "caml_terminfo_standout", "caml_update_dummy", "caml_weak_blit", "caml_weak_check", "caml_weak_create", "caml_weak_get", "caml_weak_get_copy", "caml_weak_set", (char *) 0 }; void caml_startup(char ** argv) { caml_startup_code(caml_code, sizeof(caml_code), caml_data, sizeof(caml_data), caml_sections, sizeof(caml_sections), argv); } #ifdef __cplusplus } #endif ================================================ FILE: code/back-end-embed/hello.ml ================================================ let () = print_endline "Hello OCaml World!" ================================================ FILE: code/back-end-embed/link_custom.rawsh ================================================ $ ocamlc -a -o mylib.cma -custom a.cmo b.cmo -cclib -lmylib ================================================ FILE: code/back-end-embed/link_dllib.rawsh ================================================ $ ocamlc -a -o mylib.cma a.cmo b.cmo -dllib -lmylib ================================================ FILE: code/back-end-embed/main.c ================================================ #include #include #include #include #include int main (int argc, char **argv) { printf("Before calling OCaml\n"); fflush(stdout); caml_startup (argv); printf("After calling OCaml\n"); return 0; } ================================================ FILE: code/back-end-embed/run_debug_hello.sh ================================================ ocamlopt -runtime-variant d -verbose -o hello.native hello.ml ./hello.native ================================================ FILE: code/back-end-embed/xbuild_embed_binary.sh ================================================ gcc -fPIC -Wall -I`ocamlc -where` -L`ocamlc -where` -ltermcap -lm -ldl -o finalbc.native main.c embed_out.o -lcamlrun ./finalbc.native ================================================ FILE: code/back-end-embed/xbuild_embed_native.sh ================================================ ocamlopt -output-obj -o embed_native.o embed_me1.ml embed_me2.ml gcc -Wall -I `ocamlc -where` -o final.native embed_native.o main.c -L `ocamlc -where` -lasmrun -ltermcap -lm -ldl ./final.native ================================================ FILE: code/classes/Iterator.java ================================================ // Java-style iterator, specified as an interface. interface iterator { T Get(); boolean HasValue(); void Next(); }; ================================================ FILE: code/classes/binary.topscript ================================================ class square w = object(self : 'self) method width = w method area = Float.of_int (self#width * self#width) method equals (other : 'self) = other#width = self#width end ;; class circle r = object(self : 'self) method radius = r method area = 3.14 *. (Float.of_int self#radius) ** 2.0 method equals (other : 'self) = other#radius = self#radius end ;; #part 1 (new square 5)#equals (new square 5) ;; (new circle 10)#equals (new circle 7) ;; #part 2 type shape = < equals : shape -> bool; area : float > ;; (new square 5 :> shape) ;; #part 3 (object method area = 5 end) = (object method area = 5 end) ;; #part 4 type shape_repr = | Square of int | Circle of int ;; type shape = < repr : shape_repr; equals : shape -> bool; area : float > ;; class square w = object(self) method width = w method area = Float.of_int (self#width * self#width) method repr = Square self#width method equals (other : shape) = other#repr = self#repr end ;; ================================================ FILE: code/classes/binary_larger.ml ================================================ class square w = object(self) method width = w method area = Float.of_int (self#width * self#width) method larger other = self#area > other#area end ================================================ FILE: code/classes/binary_module.ml ================================================ module Shapes : sig type shape_repr type shape = < repr : shape_repr; equals : shape -> bool; area: float > class square : int -> object method width : int method area : float method repr : shape_repr method equals : shape -> bool end end = struct type shape_repr = | Square of int | Circle of int ... end ================================================ FILE: code/classes/build_doc.sh ================================================ corebuild doc.native ================================================ FILE: code/classes/citerator.cpp ================================================ // Abstract class definition in C++. template class Iterator { public: virtual ~Iterator() {} virtual T get() const = 0; virtual bool has_value() const = 0; virtual void next() = 0; }; ================================================ FILE: code/classes/class_types_stack.ml ================================================ module Stack = struct class ['a] stack init = object ... end type 'a t = 'a stack let make init = new stack init end (* part 1 *) module AbstractStack : sig type 'a t = < pop: 'a option; push: 'a -> unit > val make : unit -> 'a t end = Stack (* part 2 *) module VisibleStack : sig type 'a t = < pop: 'a option; push: 'a -> unit > class ['a] stack : object val mutable v : 'a list method pop : 'a option method push : 'a -> unit end val make : unit -> 'a t end = Stack ================================================ FILE: code/classes/doc.ml ================================================ type doc = | Heading of string | Paragraph of text_item list | Definition of string list_item list and text_item = | Raw of string | Bold of text_item list | Enumerate of int list_item list | Quote of doc and 'a list_item = { tag: 'a; text: text_item list } (* part 1 *) open Core.Std class ['a] folder = object(self) method doc acc = function | Heading _ -> acc | Paragraph text -> List.fold ~f:self#text_item ~init:acc text | Definition list -> List.fold ~f:self#list_item ~init:acc list method list_item: 'b. 'a -> 'b list_item -> 'a = fun acc {tag; text} -> List.fold ~f:self#text_item ~init:acc text method text_item acc = function | Raw _ -> acc | Bold text -> List.fold ~f:self#text_item ~init:acc text | Enumerate list -> List.fold ~f:self#list_item ~init:acc list | Quote doc -> self#doc acc doc end (* part 2 *) class counter = object inherit [int] folder as super method list_item acc li = acc method text_item acc ti = let acc = super#text_item acc ti in match ti with | Bold _ -> acc + 1 | _ -> acc end let count_doc = (new counter)#doc (* part 3 *) class ['a] folder2 = object(self) method doc acc = function | Heading str -> self#heading acc str | Paragraph text -> self#paragraph acc text | Definition list -> self#definition acc list method list_item: 'b. 'a -> 'b list_item -> 'a = fun acc {tag; text} -> List.fold ~f:self#text_item ~init:acc text method text_item acc = function | Raw str -> self#raw acc str | Bold text -> self#bold acc text | Enumerate list -> self#enumerate acc list | Quote doc -> self#quote acc doc method private heading acc str = acc method private paragraph acc text = List.fold ~f:self#text_item ~init:acc text method private definition acc list = List.fold ~f:self#list_item ~init:acc list method private raw acc str = acc method private bold acc text = List.fold ~f:self#text_item ~init:acc text method private enumerate acc list = List.fold ~f:self#list_item ~init:acc list method private quote acc doc = self#doc acc doc end let f : < doc : int -> doc -> int; list_item : 'a . int -> 'a list_item -> int; text_item : int -> text_item -> int > = new folder2 (* part 4 *) class counter_with_private_method = object inherit [int] folder2 as super method list_item acc li = acc method private bold acc txt = let acc = super#bold acc txt in acc + 1 end (* part 5 *) class counter_with_sig : object method doc : int -> doc -> int method list_item : int -> 'b list_item -> int method text_item : int -> text_item -> int end = object inherit [int] folder2 as super method list_item acc li = acc method private bold acc txt = let acc = super#bold acc txt in acc + 1 end ================================================ FILE: code/classes/initializer.topscript ================================================ class obj x = let () = printf "Creating obj %d\n" x in object val field = printf "Initializing field\n"; x end ;; let o = new obj 3 ;; ================================================ FILE: code/classes/istack.topscript ================================================ class istack = object val mutable v = [0; 2] method pop = match v with | hd :: tl -> v <- tl; Some hd | [] -> None method push hd = v <- hd :: v end ;; #part 1 let s = new istack ;; s#pop ;; s#push 5 ;; s#pop ;; - : int option = Some 5 #part 2 type istack = < pop: int option; push: int -> unit > ;; ================================================ FILE: code/classes/iter.topscript ================================================ type 'a iterator = < get : 'a; has_value : bool; next : unit > ;; #part 1 class ['a] list_iterator init = object val mutable current : 'a list = init method has_value = current <> [] method get = match current with | hd :: tl -> hd | [] -> raise (Invalid_argument "no value") method next = match current with | hd :: tl -> current <- tl | [] -> raise (Invalid_argument "no value") end ;; #part 2 class ['a] stack init = object val mutable v : 'a list = init method pop = match v with | hd :: tl -> v <- tl; Some hd | [] -> None method push hd = v <- hd :: v method iterator : 'a iterator = new list_iterator v end ;; #part 3 let s = new stack [] ;; s#push 5 ;; s#push 4 ;; let it = s#iterator ;; it#get ;; it#next ;; it#get ;; it#next ;; it#has_value ;; #part 4 class ['a] stack init = object val mutable v : 'a list = init method pop = match v with | hd :: tl -> v <- tl; Some hd | [] -> None method push hd = v <- hd :: v method iter f = List.iter ~f v end ;; #part 5 class ['a] stack init = object val mutable v : 'a list = init method pop = match v with | hd :: tl -> v <- tl; Some hd | [] -> None method push hd = v <- hd :: v method fold : 'b. ('b -> 'a -> 'b) -> 'b -> 'b = (fun f init -> List.fold ~f ~init v) end ;; ================================================ FILE: code/classes/stack.topscript ================================================ class ['a] stack init = object val mutable v : 'a list = init method pop = match v with | hd :: tl -> v <- tl; Some hd | [] -> None method push hd = v <- hd :: v end ;; #part 1 class ['a] stack init = object val mutable v = init method pop = match v with | hd :: tl -> v <- tl; Some hd | [] -> None method push hd = v <- hd :: v end ;; #part 2 class sstack init = object inherit [string] stack init method print = List.iter ~f:print_string v end ;; #part 3 class double_stack init = object inherit [int] stack init as super method push hd = super#push (hd * 2) end ;; ================================================ FILE: code/classes-async/build_shapes.sh ================================================ corebuild -pkg async_graphics shapes.native ================================================ FILE: code/classes-async/multiple_inheritance.ml ================================================ open Core.Std open Async.Std open Async_graphics class virtual shape x y = object(self) method virtual private contains: int -> int -> bool val mutable x: int = x method x = x val mutable y: int = y method y = y method on_click ?start ?stop f = on_click ?start ?stop (fun {mouse_x;mouse_y} -> if self#contains mouse_x mouse_y then f mouse_x mouse_y) method on_mousedown ?start ?stop f = on_mousedown ?start ?stop (fun {mouse_x;mouse_y} -> if self#contains mouse_x mouse_y then f mouse_x mouse_y) end class square w x y = object inherit shape x y val mutable width = w method width = width method draw = fill_rect x y width width method private contains x' y' = x <= x' && x' <= x + width && y <= y' && y' <= y + width end (* part 1 *) class square_outline w x y = object inherit square w x y method draw = draw_rect x y width width end ================================================ FILE: code/classes-async/multiple_inheritance_wrong.ml ================================================ open Core.Std open Async.Std open Async_graphics class virtual shape x y = object(self) method virtual private contains: int -> int -> bool val mutable x: int = x method x = x val mutable y: int = y method y = y method on_click ?start ?stop f = on_click ?start ?stop (fun {mouse_x;mouse_y} -> if self#contains mouse_x mouse_y then f mouse_x mouse_y) method on_mousedown ?start ?stop f = on_mousedown ?start ?stop (fun {mouse_x;mouse_y} -> if self#contains mouse_x mouse_y then f mouse_x mouse_y) end class square w x y = object inherit shape x y val mutable width = w method width = width method draw = fill_rect x y width width method private contains x' y' = x <= x' && x' <= x + width && y <= y' && y' <= y + width end (* part 1 *) class square_outline w x y = object method draw = draw_rect x y w w inherit square w x y end ================================================ FILE: code/classes-async/shapes.ml ================================================ open Core.Std open Async.Std open Async_graphics type drawable = < draw: unit > (* part 1 *) class virtual shape x y = object(self) method virtual private contains: int -> int -> bool val mutable x: int = x method x = x val mutable y: int = y method y = y method on_click ?start ?stop f = on_click ?start ?stop (fun ev -> if self#contains ev.mouse_x ev.mouse_y then f ev.mouse_x ev.mouse_y) method on_mousedown ?start ?stop f = on_mousedown ?start ?stop (fun ev -> if self#contains ev.mouse_x ev.mouse_y then f ev.mouse_x ev.mouse_y) end (* part 2 *) class square w x y = object inherit shape x y val mutable width = w method width = width method draw = fill_rect x y width width method private contains x' y' = x <= x' && x' <= x + width && y <= y' && y' <= y + width end class circle r x y = object inherit shape x y val mutable radius = r method radius = radius method draw = fill_circle x y radius method private contains x' y' = let dx = abs (x' - x) in let dy = abs (y' - y) in let dist = sqrt (Float.of_int ((dx * dx) + (dy * dy))) in dist <= (Float.of_int radius) end (* part 3 *) class growing_circle r x y = object(self) inherit circle r x y initializer self#on_click (fun _x _y -> radius <- radius * 2) end (* part 4 *) class virtual draggable = object(self) method virtual on_mousedown: ?start:unit Deferred.t -> ?stop:unit Deferred.t -> (int -> int -> unit) -> unit val virtual mutable x: int val virtual mutable y: int val mutable dragging = false method dragging = dragging initializer self#on_mousedown (fun mouse_x mouse_y -> let offset_x = x - mouse_x in let offset_y = y - mouse_y in let mouse_up = Ivar.create () in let stop = Ivar.read mouse_up in dragging <- true; on_mouseup ~stop (fun _ -> Ivar.fill mouse_up (); dragging <- false); on_mousemove ~stop (fun ev -> x <- ev.mouse_x + offset_x; y <- ev.mouse_y + offset_y)) end (* part 5 *) class small_square = object inherit square 20 40 40 inherit draggable end (* part 6 *) class virtual animated span = object(self) method virtual on_click: ?start:unit Deferred.t -> ?stop:unit Deferred.t -> (int -> int -> unit) -> unit val mutable updates: (int -> unit) list = [] val mutable step = 0 val mutable running = false method running = running method animate = step <- 0; running <- true; let stop = Clock.after span >>| fun () -> running <- false in Clock.every ~stop (Time.Span.of_sec (1.0 /. 24.0)) (fun () -> step <- step + 1; List.iter ~f:(fun f -> f step) updates ) initializer self#on_click (fun _x _y -> if not self#running then self#animate) end (* part 7 *) class my_circle = object inherit circle 20 50 50 inherit animated Time.Span.second initializer updates <- [fun _ -> x <- x + 5] end (* part 8 *) class virtual linear x' y' = object val virtual mutable updates: (int -> unit) list val virtual mutable x: int val virtual mutable y: int initializer let update _ = x <- x + x'; y <- y + y' in updates <- update :: updates end let pi = (atan 1.0) *. 4.0 class virtual harmonic offset x' y' = object val virtual mutable updates: (int -> unit) list val virtual mutable x: int val virtual mutable y: int initializer let update step = let m = sin (offset +. ((Float.of_int step) *. (pi /. 64.))) in let x' = Float.to_int (m *. Float.of_int x') in let y' = Float.to_int (m *. Float.of_int y') in x <- x + x'; y <- y + y' in updates <- update :: updates end (* part 9 *) class my_square x y = object inherit square 40 x y inherit draggable inherit animated (Time.Span.of_int_sec 5) inherit linear 5 0 inherit harmonic 0.0 7 ~-10 end let my_circle = object inherit circle 30 250 250 inherit animated (Time.Span.minute) inherit harmonic 0.0 10 0 inherit harmonic (pi /. 2.0) 0 10 end (* part 10 *) let main () = let shapes = [ (my_circle :> drawable); (new my_square 50 350 :> drawable); (new my_square 50 200 :> drawable); (new growing_circle 20 70 70 :> drawable); ] in let repaint () = clear_graph (); List.iter ~f:(fun s -> s#draw) shapes; synchronize () in open_graph ""; auto_synchronize false; Clock.every (Time.Span.of_sec (1.0 /. 24.0)) repaint let () = never_returns (Scheduler.go_main ~main ()) ================================================ FILE: code/classes-async/verbose_shapes.ml ================================================ open Core.Std open Async.Std open Async_graphics (* part 1 *) class square w x y = object(self) val mutable x: int = x method x = x val mutable y: int = y method y = y val mutable width = w method width = width method draw = fill_rect x y width width method private contains x' y' = x <= x' && x' <= x + width && y <= y' && y' <= y + width method on_click ?start ?stop f = on_click ?start ?stop (fun ev -> if self#contains ev.mouse_x ev.mouse_y then f ev.mouse_x ev.mouse_y) end (* part 2 *) class circle r x y = object(self) val mutable x: int = x method x = x val mutable y: int = y method y = y val mutable radius = r method radius = radius method draw = fill_circle x y radius method private contains x' y' = let dx = abs (x' - x) in let dy = abs (y' - y) in let dist = sqrt (Float.of_int ((dx * dx) + (dy * dy))) in dist <= (Float.of_int radius) method on_click ?start ?stop f = on_click ?start ?stop (fun ev -> if self#contains ev.mouse_x ev.mouse_y then f ev.mouse_x ev.mouse_y) end ================================================ FILE: code/command-line-parsing/_tags ================================================ true: short_paths ================================================ FILE: code/command-line-parsing/basic.topscript ================================================ Command.basic ;; ================================================ FILE: code/command-line-parsing/basic_md5.ml ================================================ open Core.Std let do_hash file = In_channel.with_file file ~f:(fun ic -> let open Cryptokit in hash_channel (Hash.md5 ()) ic |> transform_string (Hexa.encode ()) |> print_endline ) (* part 1 *) let spec = let open Command.Spec in empty +> anon ("filename" %: string) (* part 2 *) let command = Command.basic ~summary:"Generate an MD5 hash of the input data" ~readme:(fun () -> "More detailed information") spec (fun filename () -> do_hash filename) (* part 3 *) let () = Command.run ~version:"1.0" ~build_info:"RWO" command ================================================ FILE: code/command-line-parsing/basic_md5_as_filename.ml ================================================ open Core.Std let do_hash file () = In_channel.with_file file ~f:( fun ic -> let open Cryptokit in hash_channel (Hash.md5 ()) ic |> transform_string (Hexa.encode ()) |> print_endline ) (* part 1 *) let command = Command.basic ~summary:"Generate an MD5 hash of the input data" ~readme:(fun () -> "More detailed information") Command.Spec.(empty +> anon ("filename" %: file)) do_hash let () = Command.run ~version:"1.0" ~build_info:"RWO" command ================================================ FILE: code/command-line-parsing/basic_md5_sequence.ml ================================================ open Core.Std let do_hash filename ic = let open Cryptokit in hash_channel (Hash.md5 ()) ic |> transform_string (Hexa.encode ()) |> fun md5 -> printf "MD5 (%s) = %s\n" filename md5 let command = Command.basic ~summary:"Generate an MD5 hash of the input data" ~readme:(fun () -> "More detailed information") Command.Spec.(empty +> anon (sequence ("filename" %: file))) (fun files () -> match files with | [] -> do_hash "-" In_channel.stdin | _ -> List.iter files ~f:(fun file -> In_channel.with_file ~f:(do_hash file) file ) ) let () = Command.run ~version:"1.0" ~build_info:"RWO" command ================================================ FILE: code/command-line-parsing/basic_md5_succinct.ml ================================================ open Core.Std let do_hash file () = In_channel.with_file file ~f:(fun ic -> let open Cryptokit in hash_channel (Hash.md5 ()) ic |> transform_string (Hexa.encode ()) |> print_endline ) let command = Command.basic ~summary:"Generate an MD5 hash of the input data" ~readme:(fun () -> "More detailed information") Command.Spec.(empty +> anon ("filename" %: string)) do_hash let () = Command.run ~version:"1.0" ~build_info:"RWO" command ================================================ FILE: code/command-line-parsing/basic_md5_with_custom_arg.ml ================================================ open Core.Std let do_hash file () = In_channel.with_file file ~f:(fun ic -> let open Cryptokit in hash_channel (Hash.md5 ()) ic |> transform_string (Hexa.encode ()) |> print_endline ) let regular_file = Command.Spec.Arg_type.create (fun filename -> match Sys.is_file filename with | `Yes -> filename | `No | `Unknown -> eprintf "'%s' is not a regular file.\n%!" filename; exit 1 ) let command = Command.basic ~summary:"Generate an MD5 hash of the input data" ~readme:(fun () -> "More detailed information") Command.Spec.(empty +> anon ("filename" %: regular_file)) do_hash let () = Command.run ~version:"1.0" ~build_info:"RWO" command ================================================ FILE: code/command-line-parsing/basic_md5_with_default_file.ml ================================================ open Core.Std let get_inchan = function | "-" -> In_channel.stdin | filename -> In_channel.create ~binary:true filename let do_hash filename () = let open Cryptokit in get_inchan filename |> hash_channel (Hash.md5 ()) |> transform_string (Hexa.encode ()) |> print_endline let command = Command.basic ~summary:"Generate an MD5 hash of the input data" ~readme:(fun () -> "More detailed information") Command.Spec.( empty +> anon (maybe_with_default "-" ("filename" %: file)) ) do_hash let () = Command.run ~version:"1.0" ~build_info:"RWO" command ================================================ FILE: code/command-line-parsing/basic_md5_with_flags.ml ================================================ open Core.Std open Cryptokit let checksum_from_string buf = hash_string (Hash.md5 ()) buf |> transform_string (Hexa.encode ()) |> print_endline let checksum_from_file filename = let ic = match filename with | "-" -> In_channel.stdin | _ -> In_channel.create ~binary:true filename in hash_channel (Hash.md5 ()) ic |> transform_string (Hexa.encode ()) |> print_endline let command = Command.basic ~summary:"Generate an MD5 hash of the input data" Command.Spec.( empty +> flag "-s" (optional string) ~doc:"string Checksum the given string" +> flag "-t" no_arg ~doc:" run a built-in time trial" +> anon (maybe_with_default "-" ("filename" %: file)) ) (fun use_string trial filename () -> match trial with | true -> printf "Running time trial\n" | false -> begin match use_string with | Some buf -> checksum_from_string buf | None -> checksum_from_file filename end ) let () = Command.run command ================================================ FILE: code/command-line-parsing/basic_md5_with_opt_flags.ml ================================================ open Core.Std open Cryptokit let checksum_from_string buf = hash_string (Hash.md5 ()) buf |> transform_string (Hexa.encode ()) |> print_endline let checksum_from_file filename = let ic = match filename with | "-" -> In_channel.stdin | _ -> In_channel.create ~binary:true filename in hash_channel (Hash.md5 ()) ic |> transform_string (Hexa.encode ()) |> print_endline let command = Command.basic ~summary:"Generate an MD5 hash of the input data" Command.Spec.( empty +> flag "-s" (optional string) ~doc:"string Checksum the given string" +> flag "-v" (listed bool) ~doc:" verbosity level. Repeat multiple times for more info." +> flag "-t" no_arg ~doc:" run a built-in time trial" +> flag "-tlen" (optional_with_default 5 int) ~doc:"seconds length of time trial" +> anon (maybe_with_default "-" ("filename" %: file)) ) (fun use_string verbosity trial trial_secs filename () -> eprintf "Verbosity level: %d\n" (List.length verbosity); match trial with | true -> printf "Running time trial for %d seconds\n" trial_secs | false -> begin match use_string with | Some buf -> checksum_from_string buf | None -> checksum_from_file filename end ) let () = Command.run command ================================================ FILE: code/command-line-parsing/basic_md5_with_optional_file.ml ================================================ open Core.Std let get_inchan = function | None | Some "-" -> In_channel.stdin | Some filename -> In_channel.create ~binary:true filename let do_hash filename () = let open Cryptokit in get_inchan filename |> hash_channel (Hash.md5 ()) |> transform_string (Hexa.encode ()) |> print_endline let command = Command.basic ~summary:"Generate an MD5 hash of the input data" ~readme:(fun () -> "More detailed information") Command.Spec.(empty +> anon (maybe ("filename" %: file))) do_hash let () = Command.run ~version:"1.0" ~build_info:"RWO" command ================================================ FILE: code/command-line-parsing/basic_md5_with_optional_file_broken.ml ================================================ open Core.Std let do_hash file () = In_channel.with_file file ~f:( fun ic -> let open Cryptokit in hash_channel (Hash.md5 ()) ic |> transform_string (Hexa.encode ()) |> print_endline ) (* part 1 *) let command = Command.basic ~summary:"Generate an MD5 hash of the input data" ~readme:(fun () -> "More detailed information") Command.Spec.(empty +> anon (maybe ("filename" %: string))) do_hash let () = Command.run ~version:"1.0" ~build_info:"RWO" command ================================================ FILE: code/command-line-parsing/build_and_run_cal_add_interactive.rawsh ================================================ $ ocamlbuild -use-ocamlfind -tag thread -pkg core cal_add_interactive.native $ ./cal_add_interactive.native 2013-12-01 enter days: 35 2014-01-05 ================================================ FILE: code/command-line-parsing/build_basic_md5.sh ================================================ corebuild -pkg cryptokit basic_md5.native ================================================ FILE: code/command-line-parsing/build_basic_md5_as_filename.sh ================================================ corebuild -pkg cryptokit basic_md5_as_filename.native ================================================ FILE: code/command-line-parsing/build_basic_md5_sequence.sh ================================================ corebuild -pkg cryptokit basic_md5_sequence.native ================================================ FILE: code/command-line-parsing/build_basic_md5_with_custom_arg.sh ================================================ corebuild -pkg cryptokit basic_md5_with_custom_arg.native ================================================ FILE: code/command-line-parsing/build_basic_md5_with_default_file.sh ================================================ corebuild -pkg cryptokit basic_md5_with_default_file.native ================================================ FILE: code/command-line-parsing/build_basic_md5_with_flags.sh ================================================ corebuild -pkg cryptokit basic_md5_with_flags.native ================================================ FILE: code/command-line-parsing/build_basic_md5_with_opt_flags.sh ================================================ corebuild -pkg cryptokit basic_md5_with_opt_flags.native ================================================ FILE: code/command-line-parsing/build_basic_md5_with_optional_file.sh ================================================ corebuild -pkg cryptokit basic_md5_with_optional_file.native ================================================ FILE: code/command-line-parsing/build_basic_md5_with_optional_file_broken.errsh ================================================ corebuild -pkg cryptokit basic_md5_with_optional_file_broken.native ================================================ FILE: code/command-line-parsing/build_cal_add_days.sh ================================================ corebuild cal_add_days.native ================================================ FILE: code/command-line-parsing/build_cal_add_sub_days.sh ================================================ corebuild cal_add_sub_days.native ./cal_add_sub_days.native -help ================================================ FILE: code/command-line-parsing/build_cal_append.sh ================================================ corebuild cal_append.native ================================================ FILE: code/command-line-parsing/build_cal_append_broken.errsh ================================================ corebuild cal_append_broken.native ================================================ FILE: code/command-line-parsing/cal.cmd ================================================ function _jsautocom_96173 { export COMP_CWORD COMP_WORDS[0]=./cal_add_sub_days.native COMPREPLY=($("${COMP_WORDS[@]}")) } complete -F _jsautocom_96173 ./cal_add_sub_days.native ================================================ FILE: code/command-line-parsing/cal_add_days.ml ================================================ open Core.Std let add = Command.basic ~summary:"Add [days] to the [base] date and print day" Command.Spec.( empty +> anon ("base" %: date) +> anon ("days" %: int) ) (fun base span () -> Date.add_days base span |> Date.to_string |> print_endline ) let () = Command.run add ================================================ FILE: code/command-line-parsing/cal_add_interactive.ml ================================================ open Core.Std let add_days base span () = Date.add_days base span |> Date.to_string |> print_endline let add = Command.basic ~summary:"Add [days] to the [base] date and print day" Command.Spec.( step (fun m base days -> match days with | Some days -> m base days | None -> print_endline "enter days: "; read_int () |> m base ) +> anon ("base" %: date) +> anon (maybe ("days" %: int)) ) add_days let () = Command.run add ================================================ FILE: code/command-line-parsing/cal_add_labels.ml ================================================ open Core.Std let add_days ~base_date ~num_days () = Date.add_days base_date num_days |> Date.to_string |> print_endline let add = Command.basic ~summary:"Add [days] to the [base] date and print day" Command.Spec.( step (fun m base days -> m ~base_date:base ~num_days:days) +> anon ("base" %: date) +> anon ("days" %: int) ) add_days let () = Command.run add ================================================ FILE: code/command-line-parsing/cal_add_sub_days.ml ================================================ open Core.Std let add = Command.basic ~summary:"Add [days] to the [base] date" Command.Spec.( empty +> anon ("base" %: date) +> anon ("days" %: int) ) (fun base span () -> Date.add_days base span |> Date.to_string |> print_endline ) let diff = Command.basic ~summary:"Show days between [date1] and [date2]" Command.Spec.( empty +> anon ("date1" %: date) +> anon ("date2" %: date) ) (fun date1 date2 () -> Date.diff date1 date2 |> printf "%d days\n" ) let command = Command.group ~summary:"Manipulate dates" [ "add", add; "diff", diff ] let () = Command.run command ================================================ FILE: code/command-line-parsing/cal_append.ml ================================================ open Core.Std let add ~common = Command.basic ~summary:"Add [days] to the [base] date" Command.Spec.( empty +> anon ("base" %: date) +> anon ("days" %: int) ++ common ) (fun base span debug verbose () -> Date.add_days base span |> Date.to_string |> print_endline ) let diff ~common = Command.basic ~summary:"Show days between [date2] and [date1]" Command.Spec.( empty +> anon ("date1" %: date) +> anon ("date2" %: date) ++ common ) (fun date1 date2 debug verbose () -> Date.diff date1 date2 |> printf "%d days\n" ) (* part 1 *) let () = let common = Command.Spec.( empty +> flag "-d" (optional_with_default false bool) ~doc:" Debug mode" +> flag "-v" (optional_with_default false bool) ~doc:" Verbose output" ) in List.map ~f:(fun (name, cmd) -> (name, cmd ~common)) [ "add", add; "diff", diff ] |> Command.group ~summary:"Manipulate dates" |> Command.run ================================================ FILE: code/command-line-parsing/cal_append_broken.ml ================================================ open Core.Std let add ~common = Command.basic ~summary:"Add [days] to the [base] date" Command.Spec.( empty +> anon ("base" %: date) +> anon ("days" %: int) ++ common ) (fun base span debug verbose () -> Date.add_days base span |> Date.to_string |> print_endline ) let diff ~common = Command.basic ~summary:"Show days between [date2] and [date1]" Command.Spec.( empty +> anon ("date1" %: date) +> anon ("date2" %: date) ++ common ) (fun date1 date2 debug verbose () -> Date.diff date1 date2 |> printf "%d days\n" ) (* part 1 *) let () = let common = Command.Spec.( empty +> flag "-d" (optional_with_default false bool) ~doc:" Debug mode" ) in List.map ~f:(fun (name, cmd) -> (name, cmd ~common)) [ "add", add; "diff", diff ] |> Command.group ~summary:"Manipulate dates" |> Command.run ================================================ FILE: code/command-line-parsing/cal_completion.rawsh ================================================ $ env COMMAND_OUTPUT_INSTALLATION_BASH=1 ./cal_add_sub_days.native > cal.cmd $ . cal.cmd $ ./cal_add_sub_days.native add diff help version ================================================ FILE: code/command-line-parsing/command_types.topscript ================================================ Command.Spec.empty ;; Command.Spec.(empty +> anon ("foo" %: int)) ;; ================================================ FILE: code/command-line-parsing/get_basic_md5_help.errsh ================================================ ./basic_md5.native ================================================ FILE: code/command-line-parsing/get_basic_md5_version.sh ================================================ ./basic_md5.native -version ./basic_md5.native -build-info ================================================ FILE: code/command-line-parsing/group.topscript ================================================ Command.basic ;; Command.group ;; ================================================ FILE: code/command-line-parsing/md5_completion.sh ================================================ env COMMAND_OUTPUT_INSTALLATION_BASH=1 ./basic_md5_with_flags.native ================================================ FILE: code/command-line-parsing/opam.rawsh ================================================ $ opam config env $ opam remote list -k git $ opam install --help $ opam install cryptokit --verbose ================================================ FILE: code/command-line-parsing/run_basic_and_default_md5.sh ================================================ cat /etc/passwd | ./basic_md5_with_optional_file.native cat /etc/passwd | ./basic_md5_with_default_file.native ================================================ FILE: code/command-line-parsing/run_basic_md5.sh ================================================ ./basic_md5.native ./basic_md5.native ================================================ FILE: code/command-line-parsing/run_basic_md5_as_filename.errsh ================================================ ./basic_md5_as_filename.native nonexistent ================================================ FILE: code/command-line-parsing/run_basic_md5_flags_help.sh ================================================ ./basic_md5_with_flags.native -help ./basic_md5_with_flags.native -s "ocaml rocks" ================================================ FILE: code/command-line-parsing/run_basic_md5_with_custom_arg.errsh ================================================ ./basic_md5_with_custom_arg.native /etc/passwd ./basic_md5_with_custom_arg.native /dev/null ================================================ FILE: code/command-line-parsing/run_cal_add_sub_days.sh ================================================ ./cal_add_sub_days.native add 2012-12-25 40 ./cal_add_sub_days.native diff 2012-12-25 2012-11-01 ================================================ FILE: code/command-line-parsing/single_anon_filename.topscript ================================================ open Command.Spec ;; empty +> anon ("filename" %: string) ;; ================================================ FILE: code/command-line-parsing/step.topscript ================================================ open Command.Spec ;; step (fun m (base:Date.t) days -> match days with | Some days -> m base days | None -> print_endline "enter days: "; m base (read_int ())) ;; ================================================ FILE: code/corebuild ================================================ #!/bin/sh ocamlbuild \ -use-ocamlfind \ -classic-display \ -syntax camlp4o \ -pkg core,core_extended,async,textutils,core_bench \ -pkg sexplib.syntax,comparelib.syntax,fieldslib.syntax,variantslib.syntax \ -pkg bin_prot.syntax \ -tag thread \ -tag debug \ -cflags -short-paths \ -cflags "-w @A-4-33-41-42-43-34-44" \ -cflags -strict-sequence \ -cflags -principal \ $@ ================================================ FILE: code/ctypes/ctypes.mli ================================================ type 'a typ (* part 1 *) val void : unit typ val char : char typ val schar : int typ val short : int typ val int : int typ val long : long typ val llong : llong typ val nativeint : nativeint typ val int8_t : int typ val int16_t : int typ val int32_t : int32 typ val int64_t : int64 typ val uchar : uchar typ val uchar : uchar typ val uint8_t : uint8 typ val uint16_t : uint16 typ val uint32_t : uint32 typ val uint64_t : uint64 typ val size_t : size_t typ val ushort : ushort typ val uint : uint typ val ulong : ulong typ val ullong : ullong typ val float : float typ val double : float typ val complex32 : Complex.t typ val complex64 : Complex.t typ (* part 2 *) val view : read:('a -> 'b) -> write:('b -> 'a) -> 'a typ -> 'b typ (* part 3 *) val string_of_char_ptr : char ptr -> string val char_ptr_of_string : string -> char ptr (* part 4 *) val string : string.typ (* part 5 *) module Array : sig type 'a t = 'a array val get : 'a t -> int -> 'a val set : 'a t -> int -> 'a -> unit val of_list : 'a typ -> 'a list -> 'a t val to_list : 'a t -> 'a list val length : 'a t -> int val start : 'a t -> 'a ptr val from_ptr : 'a ptr -> int -> 'a t val make : 'a typ -> ?initial:'a -> int -> 'a t end ================================================ FILE: code/ctypes/ctypes_impl.ml ================================================ let string = view (char ptr) ~read:string_of_char_ptr ~write:char_ptr_of_string ================================================ FILE: code/error-handling/blow_up.ml ================================================ open Core.Std exception Empty_list let list_max = function | [] -> raise Empty_list | hd :: tl -> List.fold tl ~init:hd ~f:(Int.max) let () = printf "%d\n" (list_max [1;2;3]); printf "%d\n" (list_max []) ================================================ FILE: code/error-handling/build_blow_up.errsh ================================================ corebuild blow_up.byte ./blow_up.byte ================================================ FILE: code/error-handling/build_blow_up_notrace.errsh ================================================ corebuild blow_up.byte OCAMLRUNPARAM= ./blow_up.byte ================================================ FILE: code/error-handling/exn_cost.ml ================================================ open Core.Std open Core_bench.Std let simple_computation () = List.range 0 10 |> List.fold ~init:0 ~f:(fun sum x -> sum + x * x) |> ignore let simple_with_handler () = try simple_computation () with Exit -> () let end_with_exn () = try simple_computation (); raise Exit with Exit -> () let () = [ Bench.Test.create ~name:"simple computation" (fun () -> simple_computation ()); Bench.Test.create ~name:"simple computation w/handler" (fun () -> simple_with_handler ()); Bench.Test.create ~name:"end with exn" (fun () -> end_with_exn ()); ] |> Bench.make_command |> Command.run ================================================ FILE: code/error-handling/main.topscript ================================================ List.find;; #part 1 List.find [1;2;3] ~f:(fun x -> x >= 2) ;; List.find [1;2;3] ~f:(fun x -> x >= 10) ;; #part 2 let compute_bounds ~cmp list = let sorted = List.sort ~cmp list in match List.hd sorted, List.last sorted with | None,_ | _, None -> None | Some x, Some y -> Some (x,y) ;; #part 3 let find_mismatches table1 table2 = Hashtbl.fold table1 ~init:[] ~f:(fun ~key ~data mismatches -> match Hashtbl.find table2 key with | Some data' when data' <> data -> key :: mismatches | _ -> mismatches ) ;; #part 4 [ Ok 3; Error "abject failure"; Ok 4 ];; #part 5 Error.of_string "something went wrong";; #part 6 Error.of_thunk (fun () -> sprintf "something went wrong: %f" 32.3343);; #part 7 Error.create "Something failed a long time ago" Time.epoch Time.sexp_of_t;; #part 8 let custom_to_sexp = <:sexp_of>;; custom_to_sexp (3.5, ["a";"b";"c"], 6034);; #part 9 Error.create "Something went terribly wrong" (3.5, ["a";"b";"c"], 6034) <:sexp_of> ;; #part 10 Error.tag (Error.of_list [ Error.of_string "Your tires were slashed"; Error.of_string "Your windshield was smashed" ]) "over the weekend" ;; #part 11 let bind option f = match option with | None -> None | Some x -> f x ;; #part 12 let compute_bounds ~cmp list = let sorted = List.sort ~cmp list in Option.bind (List.hd sorted) (fun first -> Option.bind (List.last sorted) (fun last -> Some (first,last))) ;; #part 13 let compute_bounds ~cmp list = let open Option.Monad_infix in let sorted = List.sort ~cmp list in List.hd sorted >>= fun first -> List.last sorted >>= fun last -> Some (first,last) ;; #part 14 let compute_bounds ~cmp list = let sorted = List.sort ~cmp list in Option.both (List.hd sorted) (List.last sorted) ;; #part 15 3 / 0;; #part 16 List.map ~f:(fun x -> 100 / x) [1;3;0;4];; #part 17 List.map ~f:(fun x -> printf "%d\n%!" x; 100 / x) [1;3;0;4];; #part 18 exception Key_not_found of string;; raise (Key_not_found "a");; #part 19 let exceptions = [ Not_found; Division_by_zero; Key_not_found "b" ];; List.filter exceptions ~f:(function | Key_not_found _ | Not_found -> true | _ -> false);; #part 20 let rec find_exn alist key = match alist with | [] -> raise (Key_not_found key) | (key',data) :: tl -> if key = key' then data else find_exn tl key ;; let alist = [("a",1); ("b",2)];; find_exn alist "a";; find_exn alist "c";; #part 21 raise;; #part 22 let rec forever () = forever ();; #part 23 exception Wrong_date of Date.t;; Wrong_date (Date.of_string "2011-02-23");; #part 24 exception Wrong_date of Date.t with sexp;; Wrong_date (Date.of_string "2011-02-23");; #part 25 let failwith msg = raise (Failure msg);; #part 26 let merge_lists xs ys ~f = if List.length xs <> List.length ys then None else let rec loop xs ys = match xs,ys with | [],[] -> [] | x::xs, y::ys -> f x y :: loop xs ys | _ -> assert false in Some (loop xs ys) ;; merge_lists [1;2;3] [-1;1;2] ~f:(+);; merge_lists [1;2;3] [-1;1] ~f:(+);; #part 27 let merge_lists xs ys ~f = let rec loop xs ys = match xs,ys with | [],[] -> [] | x::xs, y::ys -> f x y :: loop xs ys | _ -> assert false in loop xs ys ;; merge_lists [1;2;3] [-1] ~f:(+);; #part 28 let reminders_of_sexp = <:of_sexp<(Time.t * string) list>> ;; let load_reminders filename = let inc = In_channel.create filename in let reminders = reminders_of_sexp (Sexp.input_sexp inc) in In_channel.close inc; reminders ;; #part 29 let load_reminders filename = let inc = In_channel.create filename in protect ~f:(fun () -> reminders_of_sexp (Sexp.input_sexp inc)) ~finally:(fun () -> In_channel.close inc) ;; #part 30 let reminders_of_sexp filename = In_channel.with_file filename ~f:(fun inc -> reminders_of_sexp (Sexp.input_sexp inc)) ;; #part 31 let lookup_weight ~compute_weight alist key = try let data = List.Assoc.find_exn alist key in compute_weight data with Not_found -> 0. ;; #part 32 lookup_weight ~compute_weight:(fun _ -> raise Not_found) ["a",3; "b",4] "a" ;; #part 33 let lookup_weight ~compute_weight alist key = match try Some (List.Assoc.find_exn alist key) with _ -> None with | None -> 0. | Some data -> compute_weight data ;; #part 34 let lookup_weight ~compute_weight alist key = match List.Assoc.find alist key with | None -> 0. | Some data -> compute_weight data ;; #part 35 let find alist key = Option.try_with (fun () -> find_exn alist key) ;; find ["a",1; "b",2] "c";; find ["a",1; "b",2] "b";; #part 36 let find alist key = Or_error.try_with (fun () -> find_exn alist key) ;; find ["a",1; "b",2] "c";; #part 37 Or_error.ok_exn (find ["a",1; "b",2] "b");; Or_error.ok_exn (find ["a",1; "b",2] "c");; ================================================ FILE: code/error-handling/result.ml ================================================ module Result : sig type ('a,'b) t = | Ok of 'a | Error of 'b end ================================================ FILE: code/error-handling/result.mli ================================================ module Result : sig type ('a,'b) t = | Ok of 'a | Error of 'b end ================================================ FILE: code/error-handling/run_exn_cost.sh ================================================ corebuild -pkg core_bench exn_cost.native ./exn_cost.native -ascii cycles ================================================ FILE: code/error-handling/run_exn_cost_notrace.sh ================================================ OCAMLRUNPARAM= ./exn_cost.native -ascii cycles ================================================ FILE: code/error-handling/sexpr.scm ================================================ (This (is an) (s expression)) ================================================ FILE: code/error-handling/try_with.syntax ================================================ try with | -> | -> ... ================================================ FILE: code/exec_script.sh ================================================ #!/usr/bin/env bash cd $(dirname $1) while IFS= read -r line ; do echo "$ $line" bash -c "$line" done < $(basename $1) ================================================ FILE: code/exec_topscript.sh ================================================ #!/usr/bin/env bash topscript=`pwd`/../scripts/_build/run_core_toplevel.byte cd $(dirname $1) $(topscript) $(basename $1) ================================================ FILE: code/fcm/build_query_handler.sh ================================================ corebuild query_handler.byte ================================================ FILE: code/fcm/build_query_handler_loader.sh ================================================ corebuild query_handler_loader.byte ================================================ FILE: code/fcm/fcm.syntax ================================================ (module : ) ================================================ FILE: code/fcm/loader_cli1.rawsh ================================================ $ ./query_handler_loader.byte >>> (loader known_services) (ls unique) >>> (loader active_services) (loader) ================================================ FILE: code/fcm/loader_cli2.rawsh ================================================ >>> (ls .) Could not find matching handler: ls ================================================ FILE: code/fcm/loader_cli3.rawsh ================================================ >>> (loader (load ls /var)) () >>> (ls /var) (agentx at audit backups db empty folders jabberd lib log mail msgs named netboot pgsql_socket_alt root rpc run rwho spool tmp vm yp) >>> (loader (unload ls)) () >>> (ls /var) Could not find matching handler: ls ================================================ FILE: code/fcm/loader_cli4.rawsh ================================================ >>> (loader (unload loader)) It's unwise to unload yourself ================================================ FILE: code/fcm/main.topscript ================================================ module type X_int = sig val x : int end;; #part 1 module Three : X_int = struct let x = 3 end;; Three.x;; #part 2 let three = (module Three : X_int);; #part 3 module Four = struct let x = 4 end;; let numbers = [ three; (module Four) ];; #part 4 let numbers = [three; (module struct let x = 4 end)];; #part 5 module New_three = (val three : X_int) ;; New_three.x;; #part 6 module type Y_int = X_int;; let five = (module struct let x = 5 end : Y_int);; [three; five];; #part 7 [three; (module (val five))];; #part 8 let to_int m = let module M = (val m : X_int) in M.x ;; let plus m1 m2 = (module struct let x = to_int m1 + to_int m2 end : X_int) ;; #part 9 let six = plus three three;; to_int (List.fold ~init:six ~f:plus [three;three]);; #part 10 let to_int (module M : X_int) = M.x ;; #part 11 module type Bumpable = sig type t val bump : t -> t end;; #part 12 module Int_bumper = struct type t = int let bump n = n + 1 end;; module Float_bumper = struct type t = float let bump n = n +. 1. end;; #part 13 let int_bumper = (module Int_bumper : Bumpable);; #part 14 let (module Bumpable) = int_bumper in Bumpable.bump 3;; #part 15 let int_bumper = (module Int_bumper : Bumpable with type t = int);; let float_bumper = (module Float_bumper : Bumpable with type t = float);; #part 16 let (module Bumpable) = int_bumper in Bumpable.bump 3;; let (module Bumpable) = float_bumper in Bumpable.bump 3.5;; #part 17 let bump_list (type a) (module B : Bumpable with type t = a) (l: a list) = List.map ~f:B.bump l ;; #part 18 bump_list int_bumper [1;2;3];; bump_list float_bumper [1.5;2.5;3.5];; #part 19 let wrap_in_list (type a) (x:a) = [x];; #part 20 let wrap_int_in_list (type a) (x:a) = x + x;; #part 21 module type Comparable = sig type t val compare : t -> t -> int end ;; let create_comparable (type a) compare = (module struct type t = a let compare = compare end : Comparable with type t = a) ;; create_comparable Int.compare;; create_comparable Float.compare;; ================================================ FILE: code/fcm/pack.syntax ================================================ (module : ) ================================================ FILE: code/fcm/query-syntax.scm ================================================ (query-name query) ================================================ FILE: code/fcm/query_example.rawscript ================================================ $ ./query_handler.byte >>> (unique ()) 0 >>> (unique ()) 1 >>> (ls .) (agentx at audit backups db empty folders jabberd lib log mail msgs named netboot pgsql_socket_alt root rpc run rwho spool tmp vm yp) >>> (ls vm) (sleepimage swapfile0 swapfile1 swapfile2 swapfile3 swapfile4 swapfile5 swapfile6) ================================================ FILE: code/fcm/query_handler.ml ================================================ open Core.Std open Query_handler_core (* part 1 *) let () = cli (build_dispatch_table [unique_instance; list_dir_instance]) ================================================ FILE: code/fcm/query_handler.topscript ================================================ module type Query_handler = sig (** Configuration for a query handler. Note that this can be converted to and from an s-expression *) type config with sexp (** The name of the query-handling service *) val name : string (** The state of the query handler *) type t (** Creates a new query handler from a config *) val create : config -> t (** Evaluate a given query, where both input and output are s-expressions *) val eval : t -> Sexp.t -> Sexp.t Or_error.t end;; #part 1 module type M = sig type t with sexp end;; #part 2 type u = { a: int; b: float } with sexp;; sexp_of_u {a=3;b=7.};; u_of_sexp (Sexp.of_string "((a 43) (b 3.4))");; #part 3 module Unique = struct type config = int with sexp type t = { mutable next_id: int } let name = "unique" let create start_at = { next_id = start_at } let eval t sexp = match Or_error.try_with (fun () -> unit_of_sexp sexp) with | Error _ as err -> err | Ok () -> let response = Ok (Int.sexp_of_t t.next_id) in t.next_id <- t.next_id + 1; response end;; #part 4 let unique = Unique.create 0;; Unique.eval unique Sexp.unit;; Unique.eval unique Sexp.unit;; #part 5 module List_dir = struct type config = string with sexp type t = { cwd: string } (** [is_abs p] Returns true if [p] is an absolute path *) let is_abs p = String.length p > 0 && p.[0] = '/' let name = "ls" let create cwd = { cwd } let eval t sexp = match Or_error.try_with (fun () -> string_of_sexp sexp) with | Error _ as err -> err | Ok dir -> let dir = if is_abs dir then dir else Filename.concat t.cwd dir in Ok (Array.sexp_of_t String.sexp_of_t (Sys.readdir dir)) end;; #part 6 let list_dir = List_dir.create "/var";; List_dir.eval list_dir (sexp_of_string ".");; List_dir.eval list_dir (sexp_of_string "yp");; #part 7 module type Query_handler_instance = sig module Query_handler : Query_handler val this : Query_handler.t end;; #part 8 let unique_instance = (module struct module Query_handler = Unique let this = Unique.create 0 end : Query_handler_instance);; #part 9 let build_instance (type a) (module Q : Query_handler with type config = a) config = (module struct module Query_handler = Q let this = Q.create config end : Query_handler_instance) ;; #part 10 let unique_instance = build_instance (module Unique) 0;; let list_dir_instance = build_instance (module List_dir) "/var";; #part 11 let build_dispatch_table handlers = let table = String.Table.create () in List.iter handlers ~f:(fun ((module I : Query_handler_instance) as instance) -> Hashtbl.replace table ~key:I.Query_handler.name ~data:instance); table ;; #part 12 let dispatch dispatch_table name_and_query = match name_and_query with | Sexp.List [Sexp.Atom name; query] -> begin match Hashtbl.find dispatch_table name with | None -> Or_error.error "Could not find matching handler" name String.sexp_of_t | Some (module I : Query_handler_instance) -> I.Query_handler.eval I.this query end | _ -> Or_error.error_string "malformed query" ;; #part 13 let rec cli dispatch_table = printf ">>> %!"; let result = match In_channel.input_line stdin with | None -> `Stop | Some line -> match Or_error.try_with (fun () -> Sexp.of_string line) with | Error e -> `Continue (Error.to_string_hum e) | Ok (Sexp.Atom "quit") -> `Stop | Ok query -> begin match dispatch dispatch_table query with | Error e -> `Continue (Error.to_string_hum e) | Ok s -> `Continue (Sexp.to_string_hum s) end; in match result with | `Stop -> () | `Continue msg -> printf "%s\n%!" msg; cli dispatch_table ;; #part 14 type query_handler_instance = { name : string ; eval : Sexp.t -> Sexp.t Or_error.t } type query_handler = Sexp.t -> query_handler_instance ;; #part 15 let unique_handler config_sexp = let config = Unique.config_of_sexp config_sexp in let unique = Unique.create config in { name = Unique.name ; eval = (fun config -> Unique.eval unique config) } ;; ================================================ FILE: code/fcm/query_handler_core.ml ================================================ open Core.Std module type Query_handler = sig (** Configuration for a query handler. Note that this can be converted to and from an s-expression *) type config with sexp (** The name of the query-handling service *) val name : string (** The state of the query handler *) type t (** Create a new query handler from a config *) val create : config -> t (** Evaluate a given query, where both input and output are s-expressions *) val eval : t -> Sexp.t -> Sexp.t Or_error.t end module Unique = struct type config = int with sexp type t = { mutable next_id: int } let name = "unique" let create start_at = { next_id = start_at } let eval t sexp = match Or_error.try_with (fun () -> unit_of_sexp sexp) with | Error _ as err -> err | Ok () -> let response = Ok (Int.sexp_of_t t.next_id) in t.next_id <- t.next_id + 1; response end module List_dir = struct type config = string with sexp type t = { cwd: string } (** [is_abs p] Returns true if [p] is an absolute path *) let is_abs p = String.length p > 0 && p.[0] = '/' let name = "ls" let create cwd = { cwd } let eval t sexp = match Or_error.try_with (fun () -> string_of_sexp sexp) with | Error _ as err -> err | Ok dir -> let dir = if is_abs dir then dir else Filename.concat t.cwd dir in Ok (Array.sexp_of_t String.sexp_of_t (Sys.readdir dir)) end module type Query_handler_instance = sig module Query_handler : Query_handler val this : Query_handler.t end let build_instance (type a) (module Q : Query_handler with type config = a) config = (module struct module Query_handler = Q let this = Q.create config end : Query_handler_instance) let build_dispatch_table handlers = let table = String.Table.create () in List.iter handlers ~f:(fun ((module I : Query_handler_instance) as instance) -> Hashtbl.replace table ~key:I.Query_handler.name ~data:instance); table let dispatch dispatch_table name_and_query = match name_and_query with | Sexp.List [Sexp.Atom name; query] -> begin match Hashtbl.find dispatch_table name with | None -> Or_error.error "Could not find matching handler" name String.sexp_of_t | Some (module I : Query_handler_instance) -> I.Query_handler.eval I.this query end | _ -> Or_error.error_string "malformed query" let rec cli dispatch_table = printf ">>> %!"; let result = match In_channel.input_line stdin with | None -> `Stop | Some line -> match Or_error.try_with (fun () -> Sexp.of_string line) with | Error e -> `Continue (Error.to_string_hum e) | Ok (Sexp.Atom "quit") -> `Stop | Ok query -> begin match dispatch dispatch_table query with | Error e -> `Continue (Error.to_string_hum e) | Ok s -> `Continue (Sexp.to_string_hum s) end; in match result with | `Stop -> () | `Continue msg -> printf "%s\n%!" msg; cli dispatch_table let unique_instance = build_instance (module Unique) 0;; let list_dir_instance = build_instance (module List_dir) "/var";; (* part 1 *) module Loader = struct type config = (module Query_handler) list sexp_opaque with sexp type t = { known : (module Query_handler) String.Table.t ; active : (module Query_handler_instance) String.Table.t } let name = "loader" (* part 2 *) let create known_list = let active = String.Table.create () in let known = String.Table.create () in List.iter known_list ~f:(fun ((module Q : Query_handler) as q) -> Hashtbl.replace known ~key:Q.name ~data:q); { known; active } (* part 3 *) let load t handler_name config = if Hashtbl.mem t.active handler_name then Or_error.error "Can't re-register an active handler" handler_name String.sexp_of_t else match Hashtbl.find t.known handler_name with | None -> Or_error.error "Unknown handler" handler_name String.sexp_of_t | Some (module Q : Query_handler) -> let instance = (module struct module Query_handler = Q let this = Q.create (Q.config_of_sexp config) end : Query_handler_instance) in Hashtbl.replace t.active ~key:handler_name ~data:instance; Ok Sexp.unit (* part 4 *) let unload t handler_name = if not (Hashtbl.mem t.active handler_name) then Or_error.error "Handler not active" handler_name String.sexp_of_t else if handler_name = name then Or_error.error_string "It's unwise to unload yourself" else ( Hashtbl.remove t.active handler_name; Ok Sexp.unit ) (* part 5 *) type request = | Load of string * Sexp.t | Unload of string | Known_services | Active_services with sexp (* part 6 *) let eval t sexp = match Or_error.try_with (fun () -> request_of_sexp sexp) with | Error _ as err -> err | Ok resp -> match resp with | Load (name,config) -> load t name config | Unload name -> unload t name | Known_services -> Ok (<:sexp_of> (Hashtbl.keys t.known)) | Active_services -> Ok (<:sexp_of> (Hashtbl.keys t.active)) end ================================================ FILE: code/fcm/query_handler_loader.ml ================================================ open Core.Std open Query_handler_core (* part 1 *) let () = let loader = Loader.create [(module Unique); (module List_dir)] in let loader_instance = (module struct module Query_handler = Loader let this = loader end : Query_handler_instance) in Hashtbl.replace loader.Loader.active ~key:Loader.name ~data:loader_instance; cli loader.Loader.active ================================================ FILE: code/fcm/unpack.syntax ================================================ (val : ) ================================================ FILE: code/ffi/build_datetime.sh ================================================ corebuild -pkg ctypes.foreign datetime.native ./datetime.native ./datetime.native -a ================================================ FILE: code/ffi/build_hello.sh ================================================ corebuild -pkg ctypes.foreign -lflags -cclib,-lncurses hello.native ================================================ FILE: code/ffi/build_qsort.sh ================================================ corebuild -pkg ctypes.foreign qsort.native cat input.txt ./qsort.native < input.txt corebuild -pkg ctypes.foreign qsort.inferred.mli cp _build/qsort.inferred.mli qsort.mli ================================================ FILE: code/ffi/datetime.ml ================================================ open Core.Std open Ctypes open PosixTypes open Foreign let time = foreign "time" (ptr time_t @-> returning time_t) let difftime = foreign "difftime" (time_t @-> time_t @-> returning double) let ctime = foreign "ctime" (ptr time_t @-> returning string) type timeval let timeval : timeval structure typ = structure "timeval" let tv_sec = timeval *:* long let tv_usec = timeval *:* long let () = seal timeval type timezone let timezone : timezone structure typ = structure "timezone" let gettimeofday = foreign "gettimeofday" ~check_errno:true (ptr timeval @-> ptr timezone @-> returning int) let time' () = time (from_voidp time_t null) let gettimeofday' () = let tv = make timeval in ignore(gettimeofday (addr tv) (from_voidp timezone null)); let secs = Signed.Long.(to_int (getf tv tv_sec)) in let usecs = Signed.Long.(to_int (getf tv tv_usec)) in Pervasives.(float secs +. float usecs /. 1_000_000.) let float_time () = printf "%f%!\n" (gettimeofday' ()) let ascii_time () = let t_ptr = allocate time_t (time' ()) in printf "%s%!" (ctime t_ptr) let () = let open Command in basic ~summary:"Display the current time in various formats" Spec.(empty +> flag "-a" no_arg ~doc:" Human-readable output format") (fun human -> if human then ascii_time else float_time) |> Command.run ================================================ FILE: code/ffi/hello.ml ================================================ open Ncurses let () = let main_window = initscr () in ignore(cbreak ()); let small_window = newwin 10 10 5 5 in mvwaddstr main_window 1 2 "Hello"; mvwaddstr small_window 2 2 "World"; box small_window '\000' '\000'; refresh (); Unix.sleep 1; wrefresh small_window; Unix.sleep 5; endwin () ================================================ FILE: code/ffi/infer_ncurses.sh ================================================ corebuild -pkg ctypes.foreign ncurses.inferred.mli cp _build/ncurses.inferred.mli . ================================================ FILE: code/ffi/input.txt ================================================ 5 3 2 1 4 ================================================ FILE: code/ffi/install.rawsh ================================================ $ brew install libffi # for MacOS X users $ opam install ctypes $ utop # require "ctypes.foreign" ;; ================================================ FILE: code/ffi/ncurses.h ================================================ typedef struct _win_st WINDOW; typedef unsigned int chtype; WINDOW *initscr (void); WINDOW *newwin (int, int, int, int); void endwin (void); void refresh (void); void wrefresh (WINDOW *); void addstr (const char *); int mvwaddch (WINDOW *, int, int, const chtype); void mvwaddstr (WINDOW *, int, int, char *); void box (WINDOW *, chtype, chtype); int cbreak (void); ================================================ FILE: code/ffi/ncurses.inferred.mli ================================================ type window = unit Ctypes.ptr val window : window Ctypes.typ val initscr : unit -> window val endwin : unit -> unit val refresh : unit -> unit val wrefresh : window -> unit val newwin : int -> int -> int -> int -> window val mvwaddch : window -> int -> int -> char -> unit val addstr : string -> unit val mvwaddstr : window -> int -> int -> string -> unit val box : window -> int -> int -> unit val cbreak : unit -> unit ================================================ FILE: code/ffi/ncurses.ml ================================================ open Ctypes type window = unit ptr let window : window typ = ptr void (* part 1 *) open Foreign let initscr = foreign "initscr" (void @-> returning window) (* part 2 *) let newwin = foreign "newwin" (int @-> int @-> int @-> int @-> returning window) let endwin = foreign "endwin" (void @-> returning void) let refresh = foreign "refresh" (void @-> returning void) let wrefresh = foreign "wrefresh" (window @-> returning void) let addstr = foreign "addstr" (string @-> returning void) let mvwaddch = foreign "mvwaddch" (window @-> int @-> int @-> char @-> returning void) let mvwaddstr = foreign "mvwaddstr" (window @-> int @-> int @-> string @-> returning void) let box = foreign "box" (window @-> char @-> char @-> returning void) let cbreak = foreign "cbreak" (void @-> returning int) ================================================ FILE: code/ffi/ncurses.mli ================================================ type window val window : window Ctypes.typ val initscr : unit -> window val endwin : unit -> unit val refresh : unit -> unit val wrefresh : window -> unit val newwin : int -> int -> int -> int -> window val mvwaddch : window -> int -> int -> char -> unit val addstr : string -> unit val mvwaddstr : window -> int -> int -> string -> unit val box : window -> char -> char -> unit val cbreak : unit -> int ================================================ FILE: code/ffi/posix.topscript ================================================ #require "ctypes.foreign" ;; #require "ctypes.top" ;; open Ctypes ;; open PosixTypes ;; open Foreign ;; let time = foreign "time" (ptr time_t @-> returning time_t) ;; #part 1 let cur_time = time (from_voidp time_t null) ;; #part 2 let time' () = time (from_voidp time_t null) ;; #part 3 let difftime = foreign "difftime" (time_t @-> time_t @-> returning double) ;; let t1 = time' () in Unix.sleep 2; let t2 = time' () in difftime t2 t1 ;; #part 4 let ctime = foreign "ctime" (ptr time_t @-> returning string) ;; #part 5 ctime (time' ()) ;; #part 6 let t_ptr = allocate time_t (time' ()) ;; #part 7 ctime t_ptr ;; #part 8 type timeval ;; let timeval : timeval structure typ = structure "timeval" ;; #part 9 let tv_sec = field timeval "tv_sec" long ;; let tv_usec = field timeval "tv_usec" long ;; seal timeval ;; #part 10 type timezone ;; let timezone : timezone structure typ = structure "timezone" ;; #part 11 let gettimeofday = foreign "gettimeofday" (ptr timeval @-> ptr timezone @-> returning_checking_errno int) ;; #part 12 let gettimeofday' () = let tv = make timeval in ignore(gettimeofday (addr tv) (from_voidp timezone null)); let secs = Signed.Long.(to_int (getf tv tv_sec)) in let usecs = Signed.Long.(to_int (getf tv tv_usec)) in Pervasives.(float secs +. float usecs /. 1000000.0) ;; gettimeofday' () ;; ================================================ FILE: code/ffi/posix_headers.h ================================================ time_t time(time_t *); double difftime(time_t, time_t); char *ctime(const time_t *timep); ================================================ FILE: code/ffi/qsort.h ================================================ void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)); ================================================ FILE: code/ffi/qsort.ml ================================================ open Core.Std open Ctypes open PosixTypes open Foreign let compare_t = ptr void @-> ptr void @-> returning int let qsort = foreign "qsort" (ptr void @-> size_t @-> size_t @-> funptr compare_t @-> returning void) let qsort' cmp arr = let open Unsigned.Size_t in let ty = Array.element_type arr in let len = of_int (Array.length arr) in let elsize = of_int (sizeof ty) in let start = to_voidp (Array.start arr) in let compare l r = cmp (!@ (from_voidp ty l)) (!@ (from_voidp ty r)) in qsort start len elsize compare; arr let sort_stdin () = In_channel.input_lines stdin |> List.map ~f:int_of_string |> Array.of_list int |> qsort' Int.compare |> Array.to_list |> List.iter ~f:(fun a -> printf "%d\n" a) let () = Command.basic ~summary:"Sort integers on standard input" Command.Spec.empty sort_stdin |> Command.run ================================================ FILE: code/ffi/qsort.mli ================================================ val compare_t : (unit Ctypes.ptr -> unit Ctypes.ptr -> int) Ctypes.fn val qsort : unit Ctypes.ptr -> PosixTypes.size_t -> PosixTypes.size_t -> (unit Ctypes.ptr -> unit Ctypes.ptr -> int) -> unit val qsort' : ('a -> 'a -> int) -> 'a Ctypes.array -> 'a Ctypes.array val sort_stdin : unit -> unit ================================================ FILE: code/ffi/qsort.topscript ================================================ #require "ctypes.foreign" ;; open Ctypes ;; open PosixTypes ;; open Foreign ;; let compare_t = ptr void @-> ptr void @-> returning int ;; let qsort = foreign "qsort" (ptr void @-> size_t @-> size_t @-> funptr compare_t @-> returning void) ;; ================================================ FILE: code/ffi/qsort_typedef.h ================================================ typedef int(compare_t)(const void *, const void *); void qsort(void *base, size_t nmemb, size_t size, compare_t *); ================================================ FILE: code/ffi/return_c_frag.c ================================================ uncurried_C(3, 4); ================================================ FILE: code/ffi/return_c_frag.h ================================================ int uncurried_C(int, int); ================================================ FILE: code/ffi/return_c_uncurried.c ================================================ /* A function that accepts an int, and returns a function pointer that accepts a second int and returns an int. */ typedef int (function_t)(int); function_t *curried_C(int); /* supply both arguments */ curried_C(3)(4); /* supply one argument at a time */ function_t *f = curried_C(3); f(4); ================================================ FILE: code/ffi/return_frag.ml ================================================ (* correct types *) val time: ptr time_t @-> returning time_t val difftime: time_t @-> time_t @-> returning double (* part 1 *) (* incorrect types *) val time: ptr time_t @-> time_t val difftime: time_t @-> time_t @-> double (* part 2 *) val curried : int -> int -> int (* part 3 *) val curried : int -> (int -> int) ================================================ FILE: code/ffi/timeval_headers.h ================================================ struct timeval { long tv_sec; long tv_usec; }; int gettimeofday(struct timeval *, struct timezone *tv); ================================================ FILE: code/files-modules-and-programs/abstract_username.ml ================================================ open Core.Std module Username : sig type t val of_string : string -> t val to_string : t -> string end = struct type t = string let of_string x = x let to_string x = x end ================================================ FILE: code/files-modules-and-programs/build_session_info.errsh ================================================ corebuild session_info.native ================================================ FILE: code/files-modules-and-programs/common.ml ================================================ module List = Ext_list ================================================ FILE: code/files-modules-and-programs/confusing_username_and_host.ml ================================================ open Core.Std module type ID = sig type t val of_string : string -> t val to_string : t -> string end module String_id = struct type t = string let of_string x = x let to_string x = x end module Username : ID = String_id module Hostname : ID = String_id type session_info = { user: Username.t; host: Hostname.t; when_started: Time.t; } let sessions_have_same_user s1 s2 = s1.user = s2.host ================================================ FILE: code/files-modules-and-programs/ext_list.ml ================================================ open Core.Std (* The new function we're going to add *) let rec intersperse list el = match list with | [] | [ _ ] -> list | x :: y :: tl -> x :: el :: intersperse (y::tl) el (* The remainder of the list module *) include List ================================================ FILE: code/files-modules-and-programs/ext_list.mli ================================================ open Core.Std (* Include the interface of the list module from Core *) include (module type of List) (* Signature of function we're adding *) val intersperse : 'a list -> 'a -> 'a list ================================================ FILE: code/files-modules-and-programs/freq.ml ================================================ open Core.Std let build_counts () = In_channel.fold_lines stdin ~init:[] ~f:(fun counts line -> let count = match List.Assoc.find counts line with | None -> 0 | Some x -> x in List.Assoc.add counts line (count + 1) ) let () = build_counts () |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y) |> (fun l -> List.take l 10) |> List.iter ~f:(fun (line,count) -> printf "%3d: %s\n" count line) ================================================ FILE: code/files-modules-and-programs/intro.topscript ================================================ let assoc = [("one", 1); ("two",2); ("three",3)] ;; List.Assoc.find assoc "two" ;; List.Assoc.add assoc "four" 4 (* add a new key *) ;; List.Assoc.add assoc "two" 4 (* overwrite an existing key *) ;; ================================================ FILE: code/files-modules-and-programs/main.topscript ================================================ module M = struct let foo = 3 end;; foo;; open M;; foo;; #part 1 let average x y = let open Int64 in x + y / of_int 2;; #part 2 let average x y = Int64.(x + y / of_int 2);; #part 3 module Interval = struct type t = | Interval of int * int | Empty let create low high = if high < low then Empty else Interval (low,high) end;; #part 4 module Extended_interval = struct include Interval let contains t x = match t with | Empty -> false | Interval (low,high) -> x >= low && x <= high end;; Extended_interval.contains (Extended_interval.create 3 10) 4;; #part 5 module Extended_interval = struct open Interval let contains t x = match t with | Empty -> false | Interval (low,high) -> x >= low && x <= high end;; Extended_interval.contains (Extended_interval.create 3 10) 4;; ================================================ FILE: code/files-modules-and-programs/module.syntax ================================================ module : = ================================================ FILE: code/files-modules-and-programs/session_info.ml ================================================ open Core.Std module type ID = sig type t val of_string : string -> t val to_string : t -> string end module String_id = struct type t = string let of_string x = x let to_string x = x end module Username : ID = String_id module Hostname : ID = String_id type session_info = { user: Username.t; host: Hostname.t; when_started: Time.t; } let sessions_have_same_user s1 s2 = s1.user = s2.host ================================================ FILE: code/files-modules-and-programs/val.syntax ================================================ val : ================================================ FILE: code/files-modules-and-programs-freq/freq.ml ================================================ open Core.Std let build_counts () = In_channel.fold_lines stdin ~init:[] ~f:(fun counts line -> let count = match List.Assoc.find counts line with | None -> 0 | Some x -> x in List.Assoc.add counts line (count + 1) ) let () = build_counts () |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y) |> (fun l -> List.take l 10) |> List.iter ~f:(fun (line,count) -> printf "%3d: %s\n" count line) ================================================ FILE: code/files-modules-and-programs-freq/simple_build.sh ================================================ ocamlfind ocamlc -linkpkg -thread -package core freq.ml -o freq.byte ================================================ FILE: code/files-modules-and-programs-freq/simple_build_fail.errsh ================================================ ocamlc freq.ml -o freq.byte ================================================ FILE: code/files-modules-and-programs-freq-cyclic1/build.errsh ================================================ corebuild freq.byte ================================================ FILE: code/files-modules-and-programs-freq-cyclic1/counter.ml ================================================ open Core.Std type t = int String.Map.t let empty = String.Map.empty let to_list t = Map.to_alist t let touch t s = let count = match Map.find t s with | None -> 0 | Some x -> x in Map.add t ~key:s ~data:(count + 1) (* part 1 *) let singleton l = Counter.touch Counter.empty (* part 2 *) type median = | Median of string | Before_and_after of string * string let median t = let sorted_strings = List.sort (Map.to_alist t) ~cmp:(fun (_,x) (_,y) -> Int.descending x y) in let len = List.length sorted_strings in if len = 0 then failwith "median: empty frequency count"; let nth n = fst (List.nth_exn sorted_strings n) in if len mod 2 = 1 then Median (nth (len/2)) else Before_and_after (nth (len/2 - 1), nth (len/2));; ================================================ FILE: code/files-modules-and-programs-freq-cyclic1/counter.mli ================================================ open Core.Std (** A collection of string frequency counts *) type t (** The empty set of frequency counts *) val empty : t (** Bump the frequency count for the given string. *) val touch : t -> string -> t (* Converts the set of frequency counts to an association list. Every strings in the list will show up at most once, and the integers will be at least 1. *) val to_list : t -> (string * int) list (** Represents the median computed from a set of strings. In the case where there is an even number of choices, the one before and after the median is returned. *) type median = | Median of string | Before_and_after of string * string val median : t -> median ================================================ FILE: code/files-modules-and-programs-freq-cyclic1/freq.ml ================================================ open Core.Std let build_counts () = In_channel.fold_lines stdin ~init:Counter.empty ~f:Counter.touch let () = build_counts () |> Counter.to_list |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y) |> (fun counts -> List.take counts 10) |> List.iter ~f:(fun (line,count) -> printf "%3d: %s\n" count line) ================================================ FILE: code/files-modules-and-programs-freq-cyclic2/build.errsh ================================================ corebuild freq.byte ================================================ FILE: code/files-modules-and-programs-freq-cyclic2/counter.ml ================================================ open Core.Std type t = int String.Map.t let empty = String.Map.empty let to_list t = Map.to_alist t let touch t s = let count = match Map.find t s with | None -> 0 | Some x -> x in Map.add t ~key:s ~data:(count + 1) (* part 1 *) let _build_counts = Freq.build_counts (* part 2 *) type median = | Median of string | Before_and_after of string * string let median t = let sorted_strings = List.sort (Map.to_alist t) ~cmp:(fun (_,x) (_,y) -> Int.descending x y) in let len = List.length sorted_strings in if len = 0 then failwith "median: empty frequency count"; let nth n = fst (List.nth_exn sorted_strings n) in if len mod 2 = 1 then Median (nth (len/2)) else Before_and_after (nth (len/2 - 1), nth (len/2));; ================================================ FILE: code/files-modules-and-programs-freq-cyclic2/counter.mli ================================================ open Core.Std (** A collection of string frequency counts *) type t (** The empty set of frequency counts *) val empty : t (** Bump the frequency count for the given string. *) val touch : t -> string -> t (* Converts the set of frequency counts to an association list. Every strings in the list will show up at most once, and the integers will be at least 1. *) val to_list : t -> (string * int) list (** Represents the median computed from a set of strings. In the case where there is an even number of choices, the one before and after the median is returned. *) type median = | Median of string | Before_and_after of string * string val median : t -> median ================================================ FILE: code/files-modules-and-programs-freq-cyclic2/freq.ml ================================================ open Core.Std let build_counts () = In_channel.fold_lines stdin ~init:Counter.empty ~f:Counter.touch let () = build_counts () |> Counter.to_list |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y) |> (fun counts -> List.take counts 10) |> List.iter ~f:(fun (line,count) -> printf "%3d: %s\n" count line) ================================================ FILE: code/files-modules-and-programs-freq-fast/build.sh ================================================ corebuild freq.byte ================================================ FILE: code/files-modules-and-programs-freq-fast/counter.ml ================================================ open Core.Std type t = int String.Map.t let empty = String.Map.empty let to_list t = Map.to_alist t let touch t s = let count = match Map.find t s with | None -> 0 | Some x -> x in Map.add t ~key:s ~data:(count + 1) ================================================ FILE: code/files-modules-and-programs-freq-fast/counter.mli ================================================ open Core.Std (** A collection of string frequency counts *) type t (** The empty set of frequency counts *) val empty : t (** Bump the frequency count for the given string. *) val touch : t -> string -> t (* Converts the set of frequency counts to an association list. Every strings in the list will show up at most once, and the integers will be at least 1. *) val to_list : t -> (string * int) list ================================================ FILE: code/files-modules-and-programs-freq-fast/freq.ml ================================================ open Core.Std let build_counts () = In_channel.fold_lines stdin ~init:Counter.empty ~f:Counter.touch let () = build_counts () |> Counter.to_list |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y) |> (fun counts -> List.take counts 10) |> List.iter ~f:(fun (line,count) -> printf "%3d: %s\n" count line) ================================================ FILE: code/files-modules-and-programs-freq-median/build.sh ================================================ corebuild freq.byte ================================================ FILE: code/files-modules-and-programs-freq-median/build_use_median.sh ================================================ ../corebuild use_median_1.native ../corebuild use_median_2.native ================================================ FILE: code/files-modules-and-programs-freq-median/counter.ml ================================================ open Core.Std type t = int String.Map.t let empty = String.Map.empty let to_list t = Map.to_alist t let touch t s = let count = match Map.find t s with | None -> 0 | Some x -> x in Map.add t ~key:s ~data:(count + 1) (* part 1 *) type median = | Median of string | Before_and_after of string * string let median t = let sorted_strings = List.sort (Map.to_alist t) ~cmp:(fun (_,x) (_,y) -> Int.descending x y) in let len = List.length sorted_strings in if len = 0 then failwith "median: empty frequency count"; let nth n = fst (List.nth_exn sorted_strings n) in if len mod 2 = 1 then Median (nth (len/2)) else Before_and_after (nth (len/2 - 1), nth (len/2));; ================================================ FILE: code/files-modules-and-programs-freq-median/counter.mli ================================================ open Core.Std (** A collection of string frequency counts *) type t (** The empty set of frequency counts *) val empty : t (** Bump the frequency count for the given string. *) val touch : t -> string -> t (* Converts the set of frequency counts to an association list. Every strings in the list will show up at most once, and the integers will be at least 1. *) val to_list : t -> (string * int) list (* part 1 *) (** Represents the median computed from a set of strings. In the case where there is an even number of choices, the one before and after the median is returned. *) type median = | Median of string | Before_and_after of string * string val median : t -> median ================================================ FILE: code/files-modules-and-programs-freq-median/freq.ml ================================================ open Core.Std let build_counts () = In_channel.fold_lines stdin ~init:Counter.empty ~f:Counter.touch let () = build_counts () |> Counter.to_list |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y) |> (fun counts -> List.take counts 10) |> List.iter ~f:(fun (line,count) -> printf "%3d: %s\n" count line) ================================================ FILE: code/files-modules-and-programs-freq-median/use_median_1.ml ================================================ open Core.Std (* part 1 *) let print_median m = match m with | Counter.Median string -> printf "True median:\n %s\n" string | Counter.Before_and_after (before, after) -> printf "Before and after median:\n %s\n %s\n" before after ================================================ FILE: code/files-modules-and-programs-freq-median/use_median_2.ml ================================================ open Core.Std (* part 1 *) let print_median m = let module C = Counter in match m with | C.Median string -> printf "True median:\n %s\n" string | C.Before_and_after (before, after) -> printf "Before and after median:\n %s\n %s\n" before after ================================================ FILE: code/files-modules-and-programs-freq-obuild/build.sh ================================================ corebuild freq.byte ================================================ FILE: code/files-modules-and-programs-freq-obuild/test.sh ================================================ strings `which ocamlopt` | ./freq.byte ================================================ FILE: code/files-modules-and-programs-freq-with-counter/build.sh ================================================ corebuild freq.byte ================================================ FILE: code/files-modules-and-programs-freq-with-counter/counter.ml ================================================ open Core.Std let touch t s = let count = match List.Assoc.find t s with | None -> 0 | Some x -> x in List.Assoc.add t s (count + 1) ================================================ FILE: code/files-modules-and-programs-freq-with-counter/freq.ml ================================================ open Core.Std let build_counts () = In_channel.fold_lines stdin ~init:[] ~f:Counter.touch let () = build_counts () |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y) |> (fun l -> List.take l 10) |> List.iter ~f:(fun (line,count) -> printf "%3d: %s\n" count line) ================================================ FILE: code/files-modules-and-programs-freq-with-counter/infer_mli.sh ================================================ corebuild counter.inferred.mli cat _build/counter.inferred.mli ================================================ FILE: code/files-modules-and-programs-freq-with-missing-def/build.errsh ================================================ corebuild freq.byte ================================================ FILE: code/files-modules-and-programs-freq-with-missing-def/counter.ml ================================================ open Core.Std type t = int String.Map.t let empty = String.Map.empty let to_list t = Map.to_alist t let touch t s = let count = match Map.find t s with | None -> 0 | Some x -> x in Map.add t ~key:s ~data:(count + 1) (* part 1 *) type median = | Median of string | Before_and_after of string * string let median t = let sorted_strings = List.sort (Map.to_alist t) ~cmp:(fun (_,x) (_,y) -> Int.descending x y) in let len = List.length sorted_strings in if len = 0 then failwith "median: empty frequency count"; let nth n = fst (List.nth_exn sorted_strings n) in if len mod 2 = 1 then Median (nth (len/2)) else Before_and_after (nth (len/2 - 1), nth (len/2));; ================================================ FILE: code/files-modules-and-programs-freq-with-missing-def/counter.mli ================================================ open Core.Std (** A collection of string frequency counts *) type t (** The empty set of frequency counts *) val empty : t (** Bump the frequency count for the given string. *) val touch : t -> string -> t (* Converts the set of frequency counts to an association list. Every strings in the list will show up at most once, and the integers will be at least 1. *) val to_list : t -> (string * int) list (* part 1 *) val count : t -> string -> int (* part 2 *) (** Represents the median computed from a set of strings. In the case where there is an even number of choices, the one before and after the median is returned. *) type median = | Median of string | Before_and_after of string * string val median : t -> median ================================================ FILE: code/files-modules-and-programs-freq-with-missing-def/freq.ml ================================================ open Core.Std let build_counts () = In_channel.fold_lines stdin ~init:Counter.empty ~f:Counter.touch let () = build_counts () |> Counter.to_list |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y) |> (fun counts -> List.take counts 10) |> List.iter ~f:(fun (line,count) -> printf "%3d: %s\n" count line) ================================================ FILE: code/files-modules-and-programs-freq-with-sig/build.sh ================================================ corebuild freq.byte ================================================ FILE: code/files-modules-and-programs-freq-with-sig/counter.ml ================================================ open Core.Std let touch t s = let count = match List.Assoc.find t s with | None -> 0 | Some x -> x in List.Assoc.add t s (count + 1) ================================================ FILE: code/files-modules-and-programs-freq-with-sig/counter.mli ================================================ open Core.Std (** Bump the frequency count for the given string. *) val touch : (string * int) list -> string -> (string * int) list ================================================ FILE: code/files-modules-and-programs-freq-with-sig/freq.ml ================================================ open Core.Std let build_counts () = In_channel.fold_lines stdin ~init:[] ~f:Counter.touch let () = build_counts () |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y) |> (fun l -> List.take l 10) |> List.iter ~f:(fun (line,count) -> printf "%3d: %s\n" count line) ================================================ FILE: code/files-modules-and-programs-freq-with-sig-abstract/build.errsh ================================================ corebuild freq.byte ================================================ FILE: code/files-modules-and-programs-freq-with-sig-abstract/counter.ml ================================================ open Core.Std type t = (string * int) list let empty = [] let to_list x = x let touch t s = let count = match List.Assoc.find t s with | None -> 0 | Some x -> x in List.Assoc.add t s (count + 1) ================================================ FILE: code/files-modules-and-programs-freq-with-sig-abstract/counter.mli ================================================ open Core.Std (** A collection of string frequency counts *) type t (** The empty set of frequency counts *) val empty : t (** Bump the frequency count for the given string. *) val touch : t -> string -> t (** Converts the set of frequency counts to an association list. A string shows up at most once, and the counts are >= 1. *) val to_list : t -> (string * int) list ================================================ FILE: code/files-modules-and-programs-freq-with-sig-abstract/freq.ml ================================================ open Core.Std let build_counts () = In_channel.fold_lines stdin ~init:[] ~f:Counter.touch let () = build_counts () |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y) |> (fun l -> List.take l 10) |> List.iter ~f:(fun (line,count) -> printf "%3d: %s\n" count line) ================================================ FILE: code/files-modules-and-programs-freq-with-sig-abstract-fixed/build.sh ================================================ corebuild freq.byte ================================================ FILE: code/files-modules-and-programs-freq-with-sig-abstract-fixed/counter.ml ================================================ open Core.Std type t = (string * int) list let empty = [] let to_list x = x let touch t s = let count = match List.Assoc.find t s with | None -> 0 | Some x -> x in List.Assoc.add t s (count + 1) ================================================ FILE: code/files-modules-and-programs-freq-with-sig-abstract-fixed/counter.mli ================================================ open Core.Std (** A collection of string frequency counts *) type t (** The empty set of frequency counts *) val empty : t (** Bump the frequency count for the given string. *) val touch : t -> string -> t (* Converts the set of frequency counts to an association list. Every strings in the list will show up at most once, and the integers will be at least 1. *) val to_list : t -> (string * int) list ================================================ FILE: code/files-modules-and-programs-freq-with-sig-abstract-fixed/freq.ml ================================================ open Core.Std let build_counts () = In_channel.fold_lines stdin ~init:Counter.empty ~f:Counter.touch let () = build_counts () |> Counter.to_list |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y) |> (fun counts -> List.take counts 10) |> List.iter ~f:(fun (line,count) -> printf "%3d: %s\n" count line) ================================================ FILE: code/files-modules-and-programs-freq-with-sig-mismatch/build.errsh ================================================ corebuild freq.byte ================================================ FILE: code/files-modules-and-programs-freq-with-sig-mismatch/counter.ml ================================================ open Core.Std type t = int String.Map.t let empty = String.Map.empty let to_list t = Map.to_alist t let touch t s = let count = match Map.find t s with | None -> 0 | Some x -> x in Map.add t ~key:s ~data:(count + 1) ================================================ FILE: code/files-modules-and-programs-freq-with-sig-mismatch/counter.mli ================================================ open Core.Std (** A collection of string frequency counts *) type t (** The empty set of frequency counts *) val empty : t (* part 1 *) (** Bump the frequency count for the given string. *) val touch : string -> t -> t (* part 2 *) (* Converts the set of frequency counts to an association list. Every strings in the list will show up at most once, and the integers will be at least 1. *) val to_list : t -> (string * int) list ================================================ FILE: code/files-modules-and-programs-freq-with-sig-mismatch/freq.ml ================================================ open Core.Std let build_counts () = In_channel.fold_lines stdin ~init:Counter.empty ~f:Counter.touch let () = build_counts () |> Counter.to_list |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y) |> (fun counts -> List.take counts 10) |> List.iter ~f:(fun (line,count) -> printf "%3d: %s\n" count line) ================================================ FILE: code/files-modules-and-programs-freq-with-type-mismatch/build.errsh ================================================ corebuild freq.byte ================================================ FILE: code/files-modules-and-programs-freq-with-type-mismatch/counter.ml ================================================ open Core.Std type t = int String.Map.t let empty = String.Map.empty let to_list t = Map.to_alist t let touch t s = let count = match Map.find t s with | None -> 0 | Some x -> x in Map.add t ~key:s ~data:(count + 1) (* part 1 *) type median = | Median of string | Before_and_after of string * string let median t = let sorted_strings = List.sort (Map.to_alist t) ~cmp:(fun (_,x) (_,y) -> Int.descending x y) in let len = List.length sorted_strings in if len = 0 then failwith "median: empty frequency count"; let nth n = fst (List.nth_exn sorted_strings n) in if len mod 2 = 1 then Median (nth (len/2)) else Before_and_after (nth (len/2 - 1), nth (len/2));; ================================================ FILE: code/files-modules-and-programs-freq-with-type-mismatch/counter.mli ================================================ open Core.Std (** A collection of string frequency counts *) type t (** The empty set of frequency counts *) val empty : t (** Bump the frequency count for the given string. *) val touch : t -> string -> t (* Converts the set of frequency counts to an association list. Every strings in the list will show up at most once, and the integers will be at least 1. *) val to_list : t -> (string * int) list (* part 1 *) (** Represents the median computed from a set of strings. In the case where there is an even number of choices, the one before and after the median is returned. *) type median = | Before_and_after of string * string | Median of string (* part 2 *) val median : t -> median ================================================ FILE: code/files-modules-and-programs-freq-with-type-mismatch/freq.ml ================================================ open Core.Std let build_counts () = In_channel.fold_lines stdin ~init:Counter.empty ~f:Counter.touch let () = build_counts () |> Counter.to_list |> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y) |> (fun counts -> List.take counts 10) |> List.iter ~f:(fun (line,count) -> printf "%3d: %s\n" count line) ================================================ FILE: code/front-end/alice.ml ================================================ let friends = [ Bob.name ] ================================================ FILE: code/front-end/alice.mli ================================================ val friends : Bob.t list ================================================ FILE: code/front-end/alice_combined.ml ================================================ module Alice : sig val friends : Bob.t list end = struct let friends = [ Bob.name ] end ================================================ FILE: code/front-end/broken_module.ml ================================================ let () = module MyString = String; () ================================================ FILE: code/front-end/broken_poly.ml ================================================ let rec algebra = function | `Add (x,y) -> (algebra x) + (algebra y) | `Sub (x,y) -> (algebra x) - (algebra y) | `Mul (x,y) -> (algebra x) * (algebra y) | `Num x -> x let _ = algebra ( `Add ( (`Num 0), (`Sub ( (`Num 1), (`Mul ( (`Nu 3),(`Num 2) )) )) )) ================================================ FILE: code/front-end/broken_poly_with_annot.ml ================================================ type t = [ | `Add of t * t | `Sub of t * t | `Mul of t * t | `Num of int ] let rec algebra (x:t) = match x with | `Add (x,y) -> (algebra x) + (algebra y) | `Sub (x,y) -> (algebra x) - (algebra y) | `Mul (x,y) -> (algebra x) * (algebra y) | `Num x -> x let _ = algebra ( `Add ( (`Num 0), (`Sub ( (`Num 1), (`Mul ( (`Nu 3),(`Num 2) )) )) )) ================================================ FILE: code/front-end/build_broken_module.errsh ================================================ ocamlc -c broken_module.ml ================================================ FILE: code/front-end/build_broken_poly.errsh ================================================ ocamlc -c broken_poly.ml ================================================ FILE: code/front-end/build_broken_poly_with_annot.errsh ================================================ ocamlc -i broken_poly_with_annot.ml ================================================ FILE: code/front-end/build_follow_on_function.errsh ================================================ ocamlc -c follow_on_function.ml ================================================ FILE: code/front-end/build_non_principal.sh ================================================ ocamlc -i -principal non_principal.ml ================================================ FILE: code/front-end/build_ocamldoc.rawsh ================================================ $ mkdir -p html man/man3 $ ocamldoc -html -d html doc.ml $ ocamldoc -man -d man/man3 doc.ml $ man -M man Doc ================================================ FILE: code/front-end/build_principal.sh ================================================ ocamlc -i -principal principal.ml ================================================ FILE: code/front-end/build_type_conv_with_camlp4.rawsh ================================================ $ ocamlfind ocamlc -c -syntax camlp4o -package sexplib.syntax \ -package fieldslib.syntax type_conv_example.ml ================================================ FILE: code/front-end/build_type_conv_without_camlp4.errsh ================================================ ocamlfind ocamlc -c type_conv_example.ml ================================================ FILE: code/front-end/camlp4_dump.cmd ================================================ #!/bin/sh OCAMLFIND="ocamlfind query -predicates syntax,preprocessor -r" INCLUDE=`$OCAMLFIND -i-format comparelib.syntax` ARCHIVES=`$OCAMLFIND -a-format comparelib.syntax` camlp4o -printer o $INCLUDE $ARCHIVES $1 ================================================ FILE: code/front-end/camlp4_toplevel.topscript ================================================ #use "topfind" ;; #camlp4o ;; #part 1 #require "comparelib.syntax" ;; type t = { foo: string; bar : t } ;; type t = { foo: string; bar: t } with compare ;; ================================================ FILE: code/front-end/comparelib_test.ml ================================================ type t = { foo: string; bar: t } with compare ================================================ FILE: code/front-end/comparelib_test.mli ================================================ type t = { foo: string; bar: t } with compare ================================================ FILE: code/front-end/conflicting_interfaces.errsh ================================================ echo type t = Foo > test.ml echo type t = Bar > test.mli ocamlc -c test.mli test.ml ================================================ FILE: code/front-end/doc.ml ================================================ (** example.ml: The first special comment of the file is the comment associated with the whole module. *) (** Comment for exception My_exception. *) exception My_exception of (int -> int) * int (** Comment for type [weather] *) type weather = | Rain of int (** The comment for construtor Rain *) | Sun (** The comment for constructor Sun *) (** Find the current weather for a country @author Anil Madhavapeddy @param location The country to get the weather for. *) let what_is_the_weather_in location = match location with | `Cambridge -> Rain 100 | `New_york -> Rain 20 | `California -> Sun ================================================ FILE: code/front-end/fixed_module.ml ================================================ let () = let module MyString = String in () ================================================ FILE: code/front-end/follow_on_function.ml ================================================ let concat_and_print x y = let v = x ^ y in print_endline v; v; let add_and_print x y = let v = x + y in print_endline (string_of_int v); v let () = let _x = add_and_print 1 2 in let _y = concat_and_print "a" "b" in () ================================================ FILE: code/front-end/follow_on_function_fixed.ml ================================================ let concat_and_print x y = let v = x ^ y in print_endline v; v let add_and_print x y = let v = x + y in print_endline (string_of_int v); v let () = let _x = add_and_print 1 2 in let _y = concat_and_print "a" "b" in () ================================================ FILE: code/front-end/html/Doc.html ================================================ Doc

Module Doc

module Doc: sig .. end
example.ml: The first special comment of the file is the comment associated with the whole module.

exception My_exception of (int -> int) * int
Comment for exception My_exception.
type weather = 
| Rain of int (*The comment for construtor Rain*)
| Sun (*The comment for constructor Sun*)
Comment for type weather
val what_is_the_weather_in : [< `California | `Cambridge | `New_york ] -> weather
Find the current weather for a country
Author(s): Anil Madhavapeddy
location : The country to get the weather for.
================================================ FILE: code/front-end/html/index.html ================================================



Doc
example.ml: The first special comment of the file is the comment associated with the whole module.
================================================ FILE: code/front-end/html/index_attributes.html ================================================ Index of class attributes

Index of class attributes

================================================ FILE: code/front-end/html/index_class_types.html ================================================ Index of class types

Index of class types

================================================ FILE: code/front-end/html/index_classes.html ================================================ Index of classes

Index of classes

================================================ FILE: code/front-end/html/index_exceptions.html ================================================ Index of exceptions

Index of exceptions


M
My_exception [Doc]
Comment for exception My_exception.
================================================ FILE: code/front-end/html/index_methods.html ================================================ Index of class methods

Index of class methods

================================================ FILE: code/front-end/html/index_module_types.html ================================================ Index of module types

Index of module types

================================================ FILE: code/front-end/html/index_modules.html ================================================ Index of modules

Index of modules


D
Doc
example.ml: The first special comment of the file is the comment associated with the whole module.
================================================ FILE: code/front-end/html/index_types.html ================================================ Index of types

Index of types


W
weather [Doc]
Comment for type weather
================================================ FILE: code/front-end/html/index_values.html ================================================ Index of values

Index of values


W
what_is_the_weather_in [Doc]
Find the current weather for a country
================================================ FILE: code/front-end/html/style.css ================================================ .keyword { font-weight : bold ; color : Red } .keywordsign { color : #C04600 } .superscript { font-size : 4 } .subscript { font-size : 4 } .comment { color : Green } .constructor { color : Blue } .type { color : #5C6585 } .string { color : Maroon } .warning { color : Red ; font-weight : bold } .info { margin-left : 3em; margin-right: 3em } .param_info { margin-top: 4px; margin-left : 3em; margin-right : 3em } .code { color : #465F91 ; } .typetable { border-style : hidden } .paramstable { border-style : hidden ; padding: 5pt 5pt} tr { background-color : White } td.typefieldcomment { background-color : #FFFFFF ; font-size: smaller ;} div.sig_block {margin-left: 2em} *:target { background: yellow; } body {font: 13px sans-serif; color: black; text-align: left; padding: 5px; margin: 0} h1 { font-size : 20pt ; text-align: center; } h2 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90BDFF ;padding: 2px; } h3 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90DDFF ;padding: 2px; } h4 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90EDFF ;padding: 2px; } h5 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90FDFF ;padding: 2px; } h6 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90BDFF ; padding: 2px; } div.h7 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #E0FFFF ; padding: 2px; } div.h8 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #F0FFFF ; padding: 2px; } div.h9 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #FFFFFF ; padding: 2px; } a {color: #416DFF; text-decoration: none} a:hover {background-color: #ddd; text-decoration: underline} pre { margin-bottom: 4px; font-family: monospace; } pre.verbatim, pre.codepre { } .indextable {border: 1px #ddd solid; border-collapse: collapse} .indextable td, .indextable th {border: 1px #ddd solid; min-width: 80px} .indextable td.module {background-color: #eee ; padding-left: 2px; padding-right: 2px} .indextable td.module a {color: 4E6272; text-decoration: none; display: block; width: 100%} .indextable td.module a:hover {text-decoration: underline; background-color: transparent} .deprecated {color: #888; font-style: italic} .indextable tr td div.info { margin-left: 2px; margin-right: 2px } ul.indexlist { margin-left: 0; padding-left: 0;} ul.indexlist li { list-style-type: none ; margin-left: 0; padding-left: 0; } ================================================ FILE: code/front-end/html/type_Doc.html ================================================ Doc sig  end ================================================ FILE: code/front-end/inconsistent_compilation_units.rawsh ================================================ $ ocamlc -c foo.ml File "foo.ml", line 1, characters 0-1: Error: The files /home/build/bar.cmi and /usr/lib/ocaml/map.cmi make inconsistent assumptions over interface Map ================================================ FILE: code/front-end/indent_follow_on_function.sh ================================================ ocp-indent follow_on_function.ml ================================================ FILE: code/front-end/indent_follow_on_function_fixed.sh ================================================ ocp-indent follow_on_function_fixed.ml ================================================ FILE: code/front-end/infer_typedef.sh ================================================ ocamlc -i typedef.ml ================================================ FILE: code/front-end/install_ocp_index.rawsh ================================================ $ opam install ocp-index $ ocp-index ================================================ FILE: code/front-end/let_notunit.ml ================================================ let (_:some_type) = let () = ignore ( : some_type) )(* if the expression returns a unit Deferred.t *) let () = don't_wait_for ( ================================================ FILE: code/front-end/let_unit.syntax ================================================ let () = ================================================ FILE: code/front-end/man/man3/Doc.3o ================================================ .TH "Doc" 3 2013-07-23 OCamldoc "" .SH NAME Doc \- example.ml: The first special comment of the file is the comment associated with the whole module. .SH Module Module Doc .SH Documentation .sp Module .BI "Doc" : .B sig end .sp example\&.ml: The first special comment of the file is the comment associated with the whole module\&. .sp .sp .sp .sp .I exception My_exception .B of .B (int -> int) * int .sp Comment for exception My_exception\&. .sp .sp .I type weather = | Rain .B of .B int .I " " (* The comment for construtor Rain *) | Sun (* The comment for constructor Sun *) .sp Comment for type .B weather .sp .sp .I val what_is_the_weather_in : .B [< `California | `Cambridge | `New_york ] -> weather .sp Find the current weather for a country .sp .B "Author(s)" : Anil Madhavapeddy .sp .sp ================================================ FILE: code/front-end/man/man3/My_exception.3o ================================================ .TH "My_exception" 3 2013-07-23 OCamldoc "" .SH NAME My_exception \- all My_exception elements .SH Module Doc .I exception My_exception .B of .B (int -> int) * int .sp Comment for exception My_exception\&. .sp .sp ================================================ FILE: code/front-end/man/man3/Rain.3o ================================================ .TH "Rain" 3 2013-07-23 OCamldoc "" .SH NAME Rain \- all Rain elements ================================================ FILE: code/front-end/man/man3/Sun.3o ================================================ .TH "Sun" 3 2013-07-23 OCamldoc "" .SH NAME Sun \- all Sun elements ================================================ FILE: code/front-end/man/man3/weather.3o ================================================ .TH "weather" 3 2013-07-23 OCamldoc "" .SH NAME weather \- all weather elements .SH Module Doc .I type weather = | Rain .B of .B int .I " " (* The comment for construtor Rain *) | Sun (* The comment for constructor Sun *) .sp Comment for type .B weather .sp .sp ================================================ FILE: code/front-end/man/man3/what_is_the_weather_in.3o ================================================ .TH "what_is_the_weather_in" 3 2013-07-23 OCamldoc "" .SH NAME what_is_the_weather_in \- all what_is_the_weather_in elements .SH Module Doc .I val what_is_the_weather_in : .B [< `California | `Cambridge | `New_york ] -> weather .sp Find the current weather for a country .sp .B "Author(s)" : Anil Madhavapeddy .sp .sp ================================================ FILE: code/front-end/non_principal.ml ================================================ type s = { foo: int; bar: unit } type t = { foo: int } let f x = x.bar; x.foo ================================================ FILE: code/front-end/parsetree_typedef.sh ================================================ ocamlc -dparsetree typedef.ml 2>&1 ================================================ FILE: code/front-end/pipeline.ascii ================================================ Source code | | parsing and preprocessing | | camlp4 syntax extensions | v Parsetree (untyped AST) | | type inference and checking v Typedtree (type-annotated AST) | | pattern-matching compilation | elimination of modules and classes v Lambda / \ / \ closure conversion, inlining, uncurrying, v \ data representation strategy Bytecode \ | +-----+ | Cmm |ocamlrun | | | code generation | | assembly & linking v v Interpreted Compiled ================================================ FILE: code/front-end/principal.ml ================================================ type s = { foo: int; bar: unit } type t = { foo: int } let f (x:s) = x.bar; x.foo ================================================ FILE: code/front-end/process_comparelib_interface.sh ================================================ sh camlp4_dump.cmd comparelib_test.mli ================================================ FILE: code/front-end/process_comparelib_test.sh ================================================ sh camlp4_dump.cmd comparelib_test.ml ================================================ FILE: code/front-end/short_paths_1.rawsh ================================================ $ ocaml # List.map print_endline "" ;; Error: This expression has type string but an expression was expected of type string list ================================================ FILE: code/front-end/short_paths_2.rawsh ================================================ $ ocaml # open Core.Std ;; # List.map ~f:print_endline "" ;; Error: This expression has type string but an expression was expected of type 'a Core.Std.List.t = 'a list ================================================ FILE: code/front-end/short_paths_3.rawsh ================================================ $ ocaml -short-paths # open Core.Std;; # List.map ~f:print_endline "foo";; Error: This expression has type string but an expression was expected of type 'a list ================================================ FILE: code/front-end/test.ml ================================================ type t = Foo ================================================ FILE: code/front-end/test.mli ================================================ type t = Bar ================================================ FILE: code/front-end/type_conv_example.ml ================================================ open Sexplib.Std type t = { foo: int; bar: string } with sexp, fields ================================================ FILE: code/front-end/typedef.ml ================================================ type t = Foo | Bar let v = Foo ================================================ FILE: code/front-end/typedef_objinfo.sh ================================================ ocamlc -c typedef.ml ocamlobjinfo typedef.cmi ================================================ FILE: code/front-end/typedtree_typedef.sh ================================================ ocamlc -dtypedtree typedef.ml 2>&1 ================================================ FILE: code/front-end/unused_var.ml ================================================ let fn x y = let _z = x + y in () ================================================ FILE: code/front-end/xbuild_type_conv_with_camlp4.sh ================================================ ocamlfind ocamlc -c -syntax camlp4o -package sexplib.syntax -package fieldslib.syntax type_conv_example.ml ================================================ FILE: code/functors/build_extended_fqueue.sh ================================================ corebuild extended_fqueue.cmo ================================================ FILE: code/functors/build_fqueue.sh ================================================ corebuild fqueue.cmo ================================================ FILE: code/functors/compare_example.ml ================================================ compare x y < 0 (* x < y *) compare x y = 0 (* x = y *) compare x y > 0 (* x > y *) ================================================ FILE: code/functors/destructive_sub.syntax ================================================ with type := ================================================ FILE: code/functors/extended_fqueue.ml ================================================ include Fqueue include Foldable.Extend(Fqueue) ================================================ FILE: code/functors/extended_fqueue.mli ================================================ type 'a t include (module type of Fqueue) with type 'a t := 'a t include Foldable.Extension with type 'a t := 'a t ================================================ FILE: code/functors/foldable.ml ================================================ open Core.Std module type S = sig type 'a t val fold : 'a t -> init:'acc -> f:('acc -> 'a -> 'acc) -> 'acc end module type Extension = sig type 'a t val iter : 'a t -> f:('a -> unit) -> unit val length : 'a t -> int val count : 'a t -> f:('a -> bool) -> int val for_all : 'a t -> f:('a -> bool) -> bool val exists : 'a t -> f:('a -> bool) -> bool end (* For extending a Foldable module *) module Extend(Arg : S) : (Extension with type 'a t := 'a Arg.t) = struct open Arg let iter t ~f = fold t ~init:() ~f:(fun () a -> f a) let length t = fold t ~init:0 ~f:(fun acc _ -> acc + 1) let count t ~f = fold t ~init:0 ~f:(fun count x -> count + if f x then 1 else 0) exception Short_circuit let for_all c ~f = try iter c ~f:(fun x -> if not (f x) then raise Short_circuit); true with Short_circuit -> false let exists c ~f = try iter c ~f:(fun x -> if f x then raise Short_circuit); false with Short_circuit -> true end ================================================ FILE: code/functors/fqueue.ml ================================================ open Core.Std type 'a t = 'a list * 'a list let empty = ([],[]) let enqueue (in_list, out_list) x = (x :: in_list,out_list) let dequeue (in_list, out_list) = match out_list with | hd :: tl -> Some (hd, (in_list, tl)) | [] -> match List.rev in_list with | [] -> None | hd :: tl -> Some (hd, ([], tl)) let fold (in_list, out_list) ~init ~f = let after_out = List.fold ~init ~f out_list in List.fold_right ~init:after_out ~f:(fun x acc -> f acc x) in_list ================================================ FILE: code/functors/fqueue.mli ================================================ type 'a t val empty : 'a t (** [enqueue el q] adds [el] to the back of [q] *) val enqueue : 'a t -> 'a -> 'a t (** [dequeue q] returns None if the [q] is empty, otherwise returns the first element of the queue and the remainder of the queue *) val dequeue : 'a t -> ('a * 'a t) option (** Folds over the queue, from front to back *) val fold : 'a t -> init:'acc -> f:('acc -> 'a -> 'acc) -> 'acc ================================================ FILE: code/functors/main-15.rawscript ================================================ # module Make_interval(Endpoint : Comparable) : Interval_intf = struct type endpoint = Endpoint.t type t = | Interval of Endpoint.t * Endpoint.t | Empty ... end ;; module Make_interval : functor (Endpoint : Comparable) -> Interval_intf ================================================ FILE: code/functors/main-18.rawscript ================================================ # module Make_interval(Endpoint : Comparable) : (Interval_intf with type endpoint = Endpoint.t) = struct type endpoint = Endpoint.t type t = | Interval of Endpoint.t * Endpoint.t | Empty ... end ;; module Make_interval : functor (Endpoint : Comparable) -> sig type t type endpoint = Endpoint.t val create : endpoint -> endpoint -> t val is_empty : t -> bool val contains : t -> endpoint -> bool val intersect : t -> t -> t end ================================================ FILE: code/functors/main-21.rawscript ================================================ # module Make_interval(Endpoint : Comparable) : Interval_intf with type endpoint := Endpoint.t = struct type t = | Interval of Endpoint.t * Endpoint.t | Empty ... end ;; module Make_interval : functor (Endpoint : Comparable) -> sig type t val create : Endpoint.t -> Endpoint.t -> t val is_empty : t -> bool val contains : t -> Endpoint.t -> bool val intersect : t -> t -> t end ================================================ FILE: code/functors/main-25.rawscript ================================================ # module Make_interval(Endpoint : Comparable) : (Interval_intf with type endpoint := Endpoint.t) = struct type t = | Interval of Endpoint.t * Endpoint.t | Empty with sexp ... end ;; Characters 136-146: Error: Unbound value Endpoint.t_of_sexp ================================================ FILE: code/functors/main.topscript ================================================ module type X_int = sig val x : int end;; #part 1 module Increment (M : X_int) : X_int = struct let x = M.x + 1 end;; #part 2 module Increment (M : X_int) = struct let x = M.x + 1 end;; #part 3 module Three = struct let x = 3 end;; module Four = Increment(Three);; Four.x - Three.x;; #part 4 module Three_and_more = struct let x = 3 let y = "three" end;; module Four = Increment(Three_and_more);; #part 5 module type Comparable = sig type t val compare : t -> t -> int end ;; #part 6 module Make_interval(Endpoint : Comparable) = struct type t = | Interval of Endpoint.t * Endpoint.t | Empty (** [create low high] creates a new interval from [low] to [high]. If [low > high], then the interval is empty *) let create low high = if Endpoint.compare low high > 0 then Empty else Interval (low,high) (** Returns true iff the interval is empty *) let is_empty = function | Empty -> true | Interval _ -> false (** [contains t x] returns true iff [x] is contained in the interval [t] *) let contains t x = match t with | Empty -> false | Interval (l,h) -> Endpoint.compare x l >= 0 && Endpoint.compare x h <= 0 (** [intersect t1 t2] returns the intersection of the two input intervals *) let intersect t1 t2 = let min x y = if Endpoint.compare x y <= 0 then x else y in let max x y = if Endpoint.compare x y >= 0 then x else y in match t1,t2 with | Empty, _ | _, Empty -> Empty | Interval (l1,h1), Interval (l2,h2) -> create (max l1 l2) (min h1 h2) end ;; #part 7 module Int_interval = Make_interval(struct type t = int let compare = Int.compare end);; #part 8 module Int_interval = Make_interval(Int) ;; module String_interval = Make_interval(String) ;; #part 9 let i1 = Int_interval.create 3 8;; let i2 = Int_interval.create 4 10;; Int_interval.intersect i1 i2;; #part 10 module Rev_int_interval = Make_interval(struct type t = int let compare x y = Int.compare y x end);; #part 11 let interval = Int_interval.create 4 3;; let rev_interval = Rev_int_interval.create 4 3;; #part 12 Int_interval.contains rev_interval 3;; #part 13 Int_interval.is_empty (* going through create *) (Int_interval.create 4 3) ;; Int_interval.is_empty (* bypassing create *) (Int_interval.Interval (4,3)) ;; #part 14 module type Interval_intf = sig type t type endpoint val create : endpoint -> endpoint -> t val is_empty : t -> bool val contains : t -> endpoint -> bool val intersect : t -> t -> t end;; #part 15 module Make_interval(Endpoint : Comparable) : Interval_intf = struct type endpoint = Endpoint.t type t = | Interval of Endpoint.t * Endpoint.t | Empty (** [create low high] creates a new interval from [low] to [high]. If [low > high], then the interval is empty *) let create low high = if Endpoint.compare low high > 0 then Empty else Interval (low,high) (** Returns true iff the interval is empty *) let is_empty = function | Empty -> true | Interval _ -> false (** [contains t x] returns true iff [x] is contained in the interval [t] *) let contains t x = match t with | Empty -> false | Interval (l,h) -> Endpoint.compare x l >= 0 && Endpoint.compare x h <= 0 (** [intersect t1 t2] returns the intersection of the two input intervals *) let intersect t1 t2 = let min x y = if Endpoint.compare x y <= 0 then x else y in let max x y = if Endpoint.compare x y >= 0 then x else y in match t1,t2 with | Empty, _ | _, Empty -> Empty | Interval (l1,h1), Interval (l2,h2) -> create (max l1 l2) (min h1 h2) end ;; #part 16 module Int_interval = Make_interval(Int);; Int_interval.create 3 4;; #part 17 module type Int_interval_intf = Interval_intf with type endpoint = int;; #part 18 module Make_interval(Endpoint : Comparable) : (Interval_intf with type endpoint = Endpoint.t) = struct type endpoint = Endpoint.t type t = | Interval of Endpoint.t * Endpoint.t | Empty (** [create low high] creates a new interval from [low] to [high]. If [low > high], then the interval is empty *) let create low high = if Endpoint.compare low high > 0 then Empty else Interval (low,high) (** Returns true iff the interval is empty *) let is_empty = function | Empty -> true | Interval _ -> false (** [contains t x] returns true iff [x] is contained in the interval [t] *) let contains t x = match t with | Empty -> false | Interval (l,h) -> Endpoint.compare x l >= 0 && Endpoint.compare x h <= 0 (** [intersect t1 t2] returns the intersection of the two input intervals *) let intersect t1 t2 = let min x y = if Endpoint.compare x y <= 0 then x else y in let max x y = if Endpoint.compare x y >= 0 then x else y in match t1,t2 with | Empty, _ | _, Empty -> Empty | Interval (l1,h1), Interval (l2,h2) -> create (max l1 l2) (min h1 h2) end ;; #part 19 module Int_interval = Make_interval(Int);; let i = Int_interval.create 3 4;; Int_interval.contains i 5;; #part 20 module type Int_interval_intf = Interval_intf with type endpoint := int;; #part 21 module Make_interval(Endpoint : Comparable) : Interval_intf with type endpoint := Endpoint.t = struct type t = | Interval of Endpoint.t * Endpoint.t | Empty (** [create low high] creates a new interval from [low] to [high]. If [low > high], then the interval is empty *) let create low high = if Endpoint.compare low high > 0 then Empty else Interval (low,high) (** Returns true iff the interval is empty *) let is_empty = function | Empty -> true | Interval _ -> false (** [contains t x] returns true iff [x] is contained in the interval [t] *) let contains t x = match t with | Empty -> false | Interval (l,h) -> Endpoint.compare x l >= 0 && Endpoint.compare x h <= 0 (** [intersect t1 t2] returns the intersection of the two input intervals *) let intersect t1 t2 = let min x y = if Endpoint.compare x y <= 0 then x else y in let max x y = if Endpoint.compare x y >= 0 then x else y in match t1,t2 with | Empty, _ | _, Empty -> Empty | Interval (l1,h1), Interval (l2,h2) -> create (max l1 l2) (min h1 h2) end ;; #part 22 module Int_interval = Make_interval(Int);; Int_interval.is_empty (Int_interval.create 3 4);; Int_interval.is_empty (Int_interval.Interval (4,3));; #part 23 Sexp.of_string "(This is (an s-expression))";; #part 24 type some_type = int * string list with sexp;; sexp_of_some_type (33, ["one"; "two"]);; Sexp.of_string "(44 (five six))" |> some_type_of_sexp;; #part 25 module Make_interval(Endpoint : Comparable) : (Interval_intf with type endpoint := Endpoint.t) = struct type t = | Interval of Endpoint.t * Endpoint.t | Empty with sexp (** [create low high] creates a new interval from [low] to [high]. If [low > high], then the interval is empty *) let create low high = if Endpoint.compare low high > 0 then Empty else Interval (low,high) (** Returns true iff the interval is empty *) let is_empty = function | Empty -> true | Interval _ -> false (** [contains t x] returns true iff [x] is contained in the interval [t] *) let contains t x = match t with | Empty -> false | Interval (l,h) -> Endpoint.compare x l >= 0 && Endpoint.compare x h <= 0 (** [intersect t1 t2] returns the intersection of the two input intervals *) let intersect t1 t2 = let min x y = if Endpoint.compare x y <= 0 then x else y in let max x y = if Endpoint.compare x y >= 0 then x else y in match t1,t2 with | Empty, _ | _, Empty -> Empty | Interval (l1,h1), Interval (l2,h2) -> create (max l1 l2) (min h1 h2) end ;; #part 26 module type Interval_intf_with_sexp = sig include Interval_intf include Sexpable with type t := t end;; #part 27 module type Interval_intf_with_sexp = sig type t include Interval_intf with type t := t include Sexpable with type t := t end;; #part 28 module Make_interval(Endpoint : sig type t include Comparable with type t := t include Sexpable with type t := t end) : (Interval_intf_with_sexp with type endpoint := Endpoint.t) = struct type t = | Interval of Endpoint.t * Endpoint.t | Empty with sexp (** [create low high] creates a new interval from [low] to [high]. If [low > high], then the interval is empty *) let create low high = if Endpoint.compare low high > 0 then Empty else Interval (low,high) (* put a wrapper around the autogenerated [t_of_sexp] to enforce the invariants of the data structure *) let t_of_sexp sexp = match t_of_sexp sexp with | Empty -> Empty | Interval (x,y) -> create x y (** Returns true iff the interval is empty *) let is_empty = function | Empty -> true | Interval _ -> false (** [contains t x] returns true iff [x] is contained in the interval [t] *) let contains t x = match t with | Empty -> false | Interval (l,h) -> Endpoint.compare x l >= 0 && Endpoint.compare x h <= 0 (** [intersect t1 t2] returns the intersection of the two input intervals *) let intersect t1 t2 = let min x y = if Endpoint.compare x y <= 0 then x else y in let max x y = if Endpoint.compare x y >= 0 then x else y in match t1,t2 with | Empty, _ | _, Empty -> Empty | Interval (l1,h1), Interval (l2,h2) -> create (max l1 l2) (min h1 h2) end;; #part 29 module Int_interval = Make_interval(Int) ;; Int_interval.sexp_of_t (Int_interval.create 3 4);; Int_interval.sexp_of_t (Int_interval.create 4 3);; #part 30 #part 31 #part 32 #part 33 #part 34 #part 35 #part 36 #part 37 #part 38 #part 39 #part 40 #part 41 #part 42 #part 43 #part 44 #part 45 #part 46 #part 47 #part 48 #part 49 #part 50 #part 51 #part 52 #part 53 #part 54 #part 55 #part 56 #part 57 #part 58 #part 59 #part 60 #part 61 #part 62 #part 63 #part 64 #part 65 #part 66 #part 67 #part 68 #part 69 #part 70 #part 71 #part 72 #part 73 #part 74 #part 75 #part 76 #part 77 #part 78 #part 79 #part 80 #part 81 #part 82 #part 83 #part 84 #part 85 #part 86 #part 87 #part 88 #part 89 #part 90 #part 91 #part 92 #part 93 #part 94 #part 95 #part 96 #part 97 #part 98 #part 99 #part 100 ================================================ FILE: code/functors/multi_sharing_constraint.syntax ================================================ with type = and = ================================================ FILE: code/functors/sexpable.ml ================================================ module type Sexpable = sig type t val sexp_of_t : t -> Sexp.t val t_of_sexp : Sexp.t -> t end ================================================ FILE: code/functors/sharing_constraint.syntax ================================================ with type = ================================================ FILE: code/gc/barrier_bench.ml ================================================ open Core.Std open Core_bench.Std type t1 = { mutable iters1: int; mutable count1: float } type t2 = { iters2: int; count2: float } let rec test_mutable t1 = match t1.iters1 with |0 -> () |_ -> t1.iters1 <- t1.iters1 - 1; t1.count1 <- t1.count1 +. 1.0; test_mutable t1 let rec test_immutable t2 = match t2.iters2 with |0 -> () |n -> let iters2 = n - 1 in let count2 = t2.count2 +. 1.0 in test_immutable { iters2; count2 } let () = let iters = 1000000 in let tests = [ Bench.Test.create ~name:"mutable" (fun () -> test_mutable { iters1=iters; count1=0.0 }); Bench.Test.create ~name:"immutable" (fun () -> test_immutable { iters2=iters; count2=0.0 }) ] in Bench.make_command tests |> Command.run ================================================ FILE: code/gc/finalizer.ml ================================================ open Core.Std open Async.Std let attach_finalizer n v = match Heap_block.create v with | None -> printf "%20s: FAIL\n%!" n | Some hb -> let final _ = printf "%20s: OK\n%!" n in Gc.add_finalizer hb final type t = { foo: bool } let main () = let alloced_float = Unix.gettimeofday () in let alloced_bool = alloced_float > 0.0 in let alloced_string = String.create 4 in attach_finalizer "immediate int" 1; attach_finalizer "immediate float" 1.0; attach_finalizer "immediate variant" (`Foo "hello"); attach_finalizer "immediate string" "hello world"; attach_finalizer "immediate record" { foo=false }; attach_finalizer "allocated float" alloced_float; attach_finalizer "allocated bool" alloced_bool; attach_finalizer "allocated variant" (`Foo alloced_bool); attach_finalizer "allocated string" alloced_string; attach_finalizer "allocated record" { foo=alloced_bool }; Gc.compact (); return () let () = Command.async_basic ~summary:"Testing finalizers" Command.Spec.empty main |> Command.run ================================================ FILE: code/gc/minor_heap.ascii ================================================ <---- size ----> base --- start ---------------- end limit ptr <------ blocks ================================================ FILE: code/gc/run_barrier_bench.sh ================================================ corebuild -pkg core_bench barrier_bench.native ./barrier_bench.native -ascii alloc ================================================ FILE: code/gc/run_finalizer.sh ================================================ corebuild -pkg async finalizer.native ./finalizer.native ================================================ FILE: code/gc/show_barrier_bench_help.sh ================================================ ./barrier_bench.native -help ================================================ FILE: code/gc/tune.topscript ================================================ let c = Gc.get () ;; Gc.tune ~minor_heap_size:(262144 * 2) () ;; #part 1 Gc.tune ~major_heap_increment:(1000448 * 4) () ;; #part 2 Gc.major_slice 0 ;; Gc.full_major () ;; #part 3 Gc.tune ~max_overhead:0 () ;; ================================================ FILE: code/guided-tour/build_sum.sh ================================================ corebuild sum.native ================================================ FILE: code/guided-tour/local_let.topscript ================================================ let x = 7 in x + x ;; #part 1 x;; #part 2 let x = 7 in let y = x * x in x + y ;; ================================================ FILE: code/guided-tour/main.topscript ================================================ open Core.Std;; #part 1 3 + 4;; 8 / 3;; 3.5 +. 6.;; 30_000_000 / 300_000;; sqrt 9.;; #part 2 let x = 3 + 4;; let y = x + x;; #part 3 let x7 = 3 + 4;; let x_plus_y = x + y;; let x' = x + 1;; let _x' = x' + x';; _x';; #part 4 let Seven = 3 + 4;; let 7x = 7;; let x-plus-y = x + y;; #part 5 let square x = x * x ;; square 2;; square (square 2);; #part 6 let ratio x y = Float.of_int x /. Float.of_int y ;; ratio 4 7;; #part 7 let sum_if_true test first second = (if test first then first else 0) + (if test second then second else 0) ;; #part 8 let even x = x mod 2 = 0 ;; sum_if_true even 3 4;; sum_if_true even 2 4;; #part 9 let sum_if_true (test : int -> bool) (x : int) (y : int) : int = (if test x then x else 0) + (if test y then y else 0) ;; #part 10 let first_if_true test x y = if test x then x else y ;; #part 11 let long_string s = String.length s > 6;; first_if_true long_string "short" "loooooong";; #part 12 let big_number x = x > 3;; first_if_true big_number 4 3;; #part 13 first_if_true big_number "short" "loooooong";; #part 14 let add_potato x = x + "potato";; #part 15 let is_a_multiple x y = x mod y = 0 ;; is_a_multiple 8 2;; is_a_multiple 8 0;; #part 16 let a_tuple = (3,"three");; let another_tuple = (3,"four",5.);; #part 17 let (x,y) = a_tuple;; #part 18 x + String.length y;; #part 19 let distance (x1,y1) (x2,y2) = sqrt ((x1 -. x2) ** 2. +. (y1 -. y2) ** 2.) ;; #part 20 let languages = ["OCaml";"Perl";"C"];; #part 21 let numbers = [3;"four";5];; #part 22 List.length languages;; #part 23 List.map languages ~f:String.length;; #part 24 List.map ~f:String.length languages;; #part 25 "French" :: "Spanish" :: languages;; #part 26 languages;; #part 27 ["OCaml", "Perl", "C"];; #part 28 1,2,3;; #part 29 [1; 2; 3];; 1 :: (2 :: (3 :: []));; 1 :: 2 :: 3 :: [];; #part 30 [1;2;3] @ [4;5;6];; #part 31 let my_favorite_language (my_favorite :: the_rest) = my_favorite ;; #part 32 my_favorite_language ["English";"Spanish";"French"];; my_favorite_language [];; #part 33 let my_favorite_language languages = match languages with | first :: the_rest -> first | [] -> "OCaml" (* A good default! *) ;; my_favorite_language ["English";"Spanish";"French"];; my_favorite_language [];; #part 34 let rec sum l = match l with | [] -> 0 (* base case *) | hd :: tl -> hd + sum tl (* inductive case *) ;; sum [1;2;3];; #part 35 let rec destutter list = match list with | [] -> [] | hd1 :: hd2 :: tl -> if hd1 = hd2 then destutter (hd2 :: tl) else hd1 :: destutter (hd2 :: tl) ;; #part 36 let rec destutter list = match list with | [] -> [] | [hd] -> [hd] | hd1 :: hd2 :: tl -> if hd1 = hd2 then destutter (hd2 :: tl) else hd1 :: destutter (hd2 :: tl) ;; destutter ["hey";"hey";"hey";"man!"];; #part 37 let divide x y = if y = 0 then None else Some (x/y) ;; #part 38 let log_entry maybe_time message = let time = match maybe_time with | Some x -> x | None -> Time.now () in Time.to_sec_string time ^ " -- " ^ message ;; log_entry (Some Time.epoch) "A long long time ago";; log_entry None "Up to the minute";; #part 39 let x = 7 in x + x ;; #part 40 let x = 7 in let y = x * x in x + y ;; #part 41 type point2d = { x : float; y : float };; #part 42 let p = { x = 3.; y = -4. };; #part 43 let magnitude { x = x_pos; y = y_pos } = sqrt (x_pos ** 2. +. y_pos ** 2.);; #part 44 let magnitude { x; y } = sqrt (x ** 2. +. y ** 2.);; #part 45 let distance v1 v2 = magnitude { x = v1.x -. v2.x; y = v1.y -. v2.y };; #part 46 type circle_desc = { center: point2d; radius: float } type rect_desc = { lower_left: point2d; width: float; height: float } type segment_desc = { endpoint1: point2d; endpoint2: point2d } ;; #part 47 type scene_element = | Circle of circle_desc | Rect of rect_desc | Segment of segment_desc ;; #part 48 let is_inside_scene_element point scene_element = match scene_element with | Circle { center; radius } -> distance center point < radius | Rect { lower_left; width; height } -> point.x > lower_left.x && point.x < lower_left.x +. width && point.y > lower_left.y && point.y < lower_left.y +. height | Segment { endpoint1; endpoint2 } -> false ;; let is_inside_scene point scene = List.exists scene ~f:(fun el -> is_inside_scene_element point el) ;; is_inside_scene {x=3.;y=7.} [ Circle {center = {x=4.;y= 4.}; radius = 0.5 } ];; is_inside_scene {x=3.;y=7.} [ Circle {center = {x=4.;y= 4.}; radius = 5.0 } ];; #part 49 let numbers = [| 1; 2; 3; 4 |];; numbers.(2) <- 4;; numbers;; #part 50 type running_sum = { mutable sum: float; mutable sum_sq: float; (* sum of squares *) mutable samples: int; } ;; #part 51 let mean rsum = rsum.sum /. float rsum.samples let stdev rsum = sqrt (rsum.sum_sq /. float rsum.samples -. (rsum.sum /. float rsum.samples) ** 2.) ;; #part 52 let create () = { sum = 0.; sum_sq = 0.; samples = 0 } let update rsum x = rsum.samples <- rsum.samples + 1; rsum.sum <- rsum.sum +. x; rsum.sum_sq <- rsum.sum_sq +. x *. x ;; #part 53 let rsum = create ();; List.iter [1.;3.;2.;-7.;4.;5.] ~f:(fun x -> update rsum x);; mean rsum;; stdev rsum;; #part 54 let x = { contents = 0 };; x.contents <- x.contents + 1;; x;; #part 55 let x = ref 0 (* create a ref, i.e., { contents = 0 } *) ;; !x (* get the contents of a ref, i.e., x.contents *) ;; x := !x + 1 (* assignment, i.e., x.contents <- ... *) ;; !x ;; #part 56 type 'a ref = { mutable contents : 'a } let ref x = { contents = x } let (!) r = r.contents let (:=) r x = r.contents <- x ;; #part 57 let sum list = let sum = ref 0 in List.iter list ~f:(fun x -> sum := !sum + x); !sum ;; #part 58 let permute array = let length = Array.length array in for i = 0 to length - 2 do (* pick a j that is after i and before the end of the array *) let j = i + 1 + Random.int (length - i - 1) in (* Swap i and j *) let tmp = array.(i) in array.(i) <- array.(j); array.(j) <- tmp done ;; #part 59 let ar = Array.init 20 ~f:(fun i -> i);; permute ar;; ar;; #part 60 let find_first_negative_entry array = let pos = ref 0 in while !pos < Array.length array && array.(!pos) >= 0 do pos := !pos + 1 done; if !pos = Array.length array then None else Some !pos ;; find_first_negative_entry [|1;2;0;3|];; find_first_negative_entry [|1;-2;0;3|];; #part 61 let find_first_negative_entry array = let pos = ref 0 in while let pos_is_good = !pos < Array.length array in let element_is_non_negative = array.(!pos) >= 0 in pos_is_good && element_is_non_negative do pos := !pos + 1 done; if !pos = Array.length array then None else Some !pos ;; find_first_negative_entry [|1;2;0;3|];; #part 62 #part 63 ================================================ FILE: code/guided-tour/recursion.ml ================================================ sum [1;2;3] = 1 + sum [2;3] = 1 + (2 + sum [3]) = 1 + (2 + (3 + sum [])) = 1 + (2 + (3 + 0)) = 1 + (2 + 3) = 1 + 5 = 6 ================================================ FILE: code/guided-tour/run_sum.sh ================================================ ./sum.native ================================================ FILE: code/guided-tour/sum.ml ================================================ open Core.Std let rec read_and_accumulate accum = let line = In_channel.input_line In_channel.stdin in match line with | None -> accum | Some x -> read_and_accumulate (accum +. Float.of_string x) let () = printf "Total: %F\n" (read_and_accumulate 0.) ================================================ FILE: code/guided-tour/sum.rawsh ================================================ $ ./sum.native 1 2 3 94.5 Total: 100.5 ================================================ FILE: code/imperative-programming/.gitignore ================================================ numbers.txt ================================================ FILE: code/imperative-programming/array-get.syntax ================================================ .() ================================================ FILE: code/imperative-programming/array-set.syntax ================================================ .() <- ================================================ FILE: code/imperative-programming/bigarray.syntax ================================================ .{} .{} <- ================================================ FILE: code/imperative-programming/build_all.sh ================================================ corebuild dictionary.cmo corebuild dlist.cmo corebuild time_converter.byte corebuild time_converter2.byte ================================================ FILE: code/imperative-programming/dictionary.ml ================================================ (* part 1 *) (* file: dictionary.ml *) open Core.Std type ('a, 'b) t = { mutable length: int; buckets: ('a * 'b) list array; } (* part 2 *) let num_buckets = 17 let hash_bucket key = (Hashtbl.hash key) mod num_buckets let create () = { length = 0; buckets = Array.create ~len:num_buckets []; } let length t = t.length let find t key = List.find_map t.buckets.(hash_bucket key) ~f:(fun (key',data) -> if key' = key then Some data else None) (* part 3 *) let iter t ~f = for i = 0 to Array.length t.buckets - 1 do List.iter t.buckets.(i) ~f:(fun (key, data) -> f ~key ~data) done (* part 4 *) let bucket_has_key t i key = List.exists t.buckets.(i) ~f:(fun (key',_) -> key' = key) let add t ~key ~data = let i = hash_bucket key in let replace = bucket_has_key t i key in let filtered_bucket = if replace then List.filter t.buckets.(i) ~f:(fun (key',_) -> key' <> key) else t.buckets.(i) in t.buckets.(i) <- (key, data) :: filtered_bucket; if not replace then t.length <- t.length + 1 let remove t key = let i = hash_bucket key in if bucket_has_key t i key then ( let filtered_bucket = List.filter t.buckets.(i) ~f:(fun (key',_) -> key' <> key) in t.buckets.(i) <- filtered_bucket; t.length <- t.length - 1 ) ================================================ FILE: code/imperative-programming/dictionary.mli ================================================ (* part 1 *) (* file: dictionary.mli *) open Core.Std type ('a, 'b) t val create : unit -> ('a, 'b) t val length : ('a, 'b) t -> int val add : ('a, 'b) t -> key:'a -> data:'b -> unit val find : ('a, 'b) t -> 'a -> 'b option val iter : ('a, 'b) t -> f:(key:'a -> data:'b -> unit) -> unit val remove : ('a, 'b) t -> 'a -> unit ================================================ FILE: code/imperative-programming/dictionary2.ml ================================================ open Core.Std type ('a, 'b) t = { mutable length: int; buckets: ('a * 'b) list array; } let num_buckets = 17 let hash_bucket key = (Hashtbl.hash key) mod num_buckets let create () = { length = 0; buckets = Array.create ~len:num_buckets []; } let length t = t.length let find t key = List.find_map t.buckets.(hash_bucket key) ~f:(fun (key',data) -> if key' = key then Some data else None) let iter t ~f = for i = 0 to Array.length t.buckets - 1 do List.iter t.buckets.(i) ~f:(fun (key, data) -> f ~key ~data) done let bucket_has_key t i key = List.exists t.buckets.(i) ~f:(fun (key',_) -> key' = key) let add t ~key ~data = let i = hash_bucket key in let replace = bucket_has_key t i key in let filtered_bucket = if replace then List.filter t.buckets.(i) ~f:(fun (key',_) -> key' <> key) else t.buckets.(i) in (* part 1 *) let () = t.buckets.(i) <- (key, data) :: filtered_bucket in if not replace then t.length <- t.length + 1 (* part 2 *) let remove t key = let i = hash_bucket key in if bucket_has_key t i key then ( let filtered_bucket = List.filter t.buckets.(i) ~f:(fun (key',_) -> key' <> key) in t.buckets.(i) <- filtered_bucket; t.length <- t.length - 1 ) ================================================ FILE: code/imperative-programming/dlist.ml ================================================ (* part 1 *) (* file: dlist.ml *) open Core.Std type 'a element = { value : 'a; mutable next : 'a element option; mutable prev : 'a element option } type 'a t = 'a element option ref (* part 2 *) let create () = ref None let is_empty t = !t = None let value elt = elt.value let first t = !t let next elt = elt.next let prev elt = elt.prev (* part 3 *) let insert_first t value = let new_elt = { prev = None; next = !t; value } in begin match !t with | Some old_first -> old_first.prev <- Some new_elt | None -> () end; t := Some new_elt; new_elt (* part 4 *) let insert_after elt value = let new_elt = { value; prev = Some elt; next = elt.next } in begin match elt.next with | Some old_next -> old_next.prev <- Some new_elt | None -> () end; elt.next <- Some new_elt; new_elt (* part 5 *) let remove t elt = let { prev; next; _ } = elt in begin match prev with | Some prev -> prev.next <- next | None -> t := next end; begin match next with | Some next -> next.prev <- prev; | None -> () end; elt.prev <- None; elt.next <- None (* part 6 *) let iter t ~f = let rec loop = function | None -> () | Some el -> f (value el); loop (next el) in loop !t let find_el t ~f = let rec loop = function | None -> None | Some elt -> if f (value elt) then Some elt else loop (next elt) in loop !t ================================================ FILE: code/imperative-programming/dlist.mli ================================================ (* file: dlist.mli *) open Core.Std type 'a t type 'a element (** Basic list operations *) val create : unit -> 'a t val is_empty : 'a t -> bool (** Navigation using [element]s *) val first : 'a t -> 'a element option val next : 'a element -> 'a element option val prev : 'a element -> 'a element option val value : 'a element -> 'a (** Whole-data-structure iteration *) val iter : 'a t -> f:('a -> unit) -> unit val find_el : 'a t -> f:('a -> bool) -> 'a element option (** Mutation *) val insert_first : 'a t -> 'a -> 'a element val insert_after : 'a element -> 'a -> 'a element val remove : 'a t -> 'a element -> unit ================================================ FILE: code/imperative-programming/edit_distance.ascii ================================================ edit_distance "OCam" "ocaml" edit_distance "OCaml" "ocam" edit_distance "OCam" "ocam" ================================================ FILE: code/imperative-programming/edit_distance2.ascii ================================================ edit_distance "OCam" "ocaml" edit_distance "OCa" "ocaml" edit_distance "OCam" "ocam" edit_distance "OCa" "ocam" edit_distance "OCaml" "ocam" edit_distance "OCam" "ocam" edit_distance "OCaml" "oca" edit_distance "OCam" "oca" edit_distance "OCam" "ocam" edit_distance "OCa" "ocam" edit_distance "OCam" "oca" edit_distance "OCa" "oca" ================================================ FILE: code/imperative-programming/examples.topscript ================================================ 1;; #part 1 List.find_map;; #part 2 let rec endless_loop = 1 :: 2 :: 3 :: endless_loop;; ================================================ FILE: code/imperative-programming/fib.topscript ================================================ let time f = let start = Time.now () in let x = f () in let stop = Time.now () in printf "Time: %s\n" (Time.Span.to_string (Time.diff stop start)); x ;; let memoize f = let table = Hashtbl.Poly.create () in (fun x -> match Hashtbl.find table x with | Some y -> y | None -> let y = f x in Hashtbl.add_exn table ~key:x ~data:y; y );; #part 1 let rec fib i = if i <= 1 then 1 else fib (i - 1) + fib (i - 2);; #part 2 time (fun () -> fib 20);; time (fun () -> fib 40);; #part 3 let fib = memoize fib;; time (fun () -> fib 40);; time (fun () -> fib 40);; #part 4 let fib_norec fib i = if i <= 1 then i else fib (i - 1) + fib (i - 2) ;; #part 5 let rec fib i = fib_norec fib i;; fib 20;; #part 6 let make_rec f_norec = let rec f x = f_norec f x in f ;; let fib = make_rec fib_norec;; fib 20;; #part 7 let memo_rec f_norec x = let fref = ref (fun _ -> assert false) in let f = memoize (fun x -> f_norec !fref x) in fref := f; f x ;; #part 8 let fib = memo_rec fib_norec;; time (fun () -> fib 40);; #part 9 let fib = memo_rec (fun fib i -> if i <= 1 then 1 else fib (i - 1) + fib (i - 2));; ================================================ FILE: code/imperative-programming/file.topscript ================================================ 1;; #part 1 let create_number_file filename numbers = let outc = Out_channel.create filename in List.iter numbers ~f:(fun x -> fprintf outc "%d\n" x); Out_channel.close outc ;; let sum_file filename = let file = In_channel.create filename in let numbers = List.map ~f:Int.of_string (In_channel.input_lines file) in let sum = List.fold ~init:0 ~f:(+) numbers in In_channel.close file; sum ;; create_number_file "numbers.txt" [1;2;3;4;5];; sum_file "numbers.txt";; #part 2 sum_file "/etc/hosts";; #part 3 for i = 1 to 10000 do try ignore (sum_file "/etc/hosts") with _ -> () done;; sum_file "numbers.txt";; ================================================ FILE: code/imperative-programming/file2.topscript ================================================ 1;; #part 1 let sum_file filename = let file = In_channel.create filename in protect ~f:(fun () -> let numbers = List.map ~f:Int.of_string (In_channel.input_lines file) in List.fold ~init:0 ~f:(+) numbers) ~finally:(fun () -> In_channel.close file) ;; #part 2 for i = 1 to 10000 do try ignore (sum_file "/etc/hosts") with _ -> () done;; sum_file "numbers.txt";; #part 3 let sum_file filename = In_channel.with_file filename ~f:(fun file -> let numbers = List.map ~f:Int.of_string (In_channel.input_lines file) in List.fold ~init:0 ~f:(+) numbers) ;; #part 4 let sum_file filename = In_channel.with_file filename ~f:(fun file -> In_channel.fold_lines file ~init:0 ~f:(fun sum line -> sum + Int.of_string line)) ;; ================================================ FILE: code/imperative-programming/for.topscript ================================================ 1;; #part 1 for i = 0 to 3 do printf "i = %d\n" i done;; #part 2 for i = 3 downto 0 do printf "i = %d\n" i done;; #part 3 let rev_inplace ar = let i = ref 0 in let j = ref (Array.length ar - 1) in (* terminate when the upper and lower indices meet *) while !i < !j do (* swap the two elements *) let tmp = ar.(!i) in ar.(!i) <- ar.(!j); ar.(!j) <- tmp; (* bump the indices *) incr i; decr j done ;; let nums = [|1;2;3;4;5|];; rev_inplace nums;; nums;; ================================================ FILE: code/imperative-programming/lazy.topscript ================================================ 1;; #part 1 let v = lazy (print_string "performing lazy computation\n"; sqrt 16.);; Lazy.force v;; Lazy.force v;; #part 2 type 'a lazy_state = | Delayed of (unit -> 'a) | Value of 'a | Exn of exn ;; #part 3 let create_lazy f = ref (Delayed f);; let v = create_lazy (fun () -> print_string "performing lazy computation\n"; sqrt 16.);; #part 4 let force v = match !v with | Value x -> x | Exn e -> raise e | Delayed f -> try let x = f () in v := Value x; x with exn -> v := Exn exn; raise exn ;; #part 5 force v;; force v;; ================================================ FILE: code/imperative-programming/let-unit.syntax ================================================ let () = in let () = in ... ================================================ FILE: code/imperative-programming/let_rec.ml ================================================ let rec x = x + 1 ================================================ FILE: code/imperative-programming/letrec.topscript ================================================ let time f = let start = Time.now () in let x = f () in let stop = Time.now () in printf "Time: %s\n" (Time.Span.to_string (Time.diff stop start)); x ;; let memoize f = let table = Hashtbl.Poly.create () in (fun x -> match Hashtbl.find table x with | Some y -> y | None -> let y = f x in Hashtbl.add_exn table ~key:x ~data:y; y );; #part 1 let memo_rec f_norec = let rec f = memoize (fun x -> f_norec f x) in f ;; #part 2 let rec x = lazy (Lazy.force x + 1);; #part 3 Lazy.force x;; #part 4 let fib_norec fib i = if i <= 1 then i else fib (i - 1) + fib (i - 2) ;; #part 5 let lazy_memo_rec f_norec x = let rec f = lazy (memoize (fun x -> f_norec (Lazy.force f) x)) in (Lazy.force f) x ;; time (fun () -> lazy_memo_rec fib_norec 40);; ================================================ FILE: code/imperative-programming/memo.topscript ================================================ 1;; #part 1 let memoize f = let table = Hashtbl.Poly.create () in (fun x -> match Hashtbl.find table x with | Some y -> y | None -> let y = f x in Hashtbl.add_exn table ~key:x ~data:y; y );; #part 2 let rec edit_distance s t = match String.length s, String.length t with | (0,x) | (x,0) -> x | (len_s,len_t) -> let s' = String.drop_suffix s 1 in let t' = String.drop_suffix t 1 in let cost_to_drop_both = if s.[len_s - 1] = t.[len_t - 1] then 0 else 1 in List.reduce_exn ~f:Int.min [ edit_distance s' t + 1 ; edit_distance s t' + 1 ; edit_distance s' t' + cost_to_drop_both ] ;; edit_distance "OCaml" "ocaml";; #part 3 let time f = let start = Time.now () in let x = f () in let stop = Time.now () in printf "Time: %s\n" (Time.Span.to_string (Time.diff stop start)); x ;; #part 4 time (fun () -> edit_distance "OCaml" "ocaml");; time (fun () -> edit_distance "OCaml 4.01" "ocaml 4.01");; #part 5 let memo_rec f_norec x = let fref = ref (fun _ -> assert false) in let f = memoize (fun x -> f_norec !fref x) in fref := f; f x ;; #part 6 let edit_distance = memo_rec (fun edit_distance (s,t) -> match String.length s, String.length t with | (0,x) | (x,0) -> x | (len_s,len_t) -> let s' = String.drop_suffix s 1 in let t' = String.drop_suffix t 1 in let cost_to_drop_both = if s.[len_s - 1] = t.[len_t - 1] then 0 else 1 in List.reduce_exn ~f:Int.min [ edit_distance (s',t ) + 1 ; edit_distance (s ,t') + 1 ; edit_distance (s',t') + cost_to_drop_both ]) ;; #part 7 time (fun () -> edit_distance ("OCaml 4.01","ocaml 4.01"));; ================================================ FILE: code/imperative-programming/order.topscript ================================================ 1;; #part 1 let x = sin 120. in let y = sin 75. in let z = sin 128. in List.exists ~f:(fun x -> x < 0.) [x;y;z] ;; #part 2 let x = lazy (sin 120.) in let y = lazy (sin 75.) in let z = lazy (sin 128.) in List.exists ~f:(fun x -> Lazy.force x < 0.) [x;y;z] ;; #part 3 let x = lazy (printf "1\n"; sin 120.) in let y = lazy (printf "2\n"; sin 75.) in let z = lazy (printf "3\n"; sin 128.) in List.exists ~f:(fun x -> Lazy.force x < 0.) [x;y;z] ;; #part 4 List.exists ~f:(fun x -> x < 0.) [ (printf "1\n"; sin 120.); (printf "2\n"; sin 75.); (printf "3\n"; sin 128.); ] ;; ================================================ FILE: code/imperative-programming/printf.topscript ================================================ open Printf 1;; #part 1 printf "%i is an integer, %F is a float, \"%s\" is a string\n" 3 4.5 "five";; #part 2 printf "An integer: %i\n" 4.5;; #part 3 let fmt = "%i is an integer, %F is a float, \"%s\" is a string\n";; printf fmt 3 4.5 "five";; #part 4 let fmt : ('a, 'b, 'c) format = "%i is an integer, %F is a float, \"%s\" is a string\n";; #part 5 printf fmt 3 4.5 "five";; ================================================ FILE: code/imperative-programming/ref.topscript ================================================ 1;; #part 1 type 'a ref = { mutable contents : 'a };; #part 2 let ref x = { contents = x };; let (!) r = r.contents;; let (:=) r x = r.contents <- x;; #part 3 let x = ref 1;; !x;; x := !x + 1;; !x;; ================================================ FILE: code/imperative-programming/remember_type.ml ================================================ val remember : '_a -> '_a = ================================================ FILE: code/imperative-programming/semicolon-syntax.syntax ================================================ ; ; ... ================================================ FILE: code/imperative-programming/semicolon.syntax ================================================ ; ; ... ================================================ FILE: code/imperative-programming/string.syntax ================================================ .[] .[] <- ================================================ FILE: code/imperative-programming/time_converter.ml ================================================ open Core.Std let () = Out_channel.output_string stdout "Pick a timezone: "; Out_channel.flush stdout; match In_channel.input_line stdin with | None -> failwith "No timezone provided" | Some zone_string -> let zone = Zone.find_exn zone_string in let time_string = Time.to_string_abs (Time.now ()) ~zone in Out_channel.output_string stdout (String.concat ["The time in ";Zone.to_string zone;" is ";time_string;".\n"]); Out_channel.flush stdout ================================================ FILE: code/imperative-programming/time_converter.rawsh ================================================ $ corebuild time_converter.byte $ ./time_converter.byte Pick a timezone: ================================================ FILE: code/imperative-programming/time_converter2.ml ================================================ open Core.Std let () = printf "Pick a timezone: %!"; match In_channel.input_line stdin with | None -> failwith "No timezone provided" | Some zone_string -> let zone = Time.Zone.find_exn zone_string in let time_string = Time.to_string_abs (Time.now ()) ~zone in printf "The time in %s is %s.\n%!" (Time.Zone.to_string zone) time_string ================================================ FILE: code/imperative-programming/time_converter2.rawsh ================================================ Pick a timezone: Europe/London The time in Europe/London is 2013-08-15 00:03:10.666220+01:00. ================================================ FILE: code/imperative-programming/value_restriction-13.rawscript ================================================ # module Concat_list : sig type 'a t val empty : 'a t val singleton : 'a -> 'a t val concat : 'a t -> 'a t -> 'a t (* constant time *) val to_list : 'a t -> 'a list (* linear time *) end = struct type 'a t = Empty | Singleton of 'a | Concat of 'a t * 'a t ... end;; module Concat_list : sig type 'a t val empty : 'a t val singleton : 'a -> 'a t val concat : 'a t -> 'a t -> 'a t val to_list : 'a t -> 'a list end ================================================ FILE: code/imperative-programming/value_restriction.topscript ================================================ let identity x = x;; let time f = let start = Time.now () in let x = f () in let stop = Time.now () in printf "Time: %s\n" (Time.Span.to_string (Time.diff stop start)); x ;; let memoize f = let table = Hashtbl.Poly.create () in (fun x -> match Hashtbl.find table x with | Some y -> y | None -> let y = f x in Hashtbl.add_exn table ~key:x ~data:y; y );; #part 1 (fun x -> [x;x]);; #part 2 memoize (fun x -> [x;x]);; #part 3 identity (fun x -> [x;x]);; #part 4 let f () = ref None;; #part 5 List.init;; List.init 10 ~f:Int.to_string;; #part 6 let list_init_10 = List.init 10;; #part 7 let list_init_10 ~f = List.init 10 ~f;; #part 8 identity (fun x -> [x;x]);; #part 9 identity [];; #part 10 [||];; identity [||];; #part 11 module Concat_list : sig type 'a t val empty : 'a t val singleton : 'a -> 'a t val concat : 'a t -> 'a t -> 'a t (* constant time *) val to_list : 'a t -> 'a list (* linear time *) end = struct type 'a t = Empty | Singleton of 'a | Concat of 'a t * 'a t let empty = Empty let singleton x = Singleton x let concat x y = Concat (x,y) let rec to_list_with_tail t tail = match t with | Empty -> tail | Singleton x -> x :: tail | Concat (x,y) -> to_list_with_tail x (to_list_with_tail y tail) let to_list t = to_list_with_tail t [] end;; #part 12 Concat_list.empty;; identity Concat_list.empty;; #part 13 module Concat_list : sig type +'a t val empty : 'a t val singleton : 'a -> 'a t val concat : 'a t -> 'a t -> 'a t (* constant time *) val to_list : 'a t -> 'a list (* linear time *) end = struct type 'a t = Empty | Singleton of 'a | Concat of 'a t * 'a t let empty = Empty let singleton x = Singleton x let concat x y = Concat (x,y) let rec to_list_with_tail t tail = match t with | Empty -> tail | Singleton x -> x :: tail | Concat (x,y) -> to_list_with_tail x (to_list_with_tail y tail) let to_list t = to_list_with_tail t [] end;; #part 14 identity Concat_list.empty;; ================================================ FILE: code/imperative-programming/weak.topscript ================================================ 1;; #part 1 let remember = let cache = ref None in (fun x -> match !cache with | Some y -> y | None -> cache := Some x; x) ;; #part 2 let identity x = x;; identity 3;; identity "five";; #part 3 let remember_three () = remember 3;; remember;; remember "avocado";; ================================================ FILE: code/installation/arch_install.rawsh ================================================ # pacman -Sy ocaml ================================================ FILE: code/installation/arch_opam.rawsh ================================================ $ sudo pacman -Sy base-devel $ wget https://aur.archlinux.org/packages/op/opam/opam.tar.gz $ tar -xvf opam.tar.gz && cd opam $ makepkg $ sudo pacman -U opam-.tar.gz ================================================ FILE: code/installation/brew_install.rawsh ================================================ $ brew update $ brew install ocaml $ brew install pcre ================================================ FILE: code/installation/brew_opam_install.rawsh ================================================ $ brew update $ brew install opam ================================================ FILE: code/installation/debian_apt.rawsh ================================================ # apt-get install \ ocaml ocaml-native-compilers camlp4-extra \ git libpcre3-dev curl build-essential m4 ================================================ FILE: code/installation/debian_apt_opam.rawsh ================================================ # apt-get update # apt-get -t unstable install opam ================================================ FILE: code/installation/emacsrc.scm ================================================ (autoload 'utop "utop" "Toplevel for OCaml" t) ================================================ FILE: code/installation/fedora_install.rawsh ================================================ # yum install ocaml # yum install ocaml-camlp4-devel # yum install pcre-devel ================================================ FILE: code/installation/macports_install.rawsh ================================================ $ sudo port install ocaml $ sudo port install ocaml-pcre ================================================ FILE: code/installation/macports_opam_install.rawsh ================================================ $ sudo port install opam ================================================ FILE: code/installation/ocaml_src_install.rawsh ================================================ $ curl -OL https://github.com/ocaml/ocaml/archive/4.01.tar.gz $ tar -zxvf 4.01.tar.gz $ cd ocaml-4.01 $ ./configure $ make world world.opt $ sudo make install ================================================ FILE: code/installation/ocaml_user_conf.rawsh ================================================ $ ./configure -prefix $HOME/my-ocaml ================================================ FILE: code/installation/opam_eval.rawsh ================================================ $ eval `opam config env` ================================================ FILE: code/installation/opam_init.rawsh ================================================ $ opam init <...> =-=-=-= Configuring OPAM =-=-=-= Do you want to update your configuration to use OPAM ? [Y/n] y [1/4] Do you want to update your shell configuration file ? [default: ~/.profile] y [2/4] Do you want to update your ~/.ocamlinit ? [Y/n] y [3/4] Do you want to install the auto-complete scripts ? [Y/n] y [4/4] Do you want to install the `opam-switch-eval` script ? [Y/n] y User configuration: ~/.ocamlinit is already up-to-date. ~/.profile is already up-to-date. Gloabal configuration: Updating /opam-init/init.sh auto-completion : [true] opam-switch-eval: [true] Updating /opam-init/init.zsh auto-completion : [true] opam-switch-eval: [true] Updating /opam-init/init.csh auto-completion : [true] opam-switch-eval: [true] ================================================ FILE: code/installation/opam_install.rawsh ================================================ $ opam install core core_extended core_bench async ================================================ FILE: code/installation/opam_install_utop.rawsh ================================================ $ opam install utop ================================================ FILE: code/installation/opam_list.rawsh ================================================ $ opam list Installed packages for 4.01.0: async 109.38.00 Monadic concurrency library async_core 109.38.00 Monadic concurrency library async_extra 109.38.00 Monadic concurrency library <...> ================================================ FILE: code/installation/opam_switch.rawsh ================================================ $ opam switch 4.01.0dev+trunk $ eval `opam config env` ================================================ FILE: code/installation/open_core.ml ================================================ open Core.Std ================================================ FILE: code/installation/show_ocamlinit.rawsh ================================================ $ cat ~/.ocamlinit #use "topfind" #thread #camlp4o #require "core.top" #require "core.syntax" ================================================ FILE: code/installation/ubuntu_opam_ppa.rawsh ================================================ $ add-apt-repository ppa:avsm/ppa $ apt-get update $ apt-get install ocaml opam ================================================ FILE: code/json/_tags ================================================ true: -warn_32 ================================================ FILE: code/json/book.json ================================================ { "title": "Real World OCaml", "tags" : [ "functional programming", "ocaml", "algorithms" ], "pages": 450, "authors": [ { "name": "Jason Hickey", "affiliation": "Google" }, { "name": "Anil Madhavapeddy", "affiliation": "Cambridge"}, { "name": "Yaron Minsky", "affiliation": "Jane Street"} ], "is_online": true } ================================================ FILE: code/json/build_github_atd.sh ================================================ atdgen -t github.atd atdgen -j github.atd ocamlfind ocamlc -package atd -i github_t.mli ================================================ FILE: code/json/build_github_org.sh ================================================ atdgen -t github_org.atd atdgen -j github_org.atd corebuild -pkg core_extended,yojson,atdgen github_org_info.native ================================================ FILE: code/json/build_json.topscript ================================================ #require "yojson" ;; open Core.Std ;; #part 1 let person = `Assoc [ ("name", `String "Anil") ] ;; #part 2 Yojson.Basic.pretty_to_string ;; #part 3 Yojson.Basic.pretty_to_string person ;; Yojson.Basic.pretty_to_channel stdout person ;; #part 4 let person = `Assoc ("name", `String "Anil");; Yojson.Basic.pretty_to_string person ;; #part 5 let (person : Yojson.Basic.json) = `Assoc ("name", `String "Anil");; ================================================ FILE: code/json/generate_github_org_json.sh ================================================ atdgen -j github_org.atd cat github_org_j.mli ================================================ FILE: code/json/generate_github_org_types.sh ================================================ atdgen -t github_org.atd cat github_org_t.mli ================================================ FILE: code/json/github.atd ================================================ type scope = [ User | Public_repo | Repo | Repo_status | Delete_repo | Gist ] type app = { name: string; url: string; } type authorization_request = { scopes: scope list; note: string; } type authorization_response = { scopes: scope list; token: string; app: app; url: string; id: int; ?note: string option; ?note_url: string option; } ================================================ FILE: code/json/github_j.ml ================================================ (* Auto-generated from "github.atd" *) type scope = Github_t.scope type app = Github_t.app = { app_name (*atd name *): string; app_url (*atd url *): string } type authorization_request = Github_t.authorization_request = { auth_req_scopes (*atd scopes *): scope list; auth_req_note (*atd note *): string } type authorization_response = Github_t.authorization_response = { scopes: scope list; token: string; app: app; url: string; id: int; note: string option; note_url: string option } let write_scope = ( fun ob x -> match x with | `User -> Bi_outbuf.add_string ob "<\"user\">" | `Public_repo -> Bi_outbuf.add_string ob "<\"public_repo\">" | `Repo -> Bi_outbuf.add_string ob "<\"repo\">" | `Repo_status -> Bi_outbuf.add_string ob "<\"repo_status\">" | `Delete_repo -> Bi_outbuf.add_string ob "<\"delete_repo\">" | `Gist -> Bi_outbuf.add_string ob "<\"gist\">" ) let string_of_scope ?(len = 1024) x = let ob = Bi_outbuf.create len in write_scope ob x; Bi_outbuf.contents ob let read_scope = ( fun p lb -> Yojson.Safe.read_space p lb; match Yojson.Safe.start_any_variant p lb with | `Edgy_bracket -> ( Yojson.Safe.read_space p lb; let f = fun s pos len -> if pos < 0 || len < 0 || pos + len > String.length s then invalid_arg "out-of-bounds substring position or length"; try match len with | 4 -> ( match String.unsafe_get s pos with | 'g' -> ( if String.unsafe_get s (pos+1) = 'i' && String.unsafe_get s (pos+2) = 's' && String.unsafe_get s (pos+3) = 't' then ( 5 ) else ( raise (Exit) ) ) | 'r' -> ( if String.unsafe_get s (pos+1) = 'e' && String.unsafe_get s (pos+2) = 'p' && String.unsafe_get s (pos+3) = 'o' then ( 2 ) else ( raise (Exit) ) ) | 'u' -> ( if String.unsafe_get s (pos+1) = 's' && String.unsafe_get s (pos+2) = 'e' && String.unsafe_get s (pos+3) = 'r' then ( 0 ) else ( raise (Exit) ) ) | _ -> ( raise (Exit) ) ) | 11 -> ( match String.unsafe_get s pos with | 'd' -> ( 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 ( 4 ) else ( raise (Exit) ) ) | 'p' -> ( 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 ( 1 ) else ( raise (Exit) ) ) | 'r' -> ( 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 ( 3 ) else ( raise (Exit) ) ) | _ -> ( raise (Exit) ) ) | _ -> ( raise (Exit) ) with Exit -> ( Ag_oj_run.invalid_variant_tag (String.sub s pos len) ) in let i = Yojson.Safe.map_ident p f lb in match i with | 0 -> Yojson.Safe.read_space p lb; Yojson.Safe.read_gt p lb; `User | 1 -> Yojson.Safe.read_space p lb; Yojson.Safe.read_gt p lb; `Public_repo | 2 -> Yojson.Safe.read_space p lb; Yojson.Safe.read_gt p lb; `Repo | 3 -> Yojson.Safe.read_space p lb; Yojson.Safe.read_gt p lb; `Repo_status | 4 -> Yojson.Safe.read_space p lb; Yojson.Safe.read_gt p lb; `Delete_repo | 5 -> Yojson.Safe.read_space p lb; Yojson.Safe.read_gt p lb; `Gist | _ -> ( assert false ) ) | `Double_quote -> ( let f = fun s pos len -> if pos < 0 || len < 0 || pos + len > String.length s then invalid_arg "out-of-bounds substring position or length"; try match len with | 4 -> ( match String.unsafe_get s pos with | 'g' -> ( if String.unsafe_get s (pos+1) = 'i' && String.unsafe_get s (pos+2) = 's' && String.unsafe_get s (pos+3) = 't' then ( 5 ) else ( raise (Exit) ) ) | 'r' -> ( if String.unsafe_get s (pos+1) = 'e' && String.unsafe_get s (pos+2) = 'p' && String.unsafe_get s (pos+3) = 'o' then ( 2 ) else ( raise (Exit) ) ) | 'u' -> ( if String.unsafe_get s (pos+1) = 's' && String.unsafe_get s (pos+2) = 'e' && String.unsafe_get s (pos+3) = 'r' then ( 0 ) else ( raise (Exit) ) ) | _ -> ( raise (Exit) ) ) | 11 -> ( match String.unsafe_get s pos with | 'd' -> ( 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 ( 4 ) else ( raise (Exit) ) ) | 'p' -> ( 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 ( 1 ) else ( raise (Exit) ) ) | 'r' -> ( 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 ( 3 ) else ( raise (Exit) ) ) | _ -> ( raise (Exit) ) ) | _ -> ( raise (Exit) ) with Exit -> ( Ag_oj_run.invalid_variant_tag (String.sub s pos len) ) in let i = Yojson.Safe.map_string p f lb in match i with | 0 -> `User | 1 -> `Public_repo | 2 -> `Repo | 3 -> `Repo_status | 4 -> `Delete_repo | 5 -> `Gist | _ -> ( assert false ) ) | `Square_bracket -> ( Yojson.Safe.read_space p lb; let f = fun s pos len -> if pos < 0 || len < 0 || pos + len > String.length s then invalid_arg "out-of-bounds substring position or length"; Ag_oj_run.invalid_variant_tag (String.sub s pos len) in let i = Yojson.Safe.map_ident p f lb in match i with | _ -> ( assert false ) ) ) let scope_of_string s = read_scope (Yojson.Safe.init_lexer ()) (Lexing.from_string s) let write_app = ( fun ob x -> Bi_outbuf.add_char ob '{'; let is_first = ref true in if !is_first then is_first := false else Bi_outbuf.add_char ob ','; Bi_outbuf.add_string ob "\"name\":"; ( Yojson.Safe.write_string ) ob x.app_name; if !is_first then is_first := false else Bi_outbuf.add_char ob ','; Bi_outbuf.add_string ob "\"url\":"; ( Yojson.Safe.write_string ) ob x.app_url; Bi_outbuf.add_char ob '}'; ) let string_of_app ?(len = 1024) x = let ob = Bi_outbuf.create len in write_app ob x; Bi_outbuf.contents ob let read_app = ( fun p lb -> Yojson.Safe.read_space p lb; Yojson.Safe.read_lcurl p lb; let x = { app_name = Obj.magic 0.0; app_url = Obj.magic 0.0; } in let bits0 = ref 0 in try Yojson.Safe.read_space p lb; Yojson.Safe.read_object_end lb; Yojson.Safe.read_space p lb; let f = fun s pos len -> if pos < 0 || len < 0 || pos + len > String.length s then invalid_arg "out-of-bounds substring position or length"; match len with | 3 -> ( if String.unsafe_get s pos = 'u' && String.unsafe_get s (pos+1) = 'r' && String.unsafe_get s (pos+2) = 'l' then ( 1 ) else ( -1 ) ) | 4 -> ( 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 ( 0 ) else ( -1 ) ) | _ -> ( -1 ) in let i = Yojson.Safe.map_ident p f lb in Ag_oj_run.read_until_field_value p lb; ( match i with | 0 -> let v = ( Ag_oj_run.read_string ) p lb in Obj.set_field (Obj.repr x) 0 (Obj.repr v); bits0 := !bits0 lor 0x1; | 1 -> let v = ( Ag_oj_run.read_string ) p lb in Obj.set_field (Obj.repr x) 1 (Obj.repr v); bits0 := !bits0 lor 0x2; | _ -> ( Yojson.Safe.skip_json p lb ) ); while true do Yojson.Safe.read_space p lb; Yojson.Safe.read_object_sep p lb; Yojson.Safe.read_space p lb; let f = fun s pos len -> if pos < 0 || len < 0 || pos + len > String.length s then invalid_arg "out-of-bounds substring position or length"; match len with | 3 -> ( if String.unsafe_get s pos = 'u' && String.unsafe_get s (pos+1) = 'r' && String.unsafe_get s (pos+2) = 'l' then ( 1 ) else ( -1 ) ) | 4 -> ( 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 ( 0 ) else ( -1 ) ) | _ -> ( -1 ) in let i = Yojson.Safe.map_ident p f lb in Ag_oj_run.read_until_field_value p lb; ( match i with | 0 -> let v = ( Ag_oj_run.read_string ) p lb in Obj.set_field (Obj.repr x) 0 (Obj.repr v); bits0 := !bits0 lor 0x1; | 1 -> let v = ( Ag_oj_run.read_string ) p lb in Obj.set_field (Obj.repr x) 1 (Obj.repr v); bits0 := !bits0 lor 0x2; | _ -> ( Yojson.Safe.skip_json p lb ) ); done; assert false; with Yojson.End_of_object -> ( if !bits0 <> 0x3 then Ag_oj_run.missing_fields [| !bits0 |] [| "name"; "url" |]; Ag_oj_run.identity x ) ) let app_of_string s = read_app (Yojson.Safe.init_lexer ()) (Lexing.from_string s) let write__1 = ( Ag_oj_run.write_list ( write_scope ) ) let string_of__1 ?(len = 1024) x = let ob = Bi_outbuf.create len in write__1 ob x; Bi_outbuf.contents ob let read__1 = ( Ag_oj_run.read_list ( read_scope ) ) let _1_of_string s = read__1 (Yojson.Safe.init_lexer ()) (Lexing.from_string s) let write_authorization_request = ( fun ob x -> Bi_outbuf.add_char ob '{'; let is_first = ref true in if !is_first then is_first := false else Bi_outbuf.add_char ob ','; Bi_outbuf.add_string ob "\"scopes\":"; ( write__1 ) ob x.auth_req_scopes; if !is_first then is_first := false else Bi_outbuf.add_char ob ','; Bi_outbuf.add_string ob "\"note\":"; ( Yojson.Safe.write_string ) ob x.auth_req_note; Bi_outbuf.add_char ob '}'; ) let string_of_authorization_request ?(len = 1024) x = let ob = Bi_outbuf.create len in write_authorization_request ob x; Bi_outbuf.contents ob let read_authorization_request = ( fun p lb -> Yojson.Safe.read_space p lb; Yojson.Safe.read_lcurl p lb; let x = { auth_req_scopes = Obj.magic 0.0; auth_req_note = Obj.magic 0.0; } in let bits0 = ref 0 in try Yojson.Safe.read_space p lb; Yojson.Safe.read_object_end lb; Yojson.Safe.read_space p lb; let f = fun s pos len -> if pos < 0 || len < 0 || pos + len > String.length s then invalid_arg "out-of-bounds substring position or length"; match len with | 4 -> ( 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 ( 1 ) else ( -1 ) ) | 6 -> ( 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 ( 0 ) else ( -1 ) ) | _ -> ( -1 ) in let i = Yojson.Safe.map_ident p f lb in Ag_oj_run.read_until_field_value p lb; ( match i with | 0 -> let v = ( read__1 ) p lb in Obj.set_field (Obj.repr x) 0 (Obj.repr v); bits0 := !bits0 lor 0x1; | 1 -> let v = ( Ag_oj_run.read_string ) p lb in Obj.set_field (Obj.repr x) 1 (Obj.repr v); bits0 := !bits0 lor 0x2; | _ -> ( Yojson.Safe.skip_json p lb ) ); while true do Yojson.Safe.read_space p lb; Yojson.Safe.read_object_sep p lb; Yojson.Safe.read_space p lb; let f = fun s pos len -> if pos < 0 || len < 0 || pos + len > String.length s then invalid_arg "out-of-bounds substring position or length"; match len with | 4 -> ( 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 ( 1 ) else ( -1 ) ) | 6 -> ( 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 ( 0 ) else ( -1 ) ) | _ -> ( -1 ) in let i = Yojson.Safe.map_ident p f lb in Ag_oj_run.read_until_field_value p lb; ( match i with | 0 -> let v = ( read__1 ) p lb in Obj.set_field (Obj.repr x) 0 (Obj.repr v); bits0 := !bits0 lor 0x1; | 1 -> let v = ( Ag_oj_run.read_string ) p lb in Obj.set_field (Obj.repr x) 1 (Obj.repr v); bits0 := !bits0 lor 0x2; | _ -> ( Yojson.Safe.skip_json p lb ) ); done; assert false; with Yojson.End_of_object -> ( if !bits0 <> 0x3 then Ag_oj_run.missing_fields [| !bits0 |] [| "scopes"; "note" |]; Ag_oj_run.identity x ) ) let authorization_request_of_string s = read_authorization_request (Yojson.Safe.init_lexer ()) (Lexing.from_string s) let write__2 = ( Ag_oj_run.write_option ( Yojson.Safe.write_string ) ) let string_of__2 ?(len = 1024) x = let ob = Bi_outbuf.create len in write__2 ob x; Bi_outbuf.contents ob let read__2 = ( fun p lb -> Yojson.Safe.read_space p lb; match Yojson.Safe.start_any_variant p lb with | `Edgy_bracket -> ( Yojson.Safe.read_space p lb; let f = fun s pos len -> if pos < 0 || len < 0 || pos + len > String.length s then invalid_arg "out-of-bounds substring position or length"; try if len = 4 then ( match String.unsafe_get s pos with | 'N' -> ( if String.unsafe_get s (pos+1) = 'o' && String.unsafe_get s (pos+2) = 'n' && String.unsafe_get s (pos+3) = 'e' then ( 0 ) else ( raise (Exit) ) ) | 'S' -> ( if String.unsafe_get s (pos+1) = 'o' && String.unsafe_get s (pos+2) = 'm' && String.unsafe_get s (pos+3) = 'e' then ( 1 ) else ( raise (Exit) ) ) | _ -> ( raise (Exit) ) ) else ( raise (Exit) ) with Exit -> ( Ag_oj_run.invalid_variant_tag (String.sub s pos len) ) in let i = Yojson.Safe.map_ident p f lb in match i with | 0 -> Yojson.Safe.read_space p lb; Yojson.Safe.read_gt p lb; None | 1 -> Ag_oj_run.read_until_field_value p lb; let x = ( Ag_oj_run.read_string ) p lb in Yojson.Safe.read_space p lb; Yojson.Safe.read_gt p lb; Some x | _ -> ( assert false ) ) | `Double_quote -> ( let f = fun s pos len -> if pos < 0 || len < 0 || pos + len > String.length s then invalid_arg "out-of-bounds substring position or length"; try 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 ( 0 ) else ( raise (Exit) ) with Exit -> ( Ag_oj_run.invalid_variant_tag (String.sub s pos len) ) in let i = Yojson.Safe.map_string p f lb in match i with | 0 -> None | _ -> ( assert false ) ) | `Square_bracket -> ( Yojson.Safe.read_space p lb; let f = fun s pos len -> if pos < 0 || len < 0 || pos + len > String.length s then invalid_arg "out-of-bounds substring position or length"; try 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 ( 0 ) else ( raise (Exit) ) with Exit -> ( Ag_oj_run.invalid_variant_tag (String.sub s pos len) ) in let i = Yojson.Safe.map_ident p f lb in match i with | 0 -> Yojson.Safe.read_space p lb; Yojson.Safe.read_comma p lb; Yojson.Safe.read_space p lb; let x = ( Ag_oj_run.read_string ) p lb in Yojson.Safe.read_space p lb; Yojson.Safe.read_rbr p lb; Some x | _ -> ( assert false ) ) ) let _2_of_string s = read__2 (Yojson.Safe.init_lexer ()) (Lexing.from_string s) let write_authorization_response = ( fun ob x -> Bi_outbuf.add_char ob '{'; let is_first = ref true in if !is_first then is_first := false else Bi_outbuf.add_char ob ','; Bi_outbuf.add_string ob "\"scopes\":"; ( write__1 ) ob x.scopes; if !is_first then is_first := false else Bi_outbuf.add_char ob ','; Bi_outbuf.add_string ob "\"token\":"; ( Yojson.Safe.write_string ) ob x.token; if !is_first then is_first := false else Bi_outbuf.add_char ob ','; Bi_outbuf.add_string ob "\"app\":"; ( write_app ) ob x.app; if !is_first then is_first := false else Bi_outbuf.add_char ob ','; Bi_outbuf.add_string ob "\"url\":"; ( Yojson.Safe.write_string ) ob x.url; if !is_first then is_first := false else Bi_outbuf.add_char ob ','; Bi_outbuf.add_string ob "\"id\":"; ( Yojson.Safe.write_int ) ob x.id; (match x.note with None -> () | Some x -> if !is_first then is_first := false else Bi_outbuf.add_char ob ','; Bi_outbuf.add_string ob "\"note\":"; ( Yojson.Safe.write_string ) ob x; ); (match x.note_url with None -> () | Some x -> if !is_first then is_first := false else Bi_outbuf.add_char ob ','; Bi_outbuf.add_string ob "\"note_url\":"; ( Yojson.Safe.write_string ) ob x; ); Bi_outbuf.add_char ob '}'; ) let string_of_authorization_response ?(len = 1024) x = let ob = Bi_outbuf.create len in write_authorization_response ob x; Bi_outbuf.contents ob let read_authorization_response = ( fun p lb -> Yojson.Safe.read_space p lb; Yojson.Safe.read_lcurl p lb; let x = { scopes = Obj.magic 0.0; token = Obj.magic 0.0; app = Obj.magic 0.0; url = Obj.magic 0.0; id = Obj.magic 0.0; note = None; note_url = None; } in let bits0 = ref 0 in try Yojson.Safe.read_space p lb; Yojson.Safe.read_object_end lb; Yojson.Safe.read_space p lb; let f = fun s pos len -> if pos < 0 || len < 0 || pos + len > String.length s then invalid_arg "out-of-bounds substring position or length"; match len with | 2 -> ( if String.unsafe_get s pos = 'i' && String.unsafe_get s (pos+1) = 'd' then ( 4 ) else ( -1 ) ) | 3 -> ( match String.unsafe_get s pos with | 'a' -> ( if String.unsafe_get s (pos+1) = 'p' && String.unsafe_get s (pos+2) = 'p' then ( 2 ) else ( -1 ) ) | 'u' -> ( if String.unsafe_get s (pos+1) = 'r' && String.unsafe_get s (pos+2) = 'l' then ( 3 ) else ( -1 ) ) | _ -> ( -1 ) ) | 4 -> ( 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 ( 5 ) else ( -1 ) ) | 5 -> ( 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 ( 1 ) else ( -1 ) ) | 6 -> ( 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 ( 0 ) else ( -1 ) ) | 8 -> ( 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 ( 6 ) else ( -1 ) ) | _ -> ( -1 ) in let i = Yojson.Safe.map_ident p f lb in Ag_oj_run.read_until_field_value p lb; ( match i with | 0 -> let v = ( read__1 ) p lb in Obj.set_field (Obj.repr x) 0 (Obj.repr v); bits0 := !bits0 lor 0x1; | 1 -> let v = ( Ag_oj_run.read_string ) p lb in Obj.set_field (Obj.repr x) 1 (Obj.repr v); bits0 := !bits0 lor 0x2; | 2 -> let v = ( read_app ) p lb in Obj.set_field (Obj.repr x) 2 (Obj.repr v); bits0 := !bits0 lor 0x4; | 3 -> let v = ( Ag_oj_run.read_string ) p lb in Obj.set_field (Obj.repr x) 3 (Obj.repr v); bits0 := !bits0 lor 0x8; | 4 -> let v = ( Ag_oj_run.read_int ) p lb in Obj.set_field (Obj.repr x) 4 (Obj.repr v); bits0 := !bits0 lor 0x10; | 5 -> if not (Yojson.Safe.read_null_if_possible p lb) then ( let v = Some ( ( Ag_oj_run.read_string ) p lb ) in Obj.set_field (Obj.repr x) 5 (Obj.repr v); ) | 6 -> if not (Yojson.Safe.read_null_if_possible p lb) then ( let v = Some ( ( Ag_oj_run.read_string ) p lb ) in Obj.set_field (Obj.repr x) 6 (Obj.repr v); ) | _ -> ( Yojson.Safe.skip_json p lb ) ); while true do Yojson.Safe.read_space p lb; Yojson.Safe.read_object_sep p lb; Yojson.Safe.read_space p lb; let f = fun s pos len -> if pos < 0 || len < 0 || pos + len > String.length s then invalid_arg "out-of-bounds substring position or length"; match len with | 2 -> ( if String.unsafe_get s pos = 'i' && String.unsafe_get s (pos+1) = 'd' then ( 4 ) else ( -1 ) ) | 3 -> ( match String.unsafe_get s pos with | 'a' -> ( if String.unsafe_get s (pos+1) = 'p' && String.unsafe_get s (pos+2) = 'p' then ( 2 ) else ( -1 ) ) | 'u' -> ( if String.unsafe_get s (pos+1) = 'r' && String.unsafe_get s (pos+2) = 'l' then ( 3 ) else ( -1 ) ) | _ -> ( -1 ) ) | 4 -> ( 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 ( 5 ) else ( -1 ) ) | 5 -> ( 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 ( 1 ) else ( -1 ) ) | 6 -> ( 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 ( 0 ) else ( -1 ) ) | 8 -> ( 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 ( 6 ) else ( -1 ) ) | _ -> ( -1 ) in let i = Yojson.Safe.map_ident p f lb in Ag_oj_run.read_until_field_value p lb; ( match i with | 0 -> let v = ( read__1 ) p lb in Obj.set_field (Obj.repr x) 0 (Obj.repr v); bits0 := !bits0 lor 0x1; | 1 -> let v = ( Ag_oj_run.read_string ) p lb in Obj.set_field (Obj.repr x) 1 (Obj.repr v); bits0 := !bits0 lor 0x2; | 2 -> let v = ( read_app ) p lb in Obj.set_field (Obj.repr x) 2 (Obj.repr v); bits0 := !bits0 lor 0x4; | 3 -> let v = ( Ag_oj_run.read_string ) p lb in Obj.set_field (Obj.repr x) 3 (Obj.repr v); bits0 := !bits0 lor 0x8; | 4 -> let v = ( Ag_oj_run.read_int ) p lb in Obj.set_field (Obj.repr x) 4 (Obj.repr v); bits0 := !bits0 lor 0x10; | 5 -> if not (Yojson.Safe.read_null_if_possible p lb) then ( let v = Some ( ( Ag_oj_run.read_string ) p lb ) in Obj.set_field (Obj.repr x) 5 (Obj.repr v); ) | 6 -> if not (Yojson.Safe.read_null_if_possible p lb) then ( let v = Some ( ( Ag_oj_run.read_string ) p lb ) in Obj.set_field (Obj.repr x) 6 (Obj.repr v); ) | _ -> ( Yojson.Safe.skip_json p lb ) ); done; assert false; with Yojson.End_of_object -> ( if !bits0 <> 0x1f then Ag_oj_run.missing_fields [| !bits0 |] [| "scopes"; "token"; "app"; "url"; "id" |]; Ag_oj_run.identity x ) ) let authorization_response_of_string s = read_authorization_response (Yojson.Safe.init_lexer ()) (Lexing.from_string s) ================================================ FILE: code/json/github_j.mli ================================================ (* Auto-generated from "github.atd" *) type scope = Github_t.scope type app = Github_t.app = { app_name (*atd name *): string; app_url (*atd url *): string } type authorization_request = Github_t.authorization_request = { auth_req_scopes (*atd scopes *): scope list; auth_req_note (*atd note *): string } type authorization_response = Github_t.authorization_response = { scopes: scope list; token: string; app: app; url: string; id: int; note: string option; note_url: string option } val write_scope : Bi_outbuf.t -> scope -> unit (** Output a JSON value of type {!scope}. *) val string_of_scope : ?len:int -> scope -> string (** Serialize a value of type {!scope} into a JSON string. @param len specifies the initial length of the buffer used internally. Default: 1024. *) val read_scope : Yojson.Safe.lexer_state -> Lexing.lexbuf -> scope (** Input JSON data of type {!scope}. *) val scope_of_string : string -> scope (** Deserialize JSON data of type {!scope}. *) val write_app : Bi_outbuf.t -> app -> unit (** Output a JSON value of type {!app}. *) val string_of_app : ?len:int -> app -> string (** Serialize a value of type {!app} into a JSON string. @param len specifies the initial length of the buffer used internally. Default: 1024. *) val read_app : Yojson.Safe.lexer_state -> Lexing.lexbuf -> app (** Input JSON data of type {!app}. *) val app_of_string : string -> app (** Deserialize JSON data of type {!app}. *) val write_authorization_request : Bi_outbuf.t -> authorization_request -> unit (** Output a JSON value of type {!authorization_request}. *) val string_of_authorization_request : ?len:int -> authorization_request -> string (** Serialize a value of type {!authorization_request} into a JSON string. @param len specifies the initial length of the buffer used internally. Default: 1024. *) val read_authorization_request : Yojson.Safe.lexer_state -> Lexing.lexbuf -> authorization_request (** Input JSON data of type {!authorization_request}. *) val authorization_request_of_string : string -> authorization_request (** Deserialize JSON data of type {!authorization_request}. *) val write_authorization_response : Bi_outbuf.t -> authorization_response -> unit (** Output a JSON value of type {!authorization_response}. *) val string_of_authorization_response : ?len:int -> authorization_response -> string (** Serialize a value of type {!authorization_response} into a JSON string. @param len specifies the initial length of the buffer used internally. Default: 1024. *) val read_authorization_response : Yojson.Safe.lexer_state -> Lexing.lexbuf -> authorization_response (** Input JSON data of type {!authorization_response}. *) val authorization_response_of_string : string -> authorization_response (** Deserialize JSON data of type {!authorization_response}. *) ================================================ FILE: code/json/github_j_excerpt.mli ================================================ val string_of_authorization_request : ?len:int -> authorization_request -> string (** Serialize a value of type {!authorization_request} into a JSON string. @param len specifies the initial length of the buffer used internally. Default: 1024. *) val string_of_authorization_response : ?len:int -> authorization_response -> string (** Serialize a value of type {!authorization_response} into a JSON string. @param len specifies the initial length of the buffer used internally. Default: 1024. *) ================================================ FILE: code/json/github_org.atd ================================================ type org = { login: string; id: int; url: string; ?name: string option; ?blog: string option; ?email: string option; public_repos: int } ================================================ FILE: code/json/github_org_info.ml ================================================ open Core.Std let print_org file () = let url = sprintf "https://api.github.com/orgs/%s" file in Core_extended.Shell.run_full "curl" [url] |> Github_org_j.org_of_string |> fun org -> let open Github_org_t in let name = Option.value ~default:"???" org.name in printf "%s (%d) with %d public repos\n" name org.id org.public_repos let () = Command.basic ~summary:"Print Github organization information" Command.Spec.(empty +> anon ("organization" %: string)) print_org |> Command.run ================================================ FILE: code/json/github_org_j.ml ================================================ (* Auto-generated from "github_org.atd" *) type org = Github_org_t.org = { login: string; id: int; url: string; name: string option; blog: string option; email: string option; public_repos: int } let write__1 = ( Ag_oj_run.write_option ( Yojson.Safe.write_string ) ) let string_of__1 ?(len = 1024) x = let ob = Bi_outbuf.create len in write__1 ob x; Bi_outbuf.contents ob let read__1 = ( fun p lb -> Yojson.Safe.read_space p lb; match Yojson.Safe.start_any_variant p lb with | `Edgy_bracket -> ( Yojson.Safe.read_space p lb; let f = fun s pos len -> if pos < 0 || len < 0 || pos + len > String.length s then invalid_arg "out-of-bounds substring position or length"; try if len = 4 then ( match String.unsafe_get s pos with | 'N' -> ( if String.unsafe_get s (pos+1) = 'o' && String.unsafe_get s (pos+2) = 'n' && String.unsafe_get s (pos+3) = 'e' then ( 0 ) else ( raise (Exit) ) ) | 'S' -> ( if String.unsafe_get s (pos+1) = 'o' && String.unsafe_get s (pos+2) = 'm' && String.unsafe_get s (pos+3) = 'e' then ( 1 ) else ( raise (Exit) ) ) | _ -> ( raise (Exit) ) ) else ( raise (Exit) ) with Exit -> ( Ag_oj_run.invalid_variant_tag (String.sub s pos len) ) in let i = Yojson.Safe.map_ident p f lb in match i with | 0 -> Yojson.Safe.read_space p lb; Yojson.Safe.read_gt p lb; None | 1 -> Ag_oj_run.read_until_field_value p lb; let x = ( Ag_oj_run.read_string ) p lb in Yojson.Safe.read_space p lb; Yojson.Safe.read_gt p lb; Some x | _ -> ( assert false ) ) | `Double_quote -> ( let f = fun s pos len -> if pos < 0 || len < 0 || pos + len > String.length s then invalid_arg "out-of-bounds substring position or length"; try 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 ( 0 ) else ( raise (Exit) ) with Exit -> ( Ag_oj_run.invalid_variant_tag (String.sub s pos len) ) in let i = Yojson.Safe.map_string p f lb in match i with | 0 -> None | _ -> ( assert false ) ) | `Square_bracket -> ( Yojson.Safe.read_space p lb; let f = fun s pos len -> if pos < 0 || len < 0 || pos + len > String.length s then invalid_arg "out-of-bounds substring position or length"; try 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 ( 0 ) else ( raise (Exit) ) with Exit -> ( Ag_oj_run.invalid_variant_tag (String.sub s pos len) ) in let i = Yojson.Safe.map_ident p f lb in match i with | 0 -> Yojson.Safe.read_space p lb; Yojson.Safe.read_comma p lb; Yojson.Safe.read_space p lb; let x = ( Ag_oj_run.read_string ) p lb in Yojson.Safe.read_space p lb; Yojson.Safe.read_rbr p lb; Some x | _ -> ( assert false ) ) ) let _1_of_string s = read__1 (Yojson.Safe.init_lexer ()) (Lexing.from_string s) let write_org = ( fun ob x -> Bi_outbuf.add_char ob '{'; let is_first = ref true in if !is_first then is_first := false else Bi_outbuf.add_char ob ','; Bi_outbuf.add_string ob "\"login\":"; ( Yojson.Safe.write_string ) ob x.login; if !is_first then is_first := false else Bi_outbuf.add_char ob ','; Bi_outbuf.add_string ob "\"id\":"; ( Yojson.Safe.write_int ) ob x.id; if !is_first then is_first := false else Bi_outbuf.add_char ob ','; Bi_outbuf.add_string ob "\"url\":"; ( Yojson.Safe.write_string ) ob x.url; (match x.name with None -> () | Some x -> if !is_first then is_first := false else Bi_outbuf.add_char ob ','; Bi_outbuf.add_string ob "\"name\":"; ( Yojson.Safe.write_string ) ob x; ); (match x.blog with None -> () | Some x -> if !is_first then is_first := false else Bi_outbuf.add_char ob ','; Bi_outbuf.add_string ob "\"blog\":"; ( Yojson.Safe.write_string ) ob x; ); (match x.email with None -> () | Some x -> if !is_first then is_first := false else Bi_outbuf.add_char ob ','; Bi_outbuf.add_string ob "\"email\":"; ( Yojson.Safe.write_string ) ob x; ); if !is_first then is_first := false else Bi_outbuf.add_char ob ','; Bi_outbuf.add_string ob "\"public_repos\":"; ( Yojson.Safe.write_int ) ob x.public_repos; Bi_outbuf.add_char ob '}'; ) let string_of_org ?(len = 1024) x = let ob = Bi_outbuf.create len in write_org ob x; Bi_outbuf.contents ob let read_org = ( fun p lb -> Yojson.Safe.read_space p lb; Yojson.Safe.read_lcurl p lb; let x = { login = Obj.magic 0.0; id = Obj.magic 0.0; url = Obj.magic 0.0; name = None; blog = None; email = None; public_repos = Obj.magic 0.0; } in let bits0 = ref 0 in try Yojson.Safe.read_space p lb; Yojson.Safe.read_object_end lb; Yojson.Safe.read_space p lb; let f = fun s pos len -> if pos < 0 || len < 0 || pos + len > String.length s then invalid_arg "out-of-bounds substring position or length"; match len with | 2 -> ( if String.unsafe_get s pos = 'i' && String.unsafe_get s (pos+1) = 'd' then ( 1 ) else ( -1 ) ) | 3 -> ( if String.unsafe_get s pos = 'u' && String.unsafe_get s (pos+1) = 'r' && String.unsafe_get s (pos+2) = 'l' then ( 2 ) else ( -1 ) ) | 4 -> ( match String.unsafe_get s pos with | 'b' -> ( if String.unsafe_get s (pos+1) = 'l' && String.unsafe_get s (pos+2) = 'o' && String.unsafe_get s (pos+3) = 'g' then ( 4 ) else ( -1 ) ) | 'n' -> ( if String.unsafe_get s (pos+1) = 'a' && String.unsafe_get s (pos+2) = 'm' && String.unsafe_get s (pos+3) = 'e' then ( 3 ) else ( -1 ) ) | _ -> ( -1 ) ) | 5 -> ( match String.unsafe_get s pos with | 'e' -> ( 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 ( 5 ) else ( -1 ) ) | 'l' -> ( 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 ( 0 ) else ( -1 ) ) | _ -> ( -1 ) ) | 12 -> ( 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 ( 6 ) else ( -1 ) ) | _ -> ( -1 ) in let i = Yojson.Safe.map_ident p f lb in Ag_oj_run.read_until_field_value p lb; ( match i with | 0 -> let v = ( Ag_oj_run.read_string ) p lb in Obj.set_field (Obj.repr x) 0 (Obj.repr v); bits0 := !bits0 lor 0x1; | 1 -> let v = ( Ag_oj_run.read_int ) p lb in Obj.set_field (Obj.repr x) 1 (Obj.repr v); bits0 := !bits0 lor 0x2; | 2 -> let v = ( Ag_oj_run.read_string ) p lb in Obj.set_field (Obj.repr x) 2 (Obj.repr v); bits0 := !bits0 lor 0x4; | 3 -> if not (Yojson.Safe.read_null_if_possible p lb) then ( let v = Some ( ( Ag_oj_run.read_string ) p lb ) in Obj.set_field (Obj.repr x) 3 (Obj.repr v); ) | 4 -> if not (Yojson.Safe.read_null_if_possible p lb) then ( let v = Some ( ( Ag_oj_run.read_string ) p lb ) in Obj.set_field (Obj.repr x) 4 (Obj.repr v); ) | 5 -> if not (Yojson.Safe.read_null_if_possible p lb) then ( let v = Some ( ( Ag_oj_run.read_string ) p lb ) in Obj.set_field (Obj.repr x) 5 (Obj.repr v); ) | 6 -> let v = ( Ag_oj_run.read_int ) p lb in Obj.set_field (Obj.repr x) 6 (Obj.repr v); bits0 := !bits0 lor 0x8; | _ -> ( Yojson.Safe.skip_json p lb ) ); while true do Yojson.Safe.read_space p lb; Yojson.Safe.read_object_sep p lb; Yojson.Safe.read_space p lb; let f = fun s pos len -> if pos < 0 || len < 0 || pos + len > String.length s then invalid_arg "out-of-bounds substring position or length"; match len with | 2 -> ( if String.unsafe_get s pos = 'i' && String.unsafe_get s (pos+1) = 'd' then ( 1 ) else ( -1 ) ) | 3 -> ( if String.unsafe_get s pos = 'u' && String.unsafe_get s (pos+1) = 'r' && String.unsafe_get s (pos+2) = 'l' then ( 2 ) else ( -1 ) ) | 4 -> ( match String.unsafe_get s pos with | 'b' -> ( if String.unsafe_get s (pos+1) = 'l' && String.unsafe_get s (pos+2) = 'o' && String.unsafe_get s (pos+3) = 'g' then ( 4 ) else ( -1 ) ) | 'n' -> ( if String.unsafe_get s (pos+1) = 'a' && String.unsafe_get s (pos+2) = 'm' && String.unsafe_get s (pos+3) = 'e' then ( 3 ) else ( -1 ) ) | _ -> ( -1 ) ) | 5 -> ( match String.unsafe_get s pos with | 'e' -> ( 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 ( 5 ) else ( -1 ) ) | 'l' -> ( 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 ( 0 ) else ( -1 ) ) | _ -> ( -1 ) ) | 12 -> ( 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 ( 6 ) else ( -1 ) ) | _ -> ( -1 ) in let i = Yojson.Safe.map_ident p f lb in Ag_oj_run.read_until_field_value p lb; ( match i with | 0 -> let v = ( Ag_oj_run.read_string ) p lb in Obj.set_field (Obj.repr x) 0 (Obj.repr v); bits0 := !bits0 lor 0x1; | 1 -> let v = ( Ag_oj_run.read_int ) p lb in Obj.set_field (Obj.repr x) 1 (Obj.repr v); bits0 := !bits0 lor 0x2; | 2 -> let v = ( Ag_oj_run.read_string ) p lb in Obj.set_field (Obj.repr x) 2 (Obj.repr v); bits0 := !bits0 lor 0x4; | 3 -> if not (Yojson.Safe.read_null_if_possible p lb) then ( let v = Some ( ( Ag_oj_run.read_string ) p lb ) in Obj.set_field (Obj.repr x) 3 (Obj.repr v); ) | 4 -> if not (Yojson.Safe.read_null_if_possible p lb) then ( let v = Some ( ( Ag_oj_run.read_string ) p lb ) in Obj.set_field (Obj.repr x) 4 (Obj.repr v); ) | 5 -> if not (Yojson.Safe.read_null_if_possible p lb) then ( let v = Some ( ( Ag_oj_run.read_string ) p lb ) in Obj.set_field (Obj.repr x) 5 (Obj.repr v); ) | 6 -> let v = ( Ag_oj_run.read_int ) p lb in Obj.set_field (Obj.repr x) 6 (Obj.repr v); bits0 := !bits0 lor 0x8; | _ -> ( Yojson.Safe.skip_json p lb ) ); done; assert false; with Yojson.End_of_object -> ( if !bits0 <> 0xf then Ag_oj_run.missing_fields [| !bits0 |] [| "login"; "id"; "url"; "public_repos" |]; Ag_oj_run.identity x ) ) let org_of_string s = read_org (Yojson.Safe.init_lexer ()) (Lexing.from_string s) ================================================ FILE: code/json/github_org_j.mli ================================================ (* Auto-generated from "github_org.atd" *) type org = Github_org_t.org = { login: string; id: int; url: string; name: string option; blog: string option; email: string option; public_repos: int } val write_org : Bi_outbuf.t -> org -> unit (** Output a JSON value of type {!org}. *) val string_of_org : ?len:int -> org -> string (** Serialize a value of type {!org} into a JSON string. @param len specifies the initial length of the buffer used internally. Default: 1024. *) val read_org : Yojson.Safe.lexer_state -> Lexing.lexbuf -> org (** Input JSON data of type {!org}. *) val org_of_string : string -> org (** Deserialize JSON data of type {!org}. *) ================================================ FILE: code/json/github_org_t.ml ================================================ (* Auto-generated from "github_org.atd" *) type org = { login: string; id: int; url: string; name: string option; blog: string option; email: string option; public_repos: int } ================================================ FILE: code/json/github_org_t.mli ================================================ (* Auto-generated from "github_org.atd" *) type org = { login: string; id: int; url: string; name: string option; blog: string option; email: string option; public_repos: int } ================================================ FILE: code/json/github_t.ml ================================================ (* Auto-generated from "github.atd" *) type scope = [ `User | `Public_repo | `Repo | `Repo_status | `Delete_repo | `Gist ] type app = { app_name (*atd name *): string; app_url (*atd url *): string } type authorization_request = { auth_req_scopes (*atd scopes *): scope list; auth_req_note (*atd note *): string } type authorization_response = { scopes: scope list; token: string; app: app; url: string; id: int; note: string option; note_url: string option } ================================================ FILE: code/json/github_t.mli ================================================ (* Auto-generated from "github.atd" *) type scope = [ `User | `Public_repo | `Repo | `Repo_status | `Delete_repo | `Gist ] type app = { app_name (*atd name *): string; app_url (*atd url *): string } type authorization_request = { auth_req_scopes (*atd scopes *): scope list; auth_req_note (*atd note *): string } type authorization_response = { scopes: scope list; token: string; app: app; url: string; id: int; note: string option; note_url: string option } ================================================ FILE: code/json/install.topscript ================================================ #require "yojson" ;; open Yojson ;; ================================================ FILE: code/json/install_atdgen.rawsh ================================================ $ opam install atdgen $ atdgen -version 1.2.3 ================================================ FILE: code/json/list_excerpt.mli ================================================ val map : 'a list -> f:('a -> 'b) -> 'b list val fold : 'a list -> init:'accum -> f:('accum -> 'a -> 'accum) -> 'accum (* part 1 *) val iter : 'a list -> f:('a -> unit) -> unit ================================================ FILE: code/json/parse_book.ml ================================================ open Core.Std let () = (* Read the JSON file *) let json = Yojson.Basic.from_file "book.json" in (* Locally open the JSON manipulation functions *) let open Yojson.Basic.Util in let title = json |> member "title" |> to_string in let tags = json |> member "tags" |> to_list |> filter_string in let pages = json |> member "pages" |> to_int in let is_online = json |> member "is_online" |> to_bool_option in let is_translated = json |> member "is_translated" |> to_bool_option in let authors = json |> member "authors" |> to_list in let names = List.map authors ~f:(fun json -> member "name" json |> to_string) in (* Print the results of the parsing *) printf "Title: %s (%d)\n" title pages; printf "Authors: %s\n" (String.concat ~sep:", " names); printf "Tags: %s\n" (String.concat ~sep:", " tags); let string_of_bool_option = function | None -> "" | Some true -> "yes" | Some false -> "no" in printf "Online: %s\n" (string_of_bool_option is_online); printf "Translated: %s\n" (string_of_bool_option is_translated) ================================================ FILE: code/json/parse_book.topscript ================================================ #require "yojson" ;; let json = Yojson.Basic.from_file "book.json" ;; #part 1 open Yojson.Basic.Util ;; let title = json |> member "title" |> to_string ;; #part 2 let tags = json |> member "tags" |> to_list |> filter_string ;; let pages = json |> member "pages" |> to_int ;; #part 3 let is_online = json |> member "is_online" |> to_bool_option ;; let is_translated = json |> member "is_translated" |> to_bool_option ;; #part 4 let authors = json |> member "authors" |> to_list ;; #part 5 let names = json |> member "authors" |> to_list |> List.map ~f:(fun json -> member "name" json |> to_string) ;; ================================================ FILE: code/json/read_json.ml ================================================ open Core.Std let () = (* Read JSON file into an OCaml string *) let buf = In_channel.read_all "book.json" in (* Use the string JSON constructor *) let json1 = Yojson.Basic.from_string buf in (* Use the file JSON constructor *) let json2 = Yojson.Basic.from_file "book.json" in (* Test that the two values are the same *) print_endline (if json1 = json2 then "OK" else "FAIL") ================================================ FILE: code/json/run_github_org.sh ================================================ ./github_org_info.native mirage ./github_org_info.native janestreet ================================================ FILE: code/json/run_parse_book.sh ================================================ corebuild -pkg yojson parse_book.native ./parse_book.native ================================================ FILE: code/json/run_read_json.sh ================================================ corebuild -pkg yojson read_json.native ./read_json.native ================================================ FILE: code/json/yojson_basic.mli ================================================ type json = [ | `Assoc of (string * json) list | `Bool of bool | `Float of float | `Int of int | `List of json list | `Null | `String of string ] (* part 1 *) val from_string : ?buf:Bi_outbuf.t -> ?fname:string -> ?lnum:int -> string -> json (* Read a JSON value from a string. [buf] : use this buffer at will during parsing instead of creating a new one. [fname] : data file name to be used in error messages. It does not have to be a real file. [lnum] : number of the first line of input. Default is 1. *) val from_file : ?buf:Bi_outbuf.t -> ?fname:string -> ?lnum:int -> string -> json (* Read a JSON value from a file. See [from_string] for the meaning of the optional arguments. *) val from_channel : ?buf:Bi_outbuf.t -> ?fname:string -> ?lnum:int -> in_channel -> json (** Read a JSON value from a channel. See [from_string] for the meaning of the optional arguments. *) ================================================ FILE: code/json/yojson_basic_simple.mli ================================================ val from_string : string -> json val from_file : string -> json val from_channel : in_channel -> json ================================================ FILE: code/json/yojson_safe.mli ================================================ type json = [ | `Assoc of (string * json) list | `Bool of bool | `Float of float | `Floatlit of string | `Int of int | `Intlit of string | `List of json list | `Null | `String of string | `Stringlit of string | `Tuple of json list | `Variant of string * json option ] (* part 1 *) val to_basic : json -> Yojson.Basic.json (** Tuples are converted to JSON arrays, Variants are converted to JSON strings or arrays of a string (constructor) and a json value (argument). Long integers are converted to JSON strings. Examples: `Tuple [ `Int 1; `Float 2.3 ] -> `List [ `Int 1; `Float 2.3 ] `Variant ("A", None) -> `String "A" `Variant ("B", Some x) -> `List [ `String "B", x ] `Intlit "12345678901234567890" -> `String "12345678901234567890" *) ================================================ FILE: code/lists-and-patterns/example.ml ================================================ ================================================ FILE: code/lists-and-patterns/example.mli ================================================ ================================================ FILE: code/lists-and-patterns/lists_layout.ascii ================================================ +---+---+ +---+---+ +---+---+ | 1 | *---->| 2 | *---->| 3 | *---->|| +---+---+ +---+---+ +---+---+ ================================================ FILE: code/lists-and-patterns/main.topscript ================================================ [1;2;3];; #part 1 1 :: (2 :: (3 :: [])) ;; 1 :: 2 :: 3 :: [] ;; #part 2 let empty = [];; 3 :: empty;; "three" :: empty;; #part 3 let l = 1 :: 2 :: 3 :: [];; let m = 0 :: l;; l;; #part 4 let rec sum l = match l with | [] -> 0 | hd :: tl -> hd + sum tl ;; sum [1;2;3];; sum [];; #part 5 let rec drop_value l to_drop = match l with | [] -> [] | to_drop :: tl -> drop_value tl to_drop | hd :: tl -> hd :: drop_value tl to_drop ;; #part 6 drop_value [1;2;3] 2;; #part 7 let rec drop_value l to_drop = match l with | [] -> [] | hd :: tl -> let new_tl = drop_value tl to_drop in if hd = to_drop then new_tl else hd :: new_tl ;; drop_value [1;2;3] 2;; #part 8 let rec drop_zero l = match l with | [] -> [] | 0 :: tl -> drop_zero tl | hd :: tl -> hd :: drop_zero tl ;; drop_zero [1;2;0;3];; #part 9 let plus_one_match x = match x with | 0 -> 1 | 1 -> 2 | 2 -> 3 | _ -> x + 1 let plus_one_if x = if x = 0 then 1 else if x = 1 then 2 else if x = 2 then 3 else x + 1 ;; #part 10 #require "core_bench";; open Core_bench.Std;; let run_bench tests = Bench.bench ~ascii_table:true ~display:Textutils.Ascii_table.Display.column_titles tests ;; [ Bench.Test.create ~name:"plus_one_match" (fun () -> ignore (plus_one_match 10)) ; Bench.Test.create ~name:"plus_one_if" (fun () -> ignore (plus_one_if 10)) ] |> run_bench ;; #part 11 let rec sum_if l = if List.is_empty l then 0 else List.hd_exn l + sum_if (List.tl_exn l) ;; #part 12 let numbers = List.range 0 1000 in [ Bench.Test.create ~name:"sum_if" (fun () -> ignore (sum_if numbers)) ; Bench.Test.create ~name:"sum" (fun () -> ignore (sum numbers)) ] |> run_bench ;; #part 13 let rec drop_zero l = match l with | [] -> [] | 0 :: tl -> drop_zero tl ;; #part 14 List.map ~f:String.length ["Hello"; "World!"];; #part 15 List.map2_exn ~f:Int.max [1;2;3] [3;2;1];; #part 16 List.map2_exn ~f:Int.max [1;2;3] [3;2;1;0];; #part 17 List.fold;; #part 18 List.fold ~init:0 ~f:(+) [1;2;3;4];; #part 19 List.fold ~init:[] ~f:(fun list x -> x :: list) [1;2;3;4];; #part 20 let max_widths header rows = let lengths l = List.map ~f:String.length l in List.fold rows ~init:(lengths header) ~f:(fun acc row -> List.map2_exn ~f:Int.max acc (lengths row)) ;; #part 21 let render_separator widths = let pieces = List.map widths ~f:(fun w -> String.make (w + 2) '-') in "|" ^ String.concat ~sep:"+" pieces ^ "|" ;; render_separator [3;6;2];; #part 22 let s = "." ^ "." ^ "." ^ "." ^ "." ^ "." ^ ".";; #part 23 let s = String.concat [".";".";".";".";".";".";"."];; #part 24 let pad s length = " " ^ s ^ String.make (length - String.length s + 1) ' ' ;; pad "hello" 10;; #part 25 let render_row row widths = let padded = List.map2_exn row widths ~f:pad in "|" ^ String.concat ~sep:"|" padded ^ "|" ;; render_row ["Hello";"World"] [10;15];; #part 26 let render_table header rows = let widths = max_widths header rows in String.concat ~sep:"\n" (render_row header widths :: render_separator widths :: List.map rows ~f:(fun row -> render_row row widths) ) ;; #part 27 List.reduce;; #part 28 List.reduce ~f:(+) [1;2;3;4;5];; List.reduce ~f:(+) [];; #part 29 List.filter ~f:(fun x -> x mod 2 = 0) [1;2;3;4;5];; #part 30 List.filter_map (Sys.ls_dir ".") ~f:(fun fname -> match String.rsplit2 ~on:'.' fname with | None | Some ("",_) -> None | Some (_,ext) -> Some ext) |> List.dedup ;; #part 31 let is_ocaml_source s = match String.rsplit2 s ~on:'.' with | Some (_,("ml"|"mli")) -> true | _ -> false ;; let (ml_files,other_files) = List.partition_tf (Sys.ls_dir ".") ~f:is_ocaml_source;; #part 32 List.append [1;2;3] [4;5;6];; #part 33 [1;2;3] @ [4;5;6];; #part 34 List.concat [[1;2];[3;4;5];[6];[]];; #part 35 let rec ls_rec s = if Sys.is_file_exn ~follow_symlinks:true s then [s] else Sys.ls_dir s |> List.map ~f:(fun sub -> ls_rec (s ^/ sub)) |> List.concat ;; #part 36 let rec ls_rec s = if Sys.is_file_exn ~follow_symlinks:true s then [s] else Sys.ls_dir s |> List.concat_map ~f:(fun sub -> ls_rec (s ^/ sub)) ;; #part 37 let rec length = function | [] -> 0 | _ :: tl -> 1 + length tl ;; length [1;2;3];; #part 38 let make_list n = List.init n ~f:(fun x -> x);; length (make_list 10);; length (make_list 10_000_000);; #part 39 let rec length_plus_n l n = match l with | [] -> n | _ :: tl -> length_plus_n tl (n + 1) ;; let length l = length_plus_n l 0 ;; length [1;2;3;4];; #part 40 length (make_list 10_000_000);; #part 41 let rec destutter list = match list with | [] -> [] | [hd] -> [hd] | hd :: hd' :: tl -> if hd = hd' then destutter (hd' :: tl) else hd :: destutter (hd' :: tl) ;; #part 42 let rec destutter = function | [] as l -> l | [_] as l -> l | hd :: (hd' :: _ as tl) -> if hd = hd' then destutter tl else hd :: destutter tl ;; #part 43 let rec destutter = function | [] | [_] as l -> l | hd :: (hd' :: _ as tl) -> if hd = hd' then destutter tl else hd :: destutter tl ;; #part 44 let rec destutter = function | [] | [_] as l -> l | hd :: (hd' :: _ as tl) when hd = hd' -> destutter tl | hd :: tl -> hd :: destutter tl ;; #part 45 3 = 4;; [3;4;5] = [3;4;5];; [Some 3; None] = [None; Some 3];; #part 46 (=);; #part 47 (fun x -> x + 1) = (fun x -> x + 1);; #part 48 let rec count_some list = match list with | [] -> 0 | x :: tl when Option.is_none x -> count_some tl | x :: tl when Option.is_some x -> 1 + count_some tl ;; #part 49 count_some [Some 3; None; Some 4];; #part 50 let rec count_some list = match list with | [] -> 0 | x :: tl when Option.is_none x -> count_some tl | x :: tl when Option.is_some x -> 1 + count_some tl | x :: tl -> -1 (* unreachable *) ;; #part 51 let rec count_some list = match list with | [] -> 0 | x :: tl when Option.is_none x -> count_some tl | _ :: tl -> 1 + count_some tl ;; #part 52 let rec count_some list = match list with | [] -> 0 | None :: tl -> count_some tl | Some _ :: tl -> 1 + count_some tl ;; #part 53 let count_some l = List.count ~f:Option.is_some l;; #part 54 #part 55 #part 56 #part 57 #part 58 #part 59 #part 60 #part 61 #part 62 #part 63 #part 64 #part 65 #part 66 #part 67 #part 68 #part 69 printf "%s\n" (render_table ["language";"architect";"first release"] [ ["Lisp" ;"John McCarthy" ;"1958"] ; ["C" ;"Dennis Ritchie";"1969"] ; ["ML" ;"Robin Milner" ;"1973"] ; ["OCaml";"Xavier Leroy" ;"1996"] ; ]);; ================================================ FILE: code/maps-and-hash-tables/comparable.ml ================================================ module type Comparable = sig type t val sexp_of_t : t -> Sexp.t val t_of_sexp : Sexp.t -> t val compare : t -> t -> int end ================================================ FILE: code/maps-and-hash-tables/core_phys_equal.topscript ================================================ open Core.Std ;; 1 == 2 ;; phys_equal 1 2 ;; ================================================ FILE: code/maps-and-hash-tables/main-22.rawscript ================================================ # module Foo_and_bar : sig type t = { foo: Int.Set.t; bar: string } include Comparable.S with type t := t end = struct module T = struct type t = { foo: Int.Set.t; bar: string } with sexp let compare t1 t2 = let c = Int.Set.compare t1.foo t2.foo in if c <> 0 then c else String.compare t1.bar t2.bar end include T include Comparable.Make(T) end;; module Foo_and_bar : sig type t = { foo : Int.Set.t; bar : string; } val ( >= ) : t -> t -> bool val ( <= ) : t -> t -> bool val ( = ) : t -> t -> bool ... end ================================================ FILE: code/maps-and-hash-tables/main-23.rawscript ================================================ # module Foo_and_bar : sig type t = { foo: Int.Set.t; bar: string } include Comparable.S with type t := t end = struct module T = struct type t = { foo: Int.Set.t; bar: string } with sexp, compare end include T include Comparable.Make(T) end;; module Foo_and_bar : sig type t = { foo : Int.Set.t; bar : string; } val ( >= ) : t -> t -> bool val ( <= ) : t -> t -> bool val ( = ) : t -> t -> bool ... end ================================================ FILE: code/maps-and-hash-tables/main-24.rawscript ================================================ # module Foo_and_bar : sig type t = { foo: int; bar: string } include Comparable.S with type t := t end = struct module T = struct type t = { foo: int; bar: string } with sexp end include T include Comparable.Poly(T) end;; module Foo_and_bar : sig type t = { foo : int; bar : string; } val ( >= ) : t -> t -> bool val ( <= ) : t -> t -> bool val ( = ) : t -> t -> bool ... end ================================================ FILE: code/maps-and-hash-tables/main-30.rawscript ================================================ # module Foo_and_bar : sig type t = { foo: int; bar: string } include Hashable.S with type t := t end = struct module T = struct type t = { foo: int; bar: string } with sexp, compare let hash t = (Int.hash t.foo) lxor (String.hash t.bar) end include T include Hashable.Make(T) end;; module Foo_and_bar : sig type t = { foo : int; bar : string; } module Hashable : sig type t = t end val hash : t -> int val compare : t -> t -> int val hashable : t Pooled_hashtbl.Hashable.t ... end ================================================ FILE: code/maps-and-hash-tables/main.topscript ================================================ let x = 0;; #part 1 let digit_alist = [ 0, "zero"; 1, "one"; 2, "two" ; 3, "three"; 4, "four" ; 5, "five"; 6, "six"; 7, "seven"; 8, "eight"; 9, "nine" ] ;; #part 2 List.Assoc.find digit_alist 6;; List.Assoc.find digit_alist 22;; List.Assoc.add digit_alist 0 "zilch";; #part 3 let digit_map = Map.of_alist_exn digit_alist ~comparator:Int.comparator;; Map.find digit_map 3;; #part 4 let zilch_map = Map.add digit_map ~key:0 ~data:"zilch";; #part 5 let left = String.Map.of_alist_exn ["foo",1; "bar",3; "snoo", 0] let right = String.Map.of_alist_exn ["foo",0; "snoo", 0] let diff = Map.symmetric_diff ~data_equal:Int.equal left right ;; #part 6 Map.symmetric_diff;; #part 7 module Reverse = Comparator.Make(struct type t = string let sexp_of_t = String.sexp_of_t let t_of_sexp = String.t_of_sexp let compare x y = String.compare y x end);; #part 8 let alist = ["foo", 0; "snoo", 3];; let ord_map = Map.of_alist_exn ~comparator:String.comparator alist;; let rev_map = Map.of_alist_exn ~comparator:Reverse.comparator alist;; #part 9 Map.min_elt ord_map;; Map.min_elt rev_map;; #part 10 Map.symmetric_diff ord_map rev_map;; #part 11 let ord_tree = Map.to_tree ord_map;; #part 12 Map.Tree.find ~comparator:String.comparator ord_tree "snoo";; #part 13 Map.Tree.find ~comparator:Reverse.comparator ord_tree "snoo";; #part 14 Map.of_alist_exn ~comparator:Comparator.Poly.comparator digit_alist;; #part 15 Map.Poly.of_alist_exn digit_alist;; #part 16 Map.symmetric_diff (Map.Poly.singleton 3 "three") (Int.Map.singleton 3 "four" ) ;; #part 17 let dedup ~comparator l = List.fold l ~init:(Set.empty ~comparator) ~f:Set.add |> Set.to_list ;; dedup ~comparator:Int.comparator [8;3;2;3;7;8;10];; #part 18 let (s1,s2) = (Int.Set.of_list [1;2], Int.Set.of_list [2;1]);; #part 19 Set.equal s1 s2;; #part 20 s1 = s2;; #part 21 Set.to_tree s1 = Set.to_tree s2;; #part 22 module Foo_and_bar : sig type t = { foo: Int.Set.t; bar: string } include Comparable.S with type t := t end = struct module T = struct type t = { foo: Int.Set.t; bar: string } with sexp let compare t1 t2 = let c = Int.Set.compare t1.foo t2.foo in if c <> 0 then c else String.compare t1.bar t2.bar end include T include Comparable.Make(T) end;; #part 23 module Foo_and_bar : sig type t = { foo: Int.Set.t; bar: string } include Comparable.S with type t := t end = struct module T = struct type t = { foo: Int.Set.t; bar: string } with sexp, compare end include T include Comparable.Make(T) end;; #part 24 module Foo_and_bar : sig type t = { foo: int; bar: string } include Comparable.S with type t := t end = struct module T = struct type t = { foo: int; bar: string } with sexp end include T include Comparable.Poly(T) end;; #part 25 let table = Hashtbl.create ~hashable:String.hashable ();; Hashtbl.replace table ~key:"three" ~data:3;; Hashtbl.find table "three";; #part 26 let table = String.Table.create ();; #part 27 let table = Hashtbl.create ~hashable:Hashtbl.Poly.hashable ();; #part 28 let table = Hashtbl.Poly.create ();; #part 29 Caml.Hashtbl.hash (List.range 0 9);; Caml.Hashtbl.hash (List.range 0 10);; Caml.Hashtbl.hash (List.range 0 11);; Caml.Hashtbl.hash (List.range 0 100);; #part 30 module Foo_and_bar : sig type t = { foo: int; bar: string } include Hashable.S with type t := t end = struct module T = struct type t = { foo: int; bar: string } with sexp, compare let hash t = (Int.hash t.foo) lxor (String.hash t.bar) end include T include Hashable.Make(T) end;; ================================================ FILE: code/maps-and-hash-tables/map_vs_hash.ml ================================================ open Core.Std open Core_bench.Std let map_iter ~num_keys ~iterations = let rec loop i map = if i <= 0 then () else loop (i - 1) (Map.change map (i mod num_keys) (fun current -> Some (1 + Option.value ~default:0 current))) in loop iterations Int.Map.empty let table_iter ~num_keys ~iterations = let table = Int.Table.create ~size:num_keys () in let rec loop i = if i <= 0 then () else ( Hashtbl.change table (i mod num_keys) (fun current -> Some (1 + Option.value ~default:0 current)); loop (i - 1) ) in loop iterations let tests ~num_keys ~iterations = let test name f = Bench.Test.create f ~name in [ test "map" (fun () -> map_iter ~num_keys ~iterations) ; test "table" (fun () -> table_iter ~num_keys ~iterations) ] let () = tests ~num_keys:1000 ~iterations:100_000 |> Bench.make_command |> Command.run ================================================ FILE: code/maps-and-hash-tables/map_vs_hash2.ml ================================================ open Core.Std open Core_bench.Std let create_maps ~num_keys ~iterations = let rec loop i map = if i <= 0 then [] else let new_map = Map.change map (i mod num_keys) (fun current -> Some (1 + Option.value ~default:0 current)) in new_map :: loop (i - 1) new_map in loop iterations Int.Map.empty let create_tables ~num_keys ~iterations = let table = Int.Table.create ~size:num_keys () in let rec loop i = if i <= 0 then [] else ( Hashtbl.change table (i mod num_keys) (fun current -> Some (1 + Option.value ~default:0 current)); let new_table = Hashtbl.copy table in new_table :: loop (i - 1) ) in loop iterations let tests ~num_keys ~iterations = let test name f = Bench.Test.create f ~name in [ test "map" (fun () -> ignore (create_maps ~num_keys ~iterations)) ; test "table" (fun () -> ignore (create_tables ~num_keys ~iterations)) ] let () = tests ~num_keys:50 ~iterations:1000 |> Bench.make_command |> Command.run ================================================ FILE: code/maps-and-hash-tables/phys_equal.rawscript ================================================ # type t1 = { foo1:int; bar1:t2 } and t2 = { foo2:int; bar2:t1 } ;; type t1 = { foo1 : int; bar1 : t2; } and t2 = { foo2 : int; bar2 : t1; } # let rec v1 = { foo1=1; bar1=v2 } and v2 = { foo2=2; bar2=v1 } ;; # v1 == v1;; - : bool = true # phys_equal v1 v1;; - : bool = true # v1 = v1 ;; ================================================ FILE: code/maps-and-hash-tables/run_map_vs_hash.sh ================================================ corebuild -pkg core_bench map_vs_hash.native ./map_vs_hash.native -ascii -clear-columns time speedup ================================================ FILE: code/maps-and-hash-tables/run_map_vs_hash2.sh ================================================ corebuild -pkg core_bench map_vs_hash2.native ./map_vs_hash2.native -ascii -clear-columns time speedup ================================================ FILE: code/memory-repr/block.ascii ================================================ +------------------------+---------+----------+----------+----------+---- | size of block in words | color | tag byte | value[0] | value[1] | ... +------------------------+---------+----------+----------+----------+---- <-either 22 or 54 bits-> <-2 bit-> <--8 bit--> ================================================ FILE: code/memory-repr/custom_ops.c ================================================ struct custom_operations { char *identifier; void (*finalize)(value v); int (*compare)(value v1, value v2); intnat (*hash)(value v); void (*serialize)(value v, /*out*/ uintnat * wsize_32 /*size in bytes*/, /*out*/ uintnat * wsize_64 /*size in bytes*/); uintnat (*deserialize)(void * dst); int (*compare_ext)(value v1, value v2); }; ================================================ FILE: code/memory-repr/float_array_layout.ascii ================================================ +---------+----------+----------- - - - - | header | float[0] | float[1] | .... +---------+----------+----------+- - - - - ================================================ FILE: code/memory-repr/reprs.topscript ================================================ Obj.is_block (Obj.repr (1,2,3)) ;; Obj.is_block (Obj.repr 1) ;; #part 1 Obj.tag (Obj.repr 1.0) ;; Obj.double_tag ;; #part 2 Obj.double_tag ;; Obj.double_array_tag ;; #part 3 Obj.tag (Obj.repr [| 1.0; 2.0; 3.0 |]) ;; Obj.tag (Obj.repr (1.0, 2.0, 3.0) ) ;; Obj.double_field (Obj.repr [| 1.1; 2.2; 3.3 |]) 1 ;; Obj.double_field (Obj.repr 1.234) 0 ;; #part 4 type t = Apple | Orange | Pear ;; ((Obj.magic (Obj.repr Apple)) : int) ;; ((Obj.magic (Obj.repr Pear)) : int) ;; Obj.is_block (Obj.repr Apple) ;; #part 5 type t = Apple | Orange of int | Pear of string | Kiwi ;; Obj.is_block (Obj.repr (Orange 1234)) ;; Obj.tag (Obj.repr (Orange 1234)) ;; Obj.tag (Obj.repr (Pear "xyz")) ;; (Obj.magic (Obj.field (Obj.repr (Orange 1234)) 0) : int) ;; (Obj.magic (Obj.field (Obj.repr (Pear "xyz")) 0) : string) ;; #part 6 Pa_type_conv.hash_variant "Foo" ;; (Obj.magic (Obj.repr `Foo) : int) ;; ================================================ FILE: code/memory-repr/simple_record.topscript ================================================ type t = { foo: int; bar: int } ;; let x = { foo = 13; bar = 14 } ;; ================================================ FILE: code/memory-repr/string_block.ascii ================================================ +---------------+----------------+--------+-----------+ | header | 'a' 'b' 'c' 'd' 'e' 'f' | '\O' '\1' | +---------------+----------------+--------+-----------+ L data L padding ================================================ FILE: code/memory-repr/string_size_calc.ascii ================================================ number_of_words_in_block * sizeof(word) - last_byte_of_block - 1 ================================================ FILE: code/memory-repr/tuple_layout.ascii ================================================ +---------+----------+----------- - - - - | header | value[0] | value[1] | .... +---------+----------+----------+- - - - - ================================================ FILE: code/objects/IsBarbell.java ================================================ boolean IsBarbell(Shape[] s) { return s.length == 3 && (s[0] instanceof Circle) && (s[1] instanceof Line) && (s[2] instanceof Circle) && ((Circle) s[0]).radius() == ((Circle) s[2]).radius(); } ================================================ FILE: code/objects/Shape.java ================================================ String GetShapeName(Shape s) { if (s instanceof Square) { return "Square"; } else if (s instanceof Circle) { return "Circle"; } else { return "Other"; } } ================================================ FILE: code/objects/immutable.topscript ================================================ 1;; #part 1 let imm_stack init = object val v = init method pop = match v with | hd :: tl -> Some (hd, {< v = tl >}) | [] -> None method push hd = {< v = hd :: v >} end ;; #part 2 let s = imm_stack [3; 2; 1] ;; let t = s#push 4 ;; s#pop ;; t#pop ;; ================================================ FILE: code/objects/is_barbell.ml ================================================ let is_barbell = function | [Circle r1; Line _; Circle r2] when r1 = r2 -> true | _ -> false ================================================ FILE: code/objects/narrowing.ml ================================================ (* part 1 *) type shape = < variant : repr; area : float> and circle = < variant : repr; area : float; radius : int > and line = < variant : repr; area : float; length : int > and repr = | Circle of circle | Line of line;; let is_barbell = function | [s1; s2; s3] -> (match s1#variant, s2#variant, s3#variant with | Circle c1, Line _, Circle c2 when c1#radius = c2#radius -> true | _ -> false) | _ -> false;; ================================================ FILE: code/objects/polymorphism.topscript ================================================ 1;; #part 1 let area sq = sq#width * sq#width ;; let minimize sq : unit = sq#resize 1 ;; let limit sq = if (area sq) > 100 then minimize sq ;; #part 2 let toggle sq b : unit = if b then sq#resize `Fullscreen else minimize sq ;; #part 3 let area_closed (sq: < width : int >) = sq#width * sq#width ;; let sq = object method width = 30 method name = "sq" end ;; area_closed sq ;; #part 4 type square = < width : int; ..> ;; ================================================ FILE: code/objects/row_polymorphism.topscript ================================================ type shape = < area : float > ;; type square = < area : float; width : int > ;; let square w = object method area = Float.of_int (w * w) method width = w end ;; type circle = < area : float; radius : int > ;; let circle r = object method area = 3.14 *. (Float.of_int r) ** 2.0 method radius = r end ;; #part 1 let remove_large l = List.filter ~f:(fun s -> s#area <= 100.) l ;; #part 2 let squares : < area : float; width : int > list = [square 5; square 15; square 10] ;; remove_large squares ;; #part 3 let remove_large (l: < area : float > list) = List.filter ~f:(fun s -> s#area <= 100.) l ;; remove_large (squares :> < area : float > list ) ;; #part 4 let hlist: < area: float; ..> list = [square 10; circle 30] ;; #part 5 let shape_ref: < area: float; ..> ref = ref (square 40) ;; shape_ref := circle 20 ;; #part 6 let hlist: shape list = [(square 10 :> shape); (circle 30 :> shape)] ;; let shape_ref: shape ref = ref (square 40 :> shape) ;; shape_ref := (circle 20 :> shape) ;; ================================================ FILE: code/objects/stack.topscript ================================================ 1;; #part 1 let s = object val mutable v = [0; 2] method pop = match v with | hd :: tl -> v <- tl; Some hd | [] -> None method push hd = v <- hd :: v end ;; #part 2 s#pop ;; s#push 4 ;; s#pop ;; #part 3 let stack init = object val mutable v = init method pop = match v with | hd :: tl -> v <- tl; Some hd | [] -> None method push hd = v <- hd :: v end ;; let s = stack [3; 2; 1] ;; s#pop ;; #part 4 let print_pop st = Option.iter ~f:(printf "Popped: %d\n") st#pop ;; print_pop (stack [5;4;3;2;1]) ;; let t = object method pop = Some (Float.to_int (Time.to_float (Time.now ()))) end ;; print_pop t ;; ================================================ FILE: code/objects/subtyping.ml ================================================ (* part 1 *) type shape = < area : float > type square = < area : float; width : int > let square w = object method area = Float.of_int (w * w) method width = w end type circle = < area : float; radius : int > let circle r = object method area = 3.14 *. (Float.of_int r) ** 2.0 method radius = r end (* part 2 *) type 'a stack = < pop: 'a option; push: 'a -> unit > let square_stack: square stack = stack [square 30; square 10] let circle_stack: circle stack = stack [circle 20; circle 40] ================================================ FILE: code/objects/subtyping.topscript ================================================ let stack init = object val mutable v = init method pop = match v with | hd :: tl -> v <- tl; Some hd | [] -> None method push hd = v <- hd :: v end ;; type shape = < area : float > ;; type square = < area : float; width : int > ;; let square w = object method area = Float.of_int (w * w) method width = w end ;; type circle = < area : float; radius : int > ;; let circle r = object method area = 3.14 *. (Float.of_int r) ** 2.0 method radius = r end ;; type 'a stack = < pop: 'a option; push: 'a -> unit > ;; let square_stack: square stack = stack [square 30; square 10] ;; let circle_stack: circle stack = stack [circle 20; circle 40] ;; #part 1 let shape w : shape = square w ;; let shape w : shape = (square w :> shape) ;; #part 2 let coin = object method shape = circle 5 method color = "silver" end ;; let map = object method shape = square 10 end ;; #part 3 type item = < shape : shape > ;; let items = [ (coin :> item) ; (map :> item) ] ;; #part 4 type num = [ `Int of int | `Float of float ] ;; type const = [ num | `String of string ] ;; let n : num = `Int 3 ;; let c : const = (n :> const) ;; #part 5 let squares: square list = [ square 10; square 20 ] ;; let shapes: shape list = (squares :> shape list) ;; #part 6 let square_array: square array = [| square 10; square 20 |] ;; let shape_array: shape array = (square_array :> shape array) ;; #part 7 let shape_to_string: shape -> string = fun s -> sprintf "Shape(%F)" s#area ;; let square_to_string: square -> string = (shape_to_string :> square -> string) ;; #part 8 module Either = struct type ('a, 'b) t = | Left of 'a | Right of 'b let left x = Left x let right x = Right x end ;; (Either.left (square 40) :> (shape, shape) Either.t) ;; #part 9 module AbstractEither : sig type ('a, 'b) t val left: 'a -> ('a, 'b) t val right: 'b -> ('a, 'b) t end = Either ;; (AbstractEither.left (square 40) :> (shape, shape) AbstractEither.t) ;; #part 10 module VarEither : sig type (+'a, +'b) t val left: 'a -> ('a, 'b) t val right: 'b -> ('a, 'b) t end = Either ;; (VarEither.left (square 40) :> (shape, shape) VarEither.t) ;; #part 11 let total_area (shape_stacks: shape stack list) = let stack_area acc st = let rec loop acc = match st#pop with | Some s -> loop (acc +. s#area) | None -> acc in loop acc in List.fold ~init:0.0 ~f:stack_area shape_stacks ;; #part 12 total_area [(square_stack :> shape stack); (circle_stack :> shape stack)] ;; #part 13 type 'a readonly_stack = < pop : 'a option > ;; let total_area (shape_stacks: shape readonly_stack list) = let stack_area acc st = let rec loop acc = match st#pop with | Some s -> loop (acc +. s#area) | None -> acc in loop acc in List.fold ~init:0.0 ~f:stack_area shape_stacks ;; total_area [(square_stack :> shape readonly_stack); (circle_stack :> shape readonly_stack)] ;; ================================================ FILE: code/ocp-index/index_ncurses.sh ================================================ corebuild -pkg ctypes.foreign -tag bin_annot ncurses.cmi ocp-index complete -I . Ncur ocp-index complete -I . Ncurses.a ocp-index complete -I . Ncurses. ================================================ FILE: code/packing/A.ml ================================================ let v = "hello" ================================================ FILE: code/packing/B.ml ================================================ let w = 42 ================================================ FILE: code/packing/X.mlpack ================================================ A B ================================================ FILE: code/packing/_tags ================================================ <*.cmx> and not "X.cmx": for-pack(X) ================================================ FILE: code/packing/build_test.sh ================================================ corebuild test.inferred.mli test.cmi cat _build/test.inferred.mli ocamlobjinfo _build/test.cmi ================================================ FILE: code/packing/show_files.sh ================================================ cat A.ml cat B.ml cat _tags cat X.mlpack ================================================ FILE: code/packing/test.ml ================================================ let v = X.A.v let w = X.B.w ================================================ FILE: code/parsing/basic_parser.mly ================================================ %token INT %token FLOAT %token ID %token STRING %token TRUE %token FALSE %token NULL %token LEFT_BRACE %token RIGHT_BRACE %token LEFT_BRACK %token RIGHT_BRACK %token COLON %token COMMA %token EOF %start exp %% exp: { () } ================================================ FILE: code/parsing/build_short_parser.sh ================================================ corebuild -use-menhir short_parser.mli ================================================ FILE: code/parsing/example.json ================================================ { "title": "Cities", "cities": [ { "name": "Chicago", "zips": [60601] }, { "name": "New York", "zips": [10004] } ] } ================================================ FILE: code/parsing/json.ml ================================================ type value = [ | `Assoc of (string * value) list | `Bool of bool | `Float of float | `Int of int | `List of value list | `Null | `String of string ] (* part 1 *) open Core.Std let rec output_value outc = function | `Assoc obj -> print_assoc outc obj | `List l -> print_list outc l | `String s -> printf "\"%s\"" s | `Int i -> printf "%d" i | `Float x -> printf "%f" x | `Bool true -> output_string outc "true" | `Bool false -> output_string outc "false" | `Null -> output_string outc "null" and print_assoc outc obj = output_string outc "{ "; let sep = ref "" in List.iter ~f:(fun (key, value) -> printf "%s\"%s\": %a" !sep key output_value value; sep := ",\n ") obj; output_string outc " }" and print_list outc arr = output_string outc "["; List.iteri ~f:(fun i v -> if i > 0 then output_string outc ", "; output_value outc v) arr; output_string outc "]" ================================================ FILE: code/parsing/lex.syntax ================================================ { OCaml code } let definitions... rules... { OCaml code } ================================================ FILE: code/parsing/lexer.mll ================================================ { open Lexing open Parser exception SyntaxError of string let next_line lexbuf = let pos = lexbuf.lex_curr_p in lexbuf.lex_curr_p <- { pos with pos_bol = lexbuf.lex_curr_pos; pos_lnum = pos.pos_lnum + 1 } } (* part 1 *) let int = '-'? ['0'-'9'] ['0'-'9']* (* part 2 *) let digit = ['0'-'9'] let frac = '.' digit* let exp = ['e' 'E'] ['-' '+']? digit+ let float = digit* frac? exp? (* part 3 *) let white = [' ' '\t']+ let newline = '\r' | '\n' | "\r\n" let id = ['a'-'z' 'A'-'Z' '_'] ['a'-'z' 'A'-'Z' '0'-'9' '_']* (* part 4 *) rule read = parse | white { read lexbuf } | newline { next_line lexbuf; read lexbuf } | int { INT (int_of_string (Lexing.lexeme lexbuf)) } | float { FLOAT (float_of_string (Lexing.lexeme lexbuf)) } | "true" { TRUE } | "false" { FALSE } | "null" { NULL } | '"' { read_string (Buffer.create 17) lexbuf } | '{' { LEFT_BRACE } | '}' { RIGHT_BRACE } | '[' { LEFT_BRACK } | ']' { RIGHT_BRACK } | ':' { COLON } | ',' { COMMA } | _ { raise (SyntaxError ("Unexpected char: " ^ Lexing.lexeme lexbuf)) } | eof { EOF } (* part 5 *) and read_string buf = parse | '"' { STRING (Buffer.contents buf) } | '\\' '/' { Buffer.add_char buf '/'; read_string buf lexbuf } | '\\' '\\' { Buffer.add_char buf '\\'; read_string buf lexbuf } | '\\' 'b' { Buffer.add_char buf '\b'; read_string buf lexbuf } | '\\' 'f' { Buffer.add_char buf '\012'; read_string buf lexbuf } | '\\' 'n' { Buffer.add_char buf '\n'; read_string buf lexbuf } | '\\' 'r' { Buffer.add_char buf '\r'; read_string buf lexbuf } | '\\' 't' { Buffer.add_char buf '\t'; read_string buf lexbuf } | [^ '"' '\\']+ { Buffer.add_string buf (Lexing.lexeme lexbuf); read_string buf lexbuf } | _ { raise (SyntaxError ("Illegal string character: " ^ Lexing.lexeme lexbuf)) } | eof { raise (SyntaxError ("String is not terminated")) } ================================================ FILE: code/parsing/lexer_int_fragment.mll ================================================ | int { INT (int_of_string (Lexing.lexeme lexbuf)) } ================================================ FILE: code/parsing/manual_token_type.ml ================================================ type token = | NULL | TRUE | FALSE | STRING of string | INT of int | FLOAT of float | ID of string | LEFT_BRACK | RIGHT_BRACK | LEFT_BRACE | RIGHT_BRACE | COMMA | COLON | EOF ================================================ FILE: code/parsing/parsed_example.ml ================================================ `Assoc ["title", `String "Cities"; "cities", `List [`Assoc ["name", `String "Chicago"; "zips", `List [`Int 60601]]; `Assoc ["name", `String "New York"; "zips", `List [`Int 10004]]]] ================================================ FILE: code/parsing/parser.mly ================================================ %token INT %token FLOAT %token ID %token STRING %token TRUE %token FALSE %token NULL %token LEFT_BRACE %token RIGHT_BRACE %token LEFT_BRACK %token RIGHT_BRACK %token COLON %token COMMA %token EOF (* part 1 *) %start prog %% (* part 2 *) prog: | EOF { None } | v = value { Some v } ; (* part 3 *) value: | LEFT_BRACE; obj = object_fields; RIGHT_BRACE { `Assoc obj } | LEFT_BRACK; vl = array_values; RIGHT_BRACK { `List vl } | s = STRING { `String s } | i = INT { `Int i } | x = FLOAT { `Float x } | TRUE { `Bool true } | FALSE { `Bool false } | NULL { `Null } ; (* part 4 *) object_fields: obj = rev_object_fields { List.rev obj }; rev_object_fields: | (* empty *) { [] } | obj = rev_object_fields; COMMA; k = ID; COLON; v = value { (k, v) :: obj } ; (* part 5 *) array_values: | (* empty *) { [] } | vl = rev_values { List.rev vl } ; rev_values: | v = value { [v] } | vl = rev_values; COMMA; v = value { v :: vl } ; ================================================ FILE: code/parsing/production.syntax ================================================ symbol: [ id1 = ] symbol1; [ id2 = ] symbol2; ...; [ idN = ] symbolN { OCaml code } ================================================ FILE: code/parsing/prog.mli ================================================ val prog:(Lexing.lexbuf -> token) -> Lexing.lexbuf -> Json.value option ================================================ FILE: code/parsing/quadratic_rule.mly ================================================ %token INT %token FLOAT %token ID %token STRING %token TRUE %token FALSE %token NULL %token LEFT_BRACE %token RIGHT_BRACE %token LEFT_BRACK %token RIGHT_BRACK %token COLON %token COMMA %token EOF (* part 1 *) %start prog %% (* part 2 *) prog: | EOF { None } | v = value { Some v } ; (* part 3 *) value: | LEFT_BRACE; obj = object_fields; RIGHT_BRACE { `Assoc obj } | LEFT_BRACK; vl = array_values; RIGHT_BRACK { `List vl } | s = STRING { `String s } | i = INT { `Int i } | x = FLOAT { `Float x } | TRUE { `Bool true } | FALSE { `Bool false } | NULL { `Null } ; (* part 4 *) (* Quadratic left-recursive rule *) object_fields: | (* empty *) { [] } | obj = object_fields; COMMA; k = ID; COLON; v = value { obj @ [k, v] } ; (* part 5 *) array_values: | (* empty *) { [] } | vl = rev_values { List.rev vl } ; rev_values: | v = value { [v] } | vl = rev_values; COMMA; v = value { v :: vl } ; ================================================ FILE: code/parsing/right_rec_rule.mly ================================================ %token INT %token FLOAT %token ID %token STRING %token TRUE %token FALSE %token NULL %token LEFT_BRACE %token RIGHT_BRACE %token LEFT_BRACK %token RIGHT_BRACK %token COLON %token COMMA %token EOF (* part 1 *) %start prog %% (* part 2 *) prog: | EOF { None } | v = value { Some v } ; (* part 3 *) value: | LEFT_BRACE; obj = object_fields; RIGHT_BRACE { `Assoc obj } | LEFT_BRACK; vl = array_values; RIGHT_BRACK { `List vl } | s = STRING { `String s } | i = INT { `Int i } | x = FLOAT { `Float x } | TRUE { `Bool true } | FALSE { `Bool false } | NULL { `Null } ; (* part 4 *) (* Inefficient right-recursive rule *) object_fields: | (* empty *) { [] } | k = ID; COLON; v = value; COMMA; obj = object_fields { (k, v) :: obj } (* part 5 *) array_values: /* empty */ { [] } | vl = rev_values { List.rev vl } ; rev_values: v = value { [v] } | vl = rev_values; COMMA; v = value { v :: vl } ; ================================================ FILE: code/parsing/short_parser.mly ================================================ %token INT %token FLOAT %token STRING %token TRUE %token FALSE %token NULL %token LEFT_BRACE %token RIGHT_BRACE %token LEFT_BRACK %token RIGHT_BRACK %token COLON %token COMMA %token EOF %start prog %% (* part 1 *) prog: | v = value { Some v } | EOF { None } ; value: | LEFT_BRACE; obj = obj_fields; RIGHT_BRACE { `Assoc obj } | LEFT_BRACK; vl = list_fields; RIGHT_BRACK { `List vl } | s = STRING { `String s } | i = INT { `Int i } | x = FLOAT { `Float x } | TRUE { `Bool true } | FALSE { `Bool false } | NULL { `Null } ; obj_fields: obj = separated_list(COMMA, obj_field) { obj } ; obj_field: k = STRING; COLON; v = value { (k, v) } ; list_fields: vl = separated_list(COMMA, value) { vl } ; ================================================ FILE: code/parsing/tokenized_example.ml ================================================ ================================================ FILE: code/parsing/tokens.ml ================================================ [ LEFT_BRACE; ID("title"); COLON; STRING("Cities"); COMMA; ID("cities"); ... ================================================ FILE: code/parsing/yacc.syntax ================================================ %% %% ================================================ FILE: code/parsing-test/build_json_parser.sh ================================================ corebuild -use-menhir parser.mli ================================================ FILE: code/parsing-test/build_test.sh ================================================ ocamlbuild -use-menhir -tag thread -use-ocamlfind -quiet -pkg core test.native ./test.native test1.json ================================================ FILE: code/parsing-test/run_broken_test.errsh ================================================ cat test2.json ./test.native test2.json ================================================ FILE: code/parsing-test/test.ml ================================================ open Core.Std open Lexer open Lexing let print_position outx lexbuf = let pos = lexbuf.lex_curr_p in fprintf outx "%s:%d:%d" pos.pos_fname pos.pos_lnum (pos.pos_cnum - pos.pos_bol + 1) let parse_with_error lexbuf = try Parser.prog Lexer.read lexbuf with | SyntaxError msg -> fprintf stderr "%a: %s\n" print_position lexbuf msg; None | Parser.Error -> fprintf stderr "%a: syntax error\n" print_position lexbuf; exit (-1) (* part 1 *) let rec parse_and_print lexbuf = match parse_with_error lexbuf with | Some value -> printf "%a\n" Json.output_value value; parse_and_print lexbuf | None -> () let loop filename () = let inx = In_channel.create filename in let lexbuf = Lexing.from_channel inx in lexbuf.lex_curr_p <- { lexbuf.lex_curr_p with pos_fname = filename }; parse_and_print lexbuf; In_channel.close inx (* part 2 *) let () = Command.basic ~summary:"Parse and display JSON" Command.Spec.(empty +> anon ("filename" %: file)) loop |> Command.run ================================================ FILE: code/parsing-test/test1.json ================================================ true false null [1, 2, 3., 4.0, .5, 5.5e5, 6.3] "Hello World" { "field1": "Hello", "field2": 17e13, "field3": [1, 2, 3], "field4": { "fieldA": 1, "fieldB": "Hello" } } ================================================ FILE: code/parsing-test/test2.json ================================================ { "name": "Chicago", "zips": [12345, } { "name": "New York", "zips": [10004] } ================================================ FILE: code/principal/build_principal.sh ================================================ corebuild -tag principal principal.cmi non_principal.cmi ================================================ FILE: code/records/functional_update.syntax ================================================ { with = ; = ; ... } ================================================ FILE: code/records/main-29.rawscript ================================================ # module Logon = struct type t = { session_id: string; time: Time.t; user: string; credentials: string; } with fields end;; module Logon : sig type t = { session_id : string; time : Time.t; user : string; credentials : string; } val credentials : t -> string val user : t -> string val time : t -> Time.t val session_id : t -> string module Fields : sig val names : string list val credentials : ([< `Read | `Set_and_create ], t, string) Field.t_with_perm val user : ([< `Read | `Set_and_create ], t, string) Field.t_with_perm val time : ([< `Read | `Set_and_create ], t, Time.t) Field.t_with_perm val session_id : ([< `Read | `Set_and_create ], t, string) Field.t_with_perm [ ... many definitions omitted ... ] end end ================================================ FILE: code/records/main.topscript ================================================ type host_info = { hostname : string; os_name : string; cpu_arch : string; timestamp : Time.t; };; #part 1 #require "core_extended";; open Core_extended.Std;; let my_host = let sh = Shell.sh_one_exn in { hostname = sh "hostname"; os_name = sh "uname -s"; cpu_arch = sh "uname -p"; timestamp = Time.now (); };; #part 2 my_host.cpu_arch;; #part 3 type 'a timestamped = { item: 'a; time: Time.t };; #part 4 let first_timestamped list = List.reduce list ~f:(fun a b -> if a.time < b.time then a else b) ;; #part 5 let host_info_to_string { hostname = h; os_name = os; cpu_arch = c; timestamp = ts; } = sprintf "%s (%s / %s, on %s)" h os c (Time.to_sec_string ts);; host_info_to_string my_host;; #part 6 type host_info = { hostname : string; os_name : string; cpu_arch : string; os_release : string; timestamp : Time.t; } ;; #part 7 #warnings "+9";; let host_info_to_string { hostname = h; os_name = os; cpu_arch = c; timestamp = ts; } = sprintf "%s (%s / %s, on %s)" h os c (Time.to_sec_string ts);; #part 8 let host_info_to_string { hostname = h; os_name = os; cpu_arch = c; timestamp = ts; _ } = sprintf "%s (%s / %s, on %s)" h os c (Time.to_sec_string ts);; #part 9 let host_info_to_string { hostname; os_name; cpu_arch; timestamp; _ } = sprintf "%s (%s / %s) <%s>" hostname os_name cpu_arch (Time.to_string timestamp);; #part 10 let my_host = let sh cmd = Shell.sh_one_exn cmd in let hostname = sh "hostname" in let os_name = sh "uname -s" in let cpu_arch = sh "uname -p" in let os_release = sh "uname -r" in let timestamp = Time.now () in { hostname; os_name; cpu_arch; os_release; timestamp };; #part 11 let create_host_info ~hostname ~os_name ~cpu_arch ~os_release = { os_name; cpu_arch; os_release; hostname = String.lowercase hostname; timestamp = Time.now () };; #part 12 let create_host_info ~hostname:hostname ~os_name:os_name ~cpu_arch:cpu_arch ~os_release:os_release = { os_name = os_name; cpu_arch = cpu_arch; os_release = os_release; hostname = String.lowercase hostname; timestamp = Time.now () };; #part 13 type log_entry = { session_id: string; time: Time.t; important: bool; message: string; } type heartbeat = { session_id: string; time: Time.t; status_message: string; } type logon = { session_id: string; time: Time.t; user: string; credentials: string; } ;; #part 14 let get_session_id t = t.session_id;; #part 15 let get_heartbeat_session_id (t:heartbeat) = t.session_id;; #part 16 let status_and_session t = (t.status_message, t.session_id);; let session_and_status t = (t.session_id, t.status_message);; let session_and_status (t:heartbeat) = (t.session_id, t.status_message);; #part 17 module Log_entry = struct type t = { session_id: string; time: Time.t; important: bool; message: string; } end module Heartbeat = struct type t = { session_id: string; time: Time.t; status_message: string; } end module Logon = struct type t = { session_id: string; time: Time.t; user: string; credentials: string; } end;; #part 18 let create_log_entry ~session_id ~important message = { Log_entry.time = Time.now (); Log_entry.session_id; Log_entry.important; Log_entry.message } ;; #part 19 let create_log_entry ~session_id ~important message = { Log_entry. time = Time.now (); session_id; important; message } ;; #part 20 let message_to_string { Log_entry.important; message; _ } = if important then String.uppercase message else message ;; #part 21 let is_important t = t.Log_entry.important;; #part 22 type client_info = { addr: Unix.Inet_addr.t; port: int; user: string; credentials: string; last_heartbeat_time: Time.t; };; let register_heartbeat t hb = { addr = t.addr; port = t.port; user = t.user; credentials = t.credentials; last_heartbeat_time = hb.Heartbeat.time; };; #part 23 let register_heartbeat t hb = { t with last_heartbeat_time = hb.Heartbeat.time };; #part 24 type client_info = { addr: Unix.Inet_addr.t; port: int; user: string; credentials: string; last_heartbeat_time: Time.t; last_heartbeat_status: string; };; #part 25 let register_heartbeat t hb = { t with last_heartbeat_time = hb.Heartbeat.time; last_heartbeat_status = hb.Heartbeat.status_message; };; #part 26 type client_info = { addr: Unix.Inet_addr.t; port: int; user: string; credentials: string; mutable last_heartbeat_time: Time.t; mutable last_heartbeat_status: string; };; #part 27 let register_heartbeat t hb = t.last_heartbeat_time <- hb.Heartbeat.time; t.last_heartbeat_status <- hb.Heartbeat.status_message ;; #part 28 let get_users logons = List.dedup (List.map logons ~f:(fun x -> x.Logon.user));; #part 29 module Logon = struct type t = { session_id: string; time: Time.t; user: string; credentials: string; } with fields end;; #part 30 let get_users logons = List.dedup (List.map logons ~f:Logon.user);; #part 31 Field.get Logon.Fields.user;; #part 32 Field.get;; #part 33 let show_field field to_string record = let name = Field.name field in let field_string = to_string (Field.get field record) in name ^ ": " ^ field_string ;; #part 34 let logon = { Logon. session_id = "26685"; time = Time.now (); user = "yminsky"; credentials = "Xy2d9W"; } ;; show_field Logon.Fields.user Fn.id logon;; show_field Logon.Fields.time Time.to_string logon;; #part 35 Logon.Fields.iter;; #part 36 let print_logon logon = let print to_string field = printf "%s\n" (show_field field to_string logon) in Logon.Fields.iter ~session_id:(print Fn.id) ~time:(print Time.to_string) ~user:(print Fn.id) ~credentials:(print Fn.id) ;; print_logon logon;; #part 37 #part 38 #part 39 #part 40 #part 41 #part 42 #part 43 #part 44 #part 45 #part 46 #part 47 #part 48 #part 49 #part 50 ================================================ FILE: code/records/record.syntax ================================================ type = { : ; : ; ... } ================================================ FILE: code/records/warn_help.sh ================================================ ocaml -warn-help | egrep '\b9\b' ================================================ FILE: code/sexpr/auto_making_sexp.topscript ================================================ type t = { foo: int; bar: float } with sexp ;; t_of_sexp (Sexp.of_string "((bar 35) (foo 3))") ;; #part 1 exception Bad_message of string list ;; Exn.to_string (Bad_message ["1";"2";"3"]) ;; exception Good_message of string list with sexp;; Exn.to_string (Good_message ["1";"2";"3"]) ;; ================================================ FILE: code/sexpr/basic.scm ================================================ (this (is an) (s expression)) ================================================ FILE: code/sexpr/build_read_foo.errsh ================================================ corebuild read_foo.native ./read_foo.native foo_example_broken.scm ================================================ FILE: code/sexpr/build_read_foo_better_errors.errsh ================================================ corebuild read_foo_better_errors.native ./read_foo_better_errors.native foo_example_broken.scm ================================================ FILE: code/sexpr/build_test_interval.sh ================================================ corebuild test_interval.native ./test_interval.native ================================================ FILE: code/sexpr/build_test_interval_manual_sexp.sh ================================================ corebuild test_interval_manual_sexp.native ================================================ FILE: code/sexpr/build_test_interval_nosexp.errsh ================================================ corebuild test_interval_nosexp.native ================================================ FILE: code/sexpr/comment_heavy.scm ================================================ ;; comment_heavy_example.scm ((this is included) ; (this is commented out (this stays) #; (all of this is commented out (even though it crosses lines.)) (and #| block delimiters #| which can be nested |# will comment out an arbitrary multi-line block))) |# now we're done )) ================================================ FILE: code/sexpr/example.scm ================================================ ;; example.scm ((foo 3.3) ;; This is a comment (bar "this is () an \" atom")) ================================================ FILE: code/sexpr/example_broken.scm ================================================ ;; example.scm ((foo 3.3) ;; This is a comment bar "this is () an \" atom")) ================================================ FILE: code/sexpr/example_load.topscript ================================================ Sexp.load_sexp "example.scm" ;; #part 1 Sexp.load_sexp "comment_heavy.scm" ;; #part 2 Exn.handle_uncaught ~exit:false (fun () -> ignore (Sexp.load_sexp "example_broken.scm")) ;; ================================================ FILE: code/sexpr/foo_broken_example.scm ================================================ ((a "not-an-integer") (b "not-an-integer") (c 1.0)) ================================================ FILE: code/sexpr/inline_sexp.topscript ================================================ let l = [(1,"one"); (2,"two")] ;; List.iter l ~f:(fun x -> <:sexp_of> x |> Sexp.to_string |> print_endline) ;; ================================================ FILE: code/sexpr/int_interval.ml ================================================ (* Module for representing closed integer intervals *) open Core.Std (* Invariant: For any Range (x,y), y >= x *) type t = | Range of int * int | Empty with sexp let is_empty = function | Empty -> true | Range _ -> false let create x y = if x > y then Empty else Range (x,y) let contains i x = match i with | Empty -> false | Range (low,high) -> x >= low && x <= high ================================================ FILE: code/sexpr/int_interval.mli ================================================ type t with sexp val is_empty : t -> bool val create : int -> int -> t val contains : t -> int -> bool ================================================ FILE: code/sexpr/int_interval_manual_sexp.ml ================================================ (* Module for representing closed integer intervals *) open Core.Std (* Invariant: For any Range (x,y), y >= x *) type t = | Range of int * int | Empty with sexp let is_empty = function | Empty -> true | Range _ -> false let create x y = if x > y then Empty else Range (x,y) let contains i x = match i with | Empty -> false | Range (low,high) -> x >= low && x <= high ================================================ FILE: code/sexpr/int_interval_manual_sexp.mli ================================================ open Core.Std type t val t_of_sexp : Sexp.t -> t val sexp_of_t : t -> Sexp.t val is_empty : t -> bool val create : int -> int -> t val contains : t -> int -> bool ================================================ FILE: code/sexpr/int_interval_nosexp.ml ================================================ (* Module for representing closed integer intervals *) open Core.Std (* Invariant: For any Range (x,y), y >= x *) type t = | Range of int * int | Empty with sexp let is_empty = function | Empty -> true | Range _ -> false let create x y = if x > y then Empty else Range (x,y) let contains i x = match i with | Empty -> false | Range (low,high) -> x >= low && x <= high ================================================ FILE: code/sexpr/int_interval_nosexp.mli ================================================ type t val is_empty : t -> bool val create : int -> int -> t val contains : t -> int -> bool ================================================ FILE: code/sexpr/list_top_packages.sh ================================================ ocamlfind list | grep top ================================================ FILE: code/sexpr/manually_making_sexp.topscript ================================================ type t = { foo: int; bar: float } ;; let sexp_of_t t = let a x = Sexp.Atom x and l x = Sexp.List x in l [ l [a "foo"; Int.sexp_of_t t.foo ]; l [a "bar"; Float.sexp_of_t t.bar]; ] ;; sexp_of_t { foo = 3; bar = -5.5 } ;; ================================================ FILE: code/sexpr/print_sexp.topscript ================================================ Sexp.List [ Sexp.Atom "this"; Sexp.List [ Sexp.Atom "is"; Sexp.Atom "an"]; Sexp.List [ Sexp.Atom "s"; Sexp.Atom "expression" ]; ];; ================================================ FILE: code/sexpr/read_foo.ml ================================================ open Core.Std type t = { a: string; b: int; c: float option } with sexp let run () = let t = Sexp.load_sexp "foo_broken_example.scm" |> t_of_sexp in printf "b is: %d\n%!" t.b let () = Exn.handle_uncaught ~exit:true run ================================================ FILE: code/sexpr/read_foo_better_errors.ml ================================================ open Core.Std type t = { a: string; b: int; c: float option } with sexp let run () = let t = Sexp.load_sexp_conv_exn "foo_broken_example.scm" t_of_sexp in printf "b is: %d\n%!" t.b let () = Exn.handle_uncaught ~exit:true run ================================================ FILE: code/sexpr/sexp.mli ================================================ module Sexp : sig type t = | Atom of string | List of t list end ================================================ FILE: code/sexpr/sexp_default.topscript ================================================ type http_server_config = { web_root: string; port: int; addr: string; } with sexp ;; #part 1 type http_server_config = { web_root: string; port: int with default(80); addr: string with default("localhost"); } with sexp ;; #part 2 let cfg = http_server_config_of_sexp (Sexp.of_string "((web_root /var/www/html))") ;; #part 3 sexp_of_http_server_config cfg ;; #part 4 type http_server_config = { web_root: string; port: int with default(80), sexp_drop_default; addr: string with default("localhost"), sexp_drop_default; } with sexp ;; let cfg = http_server_config_of_sexp (Sexp.of_string "((web_root /var/www/html))") ;; sexp_of_http_server_config cfg ;; #part 5 sexp_of_http_server_config { cfg with port = 8080 } ;; sexp_of_http_server_config { cfg with port = 8080; addr = "192.168.0.1" } ;; ================================================ FILE: code/sexpr/sexp_list.topscript ================================================ type compatible_versions = | Specific of string list | All with sexp ;; sexp_of_compatible_versions (Specific ["3.12.0"; "3.12.1"; "3.13.0"]) ;; #part 1 type compatible_versions = | Specific of string sexp_list | All with sexp ;; sexp_of_compatible_versions (Specific ["3.12.0"; "3.12.1"; "3.13.0"]) ;; ================================================ FILE: code/sexpr/sexp_opaque.topscript ================================================ type no_converter = int * int ;; type t = { a: no_converter; b: string } with sexp ;; #part 1 type t = { a: no_converter sexp_opaque; b: string } with sexp ;; #part 2 sexp_of_t { a = (3,4); b = "foo" } ;; #part 3 t_of_sexp (Sexp.of_string "((a whatever) (b foo))") ;; #part 4 type t = { a: no_converter sexp_opaque list; b: string } with sexp ;; t_of_sexp (Sexp.of_string "((a ()) (b foo))") ;; #part 5 type t = { a: no_converter sexp_opaque; b: string } with sexp_of ;; type t = { a: no_converter sexp_opaque; b: string } with of_sexp ;; ================================================ FILE: code/sexpr/sexp_option.topscript ================================================ type t = { a: int option; b: string } with sexp ;; sexp_of_t { a = None; b = "hello" } ;; sexp_of_t { a = Some 3; b = "hello" } ;; #part 1 type t = { a: int sexp_option; b: string } with sexp ;; sexp_of_t { a = Some 3; b = "hello" } ;; sexp_of_t { a = None; b = "hello" } ;; ================================================ FILE: code/sexpr/sexp_override.ml ================================================ type t = | Range of int * int | Empty with sexp let create x y = if x > y then Empty else Range (x,y) let t_of_sexp sexp = let t = t_of_sexp sexp in begin match t with | Empty -> () | Range (x,y) -> if y < x then of_sexp_error "Upper and lower bound of Range swapped" sexp end; t ================================================ FILE: code/sexpr/sexp_printer.topscript ================================================ Sexp.to_string (Sexp.List [Sexp.Atom "1"; Sexp.Atom "2"]) ;; Sexp.of_string ("(1 2 (3 4))") ;; ================================================ FILE: code/sexpr/test_interval.ml ================================================ open Core.Std let intervals = let module I = Int_interval in [ I.create 3 4; I.create 5 4; (* should be empty *) I.create 2 3; I.create 1 6; ] let () = intervals |> List.sexp_of_t Int_interval.sexp_of_t |> Sexp.to_string_hum |> print_endline ================================================ FILE: code/sexpr/test_interval_manual_sexp.ml ================================================ open Core.Std module Int_interval = Int_interval_manual_sexp let intervals = let module I = Int_interval in [ I.create 3 4; I.create 5 4; (* should be empty *) I.create 2 3; I.create 1 6; ] let () = intervals |> List.sexp_of_t Int_interval.sexp_of_t |> Sexp.to_string_hum |> print_endline ================================================ FILE: code/sexpr/test_interval_nosexp.ml ================================================ open Core.Std module Int_interval = Int_interval_nosexp let intervals = let module I = Int_interval in [ I.create 3 4; I.create 5 4; (* should be empty *) I.create 2 3; I.create 1 6; ] let () = intervals |> List.sexp_of_t Int_interval.sexp_of_t |> Sexp.to_string_hum |> print_endline ================================================ FILE: code/sexpr/to_from_sexp.topscript ================================================ Int.sexp_of_t 3;; String.sexp_of_t "hello";; Exn.sexp_of_t (Invalid_argument "foo");; #part 1 List.sexp_of_t;; List.sexp_of_t Int.sexp_of_t [1; 2; 3];; #part 2 List.t_of_sexp;; List.t_of_sexp Int.t_of_sexp (Sexp.of_string "(1 2 3)");; List.t_of_sexp Int.t_of_sexp (Sexp.of_string "(1 2 three)");; ================================================ FILE: code/variables-and-functions/abs_diff.mli ================================================ val abs_diff : int -> (int -> int) ================================================ FILE: code/variables-and-functions/htable_sig1.ml ================================================ val create_hashtable : int -> bool -> ('a,'b) Hashtable.t ================================================ FILE: code/variables-and-functions/htable_sig2.ml ================================================ val create_hashtable : init_size:int -> allow_shrinking:bool -> ('a,'b) Hashtable.t ================================================ FILE: code/variables-and-functions/let.syntax ================================================ let = ================================================ FILE: code/variables-and-functions/let_in.syntax ================================================ let = in ================================================ FILE: code/variables-and-functions/main.topscript ================================================ let x = 3;; let y = 4;; let z = x + y;; #part 1 let languages = "OCaml,Perl,C++,C";; let dashed_languages = let language_list = String.split languages ~on:',' in String.concat ~sep:"-" language_list ;; #part 2 language_list;; #part 3 let languages = "OCaml,Perl,C++,C";; let dashed_languages = let languages = String.split languages ~on:',' in String.concat ~sep:"-" languages ;; #part 4 languages;; #part 5 let area_of_ring inner_radius outer_radius = let pi = acos (-1.) in let area_of_circle r = pi *. r *. r in area_of_circle outer_radius -. area_of_circle inner_radius ;; area_of_ring 1. 3.;; #part 6 let area_of_ring inner_radius outer_radius = let pi = acos (-1.) in let area_of_circle r = pi *. r *. r in let pi = 0. in area_of_circle outer_radius -. area_of_circle inner_radius ;; #part 7 let (ints,strings) = List.unzip [(1,"one"); (2,"two"); (3,"three")];; #part 8 let upcase_first_entry line = let (first :: rest) = String.split ~on:',' line in String.concat ~sep:"," (String.uppercase first :: rest) ;; #part 9 let upcase_first_entry line = match String.split ~on:',' line with | [] -> assert false (* String.split returns at least one element *) | first :: rest -> String.concat ~sep:"," (String.uppercase first :: rest) ;; #part 10 (fun x -> x + 1);; #part 11 (fun x -> x + 1) 7;; #part 12 List.map ~f:(fun x -> x + 1) [1;2;3];; #part 13 let increments = [ (fun x -> x + 1); (fun x -> x + 2) ] ;; List.map ~f:(fun g -> g 5) increments;; #part 14 let plusone = (fun x -> x + 1);; plusone 3;; #part 15 let plusone x = x + 1;; #part 16 (fun x -> x + 1) 7;; let x = 7 in x + 1;; #part 17 let abs_diff x y = abs (x - y);; abs_diff 3 4;; #part 18 let abs_diff = (fun x -> (fun y -> abs (x - y)));; #part 19 let dist_from_3 = abs_diff 3;; dist_from_3 8;; dist_from_3 (-1);; #part 20 let abs_diff = (fun x y -> abs (x - y));; #part 21 let abs_diff (x,y) = abs (x - y);; abs_diff (3,4);; #part 22 let rec find_first_stutter list = match list with | [] | [_] -> (* only zero or one elements, so no repeats *) None | x :: y :: tl -> if x = y then Some x else find_first_stutter (y::tl) ;; #part 23 let rec is_even x = if x = 0 then true else is_odd (x - 1) and is_odd x = if x = 0 then false else is_even (x - 1) ;; List.map ~f:is_even [0;1;2;3;4;5];; List.map ~f:is_odd [0;1;2;3;4;5];; #part 24 Int.max 3 4 (* prefix *);; 3 + 4 (* infix *);; #part 25 (+) 3 4;; List.map ~f:((+) 3) [4;5;6];; #part 26 let (+!) (x1,y1) (x2,y2) = (x1 + x2, y1 + y2);; (3,2) +! (-2,4);; #part 27 let (***) x y = (x ** y) ** y;; #part 28 let ( *** ) x y = (x ** y) ** y;; #part 29 Int.max 3 (-4);; Int.max 3 -4;; #part 30 (Int.max 3) - 4;; #part 31 let (|>) x f = f x ;; #part 32 let path = "/usr/bin:/usr/local/bin:/bin:/sbin";; String.split ~on:':' path |> List.dedup ~compare:String.compare |> List.iter ~f:print_endline ;; #part 33 let split_path = String.split ~on:':' path in let deduped_path = List.dedup ~compare:String.compare split_path in List.iter ~f:print_endline deduped_path ;; #part 34 List.iter ~f:print_endline ["Two"; "lines"];; #part 35 List.iter ~f:print_endline;; #part 36 let (^>) x f = f x;; Sys.getenv_exn "PATH" ^> String.split ~on:':' path ^> List.dedup ~compare:String.compare ^> List.iter ~f:print_endline ;; #part 37 let some_or_zero = function | Some x -> x | None -> 0 ;; List.map ~f:some_or_zero [Some 3; None; Some 4];; #part 38 let some_or_zero num_opt = match num_opt with | Some x -> x | None -> 0 ;; #part 39 let some_or_default default = function | Some x -> x | None -> default ;; some_or_default 3 (Some 5);; List.map ~f:(some_or_default 100) [Some 3; None; Some 4];; #part 40 let ratio ~num ~denom = float num /. float denom;; #part 41 ratio ~num:3 ~denom:10;; ratio ~denom:10 ~num:3;; #part 42 let num = 3 in let denom = 4 in ratio ~num ~denom;; #part 43 String.split ~on:':' path |> List.dedup ~compare:String.compare |> List.iter ~f:print_endline ;; #part 44 let apply_to_tuple f (first,second) = f ~first ~second;; #part 45 let apply_to_tuple_2 f (first,second) = f ~second ~first;; #part 46 let divide ~first ~second = first / second;; #part 47 apply_to_tuple_2 divide (3,4);; #part 48 let apply_to_tuple f (first,second) = f ~first ~second;; apply_to_tuple divide (3,4);; #part 49 let concat ?sep x y = let sep = match sep with None -> "" | Some x -> x in x ^ sep ^ y ;; concat "foo" "bar" (* without the optional argument *);; concat ~sep:":" "foo" "bar" (* with the optional argument *);; #part 50 let concat ?(sep="") x y = x ^ sep ^ y ;; #part 51 concat ~sep:":" "foo" "bar" (* provide the optional argument *);; concat ?sep:(Some ":") "foo" "bar" (* pass an explicit [Some] *);; #part 52 concat "foo" "bar" (* don't provide the optional argument *);; concat ?sep:None "foo" "bar" (* explicitly pass `None` *);; #part 53 let uppercase_concat ?(sep="") a b = concat ~sep (String.uppercase a) b ;; uppercase_concat "foo" "bar";; uppercase_concat "foo" "bar" ~sep:":";; #part 54 let uppercase_concat ?sep a b = concat ?sep (String.uppercase a) b ;; #part 55 let numeric_deriv ~delta ~x ~y ~f = let x' = x +. delta in let y' = y +. delta in let base = f ~x ~y in let dx = (f ~x:x' ~y -. base) /. delta in let dy = (f ~x ~y:y' -. base) /. delta in (dx,dy) ;; #part 56 let numeric_deriv ~delta ~x ~y ~f = let x' = x +. delta in let y' = y +. delta in let base = f ~x ~y in let dx = (f ~y ~x:x' -. base) /. delta in let dy = (f ~x ~y:y' -. base) /. delta in (dx,dy) ;; #part 57 let numeric_deriv ~delta ~x ~y ~(f: x:float -> y:float -> float) = let x' = x +. delta in let y' = y +. delta in let base = f ~x ~y in let dx = (f ~y ~x:x' -. base) /. delta in let dy = (f ~x ~y:y' -. base) /. delta in (dx,dy) ;; #part 58 let colon_concat = concat ~sep:":";; colon_concat "a" "b";; #part 59 let prepend_pound = concat "# ";; prepend_pound "a BASH comment";; #part 60 prepend_pound "a BASH comment" ~sep:":";; #part 61 let concat x ?(sep="") y = x ^ sep ^ y ;; #part 62 let prepend_pound = concat "# ";; prepend_pound "a BASH comment";; prepend_pound "a BASH comment" ~sep:"--- ";; #part 63 concat "a" "b" ~sep:"=";; #part 64 let concat x y ?(sep="") = x ^ sep ^ y ;; #part 65 concat "a" "b";; #part 66 #part 67 #part 68 #part 69 #part 70 #part 71 #part 72 #part 73 #part 74 #part 75 #part 76 #part 77 #part 78 #part 79 ================================================ FILE: code/variables-and-functions/numerical_deriv_alt_sig.mli ================================================ val numeric_deriv : delta:float -> x:float -> y:float -> f:(?x:float -> y:float -> float) -> float * float ================================================ FILE: code/variables-and-functions/operators.syntax ================================================ ! $ % & * + - . / : < = > ? @ ^ | ~ ================================================ FILE: code/variables-and-functions/substring_sig1.ml ================================================ val substring: string -> int -> int -> string ================================================ FILE: code/variables-and-functions/substring_sig2.ml ================================================ val substring: string -> pos:int -> len:int -> string ================================================ FILE: code/variants/blang.topscript ================================================ type 'a expr = | Base of 'a | Const of bool | And of 'a expr list | Or of 'a expr list | Not of 'a expr ;; #part 1 type mail_field = To | From | CC | Date | Subject type mail_predicate = { field: mail_field; contains: string } ;; #part 2 let test field contains = Base { field; contains };; And [ Or [ test To "doligez"; test CC "doligez" ]; test Subject "runtime"; ] ;; #part 3 let rec eval expr base_eval = (* a shortcut, so we don't need to repeatedly pass [base_eval] explicitly to [eval] *) let eval' expr = eval expr base_eval in match expr with | Base base -> base_eval base | Const bool -> bool | And exprs -> List.for_all exprs ~f:eval' | Or exprs -> List.exists exprs ~f:eval' | Not expr -> not (eval' expr) ;; #part 4 let and_ l = if List.mem l (Const false) then Const false else match List.filter l ~f:((<>) (Const true)) with | [] -> Const true | [ x ] -> x | l -> And l let or_ l = if List.mem l (Const true) then Const true else match List.filter l ~f:((<>) (Const false)) with | [] -> Const false | [x] -> x | l -> Or l let not_ = function | Const b -> Const (not b) | e -> Not e ;; #part 5 let rec simplify = function | Base _ | Const _ as x -> x | And l -> and_ (List.map ~f:simplify l) | Or l -> or_ (List.map ~f:simplify l) | Not e -> not_ (simplify e) ;; #part 6 simplify (Not (And [ Or [Base "it's snowing"; Const true]; Base "it's raining"]));; #part 7 simplify (Not (And [ Or [Base "it's snowing"; Const true]; Not (Not (Base "it's raining"))]));; #part 8 let not_ = function | Const b -> Const (not b) | (Base _ | And _ | Or _ | Not _) as e -> Not e ;; #part 9 let not_ = function | Const b -> Const (not b) | Not e -> e | (Base _ | And _ | Or _ ) as e -> Not e ;; ================================================ FILE: code/variants/catch_all.topscript ================================================ type basic_color = | Black | Red | Green | Yellow | Blue | Magenta | Cyan | White ;; let basic_color_to_int = function | Black -> 0 | Red -> 1 | Green -> 2 | Yellow -> 3 | Blue -> 4 | Magenta -> 5 | Cyan -> 6 | White -> 7 ;; #part 1 type color = | Basic of basic_color (* basic colors *) | Bold of basic_color (* bold basic colors *) | RGB of int * int * int (* 6x6x6 color cube *) | Gray of int (* 24 grayscale levels *) ;; #part 2 let color_to_int = function | Basic (basic_color,weight) -> let base = match weight with Bold -> 8 | Regular -> 0 in base + basic_color_to_int basic_color | RGB (r,g,b) -> 16 + b + g * 6 + r * 36 | Gray i -> 232 + i ;; #part 3 let color_to_int = function | Basic basic_color -> basic_color_to_int basic_color | RGB (r,g,b) -> 16 + b + g * 6 + r * 36 | Gray i -> 232 + i ;; #part 4 let color_to_int = function | Basic basic_color -> basic_color_to_int basic_color | Bold basic_color -> 8 + basic_color_to_int basic_color | RGB (r,g,b) -> 16 + b + g * 6 + r * 36 | Gray i -> 232 + i ;; #part 5 let oldschool_color_to_int = function | Basic (basic_color,weight) -> let base = match weight with Bold -> 8 | Regular -> 0 in base + basic_color_to_int basic_color | _ -> basic_color_to_int White;; ================================================ FILE: code/variants/logger.topscript ================================================ module Heartbeat = struct type t = { session_id: string; time: Time.t; status_message: string; } end module Logon = struct type t = { session_id: string; time: Time.t; user: string; credentials: string; } end;; #part 1 module Log_entry = struct type t = { session_id: string; time: Time.t; important: bool; message: string; } end ;; #part 2 type client_message = | Logon of Logon.t | Heartbeat of Heartbeat.t | Log_entry of Log_entry.t ;; #part 3 let messages_for_user user messages = let (user_messages,_) = List.fold messages ~init:([],String.Set.empty) ~f:(fun ((messages,user_sessions) as acc) message -> match message with | Logon m -> if m.Logon.user = user then (message::messages, Set.add user_sessions m.Logon.session_id) else acc | Heartbeat _ | Log_entry _ -> let session_id = match message with | Logon m -> m.Logon.session_id | Heartbeat m -> m.Heartbeat.session_id | Log_entry m -> m.Log_entry.session_id in if Set.mem user_sessions session_id then (message::messages,user_sessions) else acc ) in List.rev user_messages ;; #part 4 module Log_entry = struct type t = { important: bool; message: string; } end module Heartbeat = struct type t = { status_message: string; } end module Logon = struct type t = { user: string; credentials: string; } end ;; #part 5 type details = | Logon of Logon.t | Heartbeat of Heartbeat.t | Log_entry of Log_entry.t ;; #part 6 module Common = struct type t = { session_id: string; time: Time.t; } end ;; #part 7 let messages_for_user user messages = let (user_messages,_) = List.fold messages ~init:([],String.Set.empty) ~f:(fun ((messages,user_sessions) as acc) ((common,details) as message) -> let session_id = common.Common.session_id in match details with | Logon m -> if m.Logon.user = user then (message::messages, Set.add user_sessions session_id) else acc | Heartbeat _ | Log_entry _ -> if Set.mem user_sessions session_id then (message::messages,user_sessions) else acc ) in List.rev user_messages ;; #part 8 let handle_message server_state (common,details) = match details with | Log_entry m -> handle_log_entry server_state (common,m) | Logon m -> handle_logon server_state (common,m) | Heartbeat m -> handle_heartbeat server_state (common,m) ;; ================================================ FILE: code/variants/main-2.rawscript ================================================ # let color_by_number number text = sprintf "\027[38;5;%dm%s\027[0m" number text;; val color_by_number : int -> string -> string = # let blue = color_by_number (basic_color_to_int Blue) "Blue";; val blue : string = "\027[38;5;4mBlue\027[0m" # printf "Hello %s World!\n" blue;; Hello Blue World! ================================================ FILE: code/variants/main-5.rawscript ================================================ # let color_print color s = printf "%s\n" (color_by_number (color_to_int color) s);; val color_print : color -> string -> unit = # color_print (Basic (Red,Bold)) "A bold red!";; A bold red! # color_print (Gray 4) "A muted gray...";; A muted gray... ================================================ FILE: code/variants/main.topscript ================================================ type basic_color = | Black | Red | Green | Yellow | Blue | Magenta | Cyan | White ;; Cyan ;; [Blue; Magenta; Red] ;; #part 1 let basic_color_to_int = function | Black -> 0 | Red -> 1 | Green -> 2 | Yellow -> 3 | Blue -> 4 | Magenta -> 5 | Cyan -> 6 | White -> 7 ;; List.map ~f:basic_color_to_int [Blue;Red];; #part 2 let color_by_number number text = sprintf "\027[38;5;%dm%s\027[0m" number text;; let blue = color_by_number (basic_color_to_int Blue) "Blue";; (* printf "Hello %s World!\n" blue*) ();; #part 3 type weight = Regular | Bold type color = | Basic of basic_color * weight (* basic colors, regular and bold *) | RGB of int * int * int (* 6x6x6 color cube *) | Gray of int (* 24 grayscale levels *) ;; [RGB (250,70,70); Basic (Green, Regular)];; #part 4 let color_to_int = function | Basic (basic_color,weight) -> let base = match weight with Bold -> 8 | Regular -> 0 in base + basic_color_to_int basic_color | RGB (r,g,b) -> 16 + b + g * 6 + r * 36 | Gray i -> 232 + i ;; #part 5 let color_print color s = printf "%s\n" (color_by_number (color_to_int color) s);; (* color_print (Basic (Red,Bold)) "A bold red!"*) ();; (* color_print (Gray 4) "A muted gray..." *) ();; #part 6 let three = `Int 3;; let four = `Float 4.;; let nan = `Not_a_number;; [three; four; nan];; #part 7 let five = `Int "five";; [three; four; five];; #part 8 let is_positive = function | `Int x -> x > 0 | `Float x -> x > 0. ;; #part 9 let exact = List.filter ~f:is_positive [three;four];; #part 10 let is_positive = function | `Int x -> Ok (x > 0) | `Float x -> Ok (x > 0.) | `Not_a_number -> Error "not a number";; List.filter [three; four] ~f:(fun x -> match is_positive x with Error _ -> false | Ok b -> b);; #part 11 type extended_color = | Basic of basic_color * weight (* basic colors, regular and bold *) | RGB of int * int * int (* 6x6x6 color space *) | Gray of int (* 24 grayscale levels *) | RGBA of int * int * int * int (* 6x6x6x6 color space *) ;; #part 12 let extended_color_to_int = function | RGBA (r,g,b,a) -> 256 + a + b * 6 + g * 36 + r * 216 | (Basic _ | RGB _ | Gray _) as color -> color_to_int color ;; #part 13 let basic_color_to_int = function | `Black -> 0 | `Red -> 1 | `Green -> 2 | `Yellow -> 3 | `Blue -> 4 | `Magenta -> 5 | `Cyan -> 6 | `White -> 7 let color_to_int = function | `Basic (basic_color,weight) -> let base = match weight with `Bold -> 8 | `Regular -> 0 in base + basic_color_to_int basic_color | `RGB (r,g,b) -> 16 + b + g * 6 + r * 36 | `Gray i -> 232 + i ;; #part 14 let extended_color_to_int = function | `RGBA (r,g,b,a) -> 256 + a + b * 6 + g * 36 + r * 216 | (`Basic _ | `RGB _ | `Gray _) as color -> color_to_int color ;; #part 15 let extended_color_to_int = function | `RGBA (r,g,b,a) -> 256 + a + b * 6 + g * 36 + r * 216 | color -> color_to_int color ;; #part 16 let is_positive_permissive = function | `Int x -> Ok (x > 0) | `Float x -> Ok (x > 0.) | _ -> Error "Unknown number type" ;; is_positive_permissive (`Int 0);; is_positive_permissive (`Ratio (3,4));; #part 17 is_positive_permissive (`Floot 3.5);; #part 18 #part 19 #part 20 #part 21 #part 22 #part 23 #part 24 #part 25 #part 26 #part 27 #part 28 #part 29 #part 30 #part 31 #part 32 #part 33 #part 34 #part 35 #part 36 #part 37 #part 38 #part 39 #part 40 #part 41 #part 42 #part 43 #part 44 #part 45 #part 46 #part 47 #part 48 #part 49 #part 50 ================================================ FILE: code/variants/variant.syntax ================================================ type = | [ of [* ]... ] | [ of [* ]... ] | ... ================================================ FILE: code/variants-termcol/build.sh ================================================ corebuild terminal_color.native ================================================ FILE: code/variants-termcol/terminal_color.ml ================================================ open Core.Std type basic_color = [ `Black | `Blue | `Cyan | `Green | `Magenta | `Red | `White | `Yellow ] type color = [ `Basic of basic_color * [ `Bold | `Regular ] | `Gray of int | `RGB of int * int * int ] type extended_color = [ color | `RGBA of int * int * int * int ] let basic_color_to_int = function | `Black -> 0 | `Red -> 1 | `Green -> 2 | `Yellow -> 3 | `Blue -> 4 | `Magenta -> 5 | `Cyan -> 6 | `White -> 7 let color_to_int = function | `Basic (basic_color,weight) -> let base = match weight with `Bold -> 8 | `Regular -> 0 in base + basic_color_to_int basic_color | `RGB (r,g,b) -> 16 + b + g * 6 + r * 36 | `Gray i -> 232 + i let extended_color_to_int = function | `RGBA (r,g,b,a) -> 256 + a + b * 6 + g * 36 + r * 216 | `Grey x -> 2000 + x | (`Basic _ | `RGB _ | `Gray _) as color -> color_to_int color ================================================ FILE: code/variants-termcol/terminal_color.mli ================================================ open Core.Std type basic_color = [ `Black | `Blue | `Cyan | `Green | `Magenta | `Red | `White | `Yellow ] type color = [ `Basic of basic_color * [ `Bold | `Regular ] | `Gray of int | `RGB of int * int * int ] type extended_color = [ color | `RGBA of int * int * int * int ] val color_to_int : color -> int val extended_color_to_int : extended_color -> int ================================================ FILE: code/variants-termcol-annotated/build.errsh ================================================ corebuild terminal_color.native ================================================ FILE: code/variants-termcol-annotated/terminal_color.ml ================================================ open Core.Std type basic_color = [ `Black | `Blue | `Cyan | `Green | `Magenta | `Red | `White | `Yellow ] type color = [ `Basic of basic_color * [ `Bold | `Regular ] | `Gray of int | `RGB of int * int * int ] type extended_color = [ color | `RGBA of int * int * int * int ] let basic_color_to_int = function | `Black -> 0 | `Red -> 1 | `Green -> 2 | `Yellow -> 3 | `Blue -> 4 | `Magenta -> 5 | `Cyan -> 6 | `White -> 7 let color_to_int = function | `Basic (basic_color,weight) -> let base = match weight with `Bold -> 8 | `Regular -> 0 in base + basic_color_to_int basic_color | `RGB (r,g,b) -> 16 + b + g * 6 + r * 36 | `Gray i -> 232 + i (* part 1 *) let extended_color_to_int : extended_color -> int = function | `RGBA (r,g,b,a) -> 256 + a + b * 6 + g * 36 + r * 216 | `Grey x -> 2000 + x | (`Basic _ | `RGB _ | `Gray _) as color -> color_to_int color ================================================ FILE: code/variants-termcol-annotated/terminal_color.mli ================================================ open Core.Std type basic_color = [ `Black | `Blue | `Cyan | `Green | `Magenta | `Red | `White | `Yellow ] type color = [ `Basic of basic_color * [ `Bold | `Regular ] | `Gray of int | `RGB of int * int * int ] type extended_color = [ color | `RGBA of int * int * int * int ] val color_to_int : color -> int val extended_color_to_int : extended_color -> int ================================================ FILE: code/variants-termcol-fixed/build.sh ================================================ corebuild terminal_color.native ================================================ FILE: code/variants-termcol-fixed/terminal_color.ml ================================================ open Core.Std type basic_color = [ `Black | `Blue | `Cyan | `Green | `Magenta | `Red | `White | `Yellow ] type color = [ `Basic of basic_color * [ `Bold | `Regular ] | `Gray of int | `RGB of int * int * int ] type extended_color = [ color | `RGBA of int * int * int * int ] let basic_color_to_int = function | `Black -> 0 | `Red -> 1 | `Green -> 2 | `Yellow -> 3 | `Blue -> 4 | `Magenta -> 5 | `Cyan -> 6 | `White -> 7 let color_to_int = function | `Basic (basic_color,weight) -> let base = match weight with `Bold -> 8 | `Regular -> 0 in base + basic_color_to_int basic_color | `RGB (r,g,b) -> 16 + b + g * 6 + r * 36 | `Gray i -> 232 + i (* part 1 *) let extended_color_to_int : extended_color -> int = function | `RGBA (r,g,b,a) -> 256 + a + b * 6 + g * 36 + r * 216 | #color as color -> color_to_int color ================================================ FILE: code/variants-termcol-fixed/terminal_color.mli ================================================ open Core.Std type basic_color = [ `Black | `Blue | `Cyan | `Green | `Magenta | `Red | `White | `Yellow ] type color = [ `Basic of basic_color * [ `Bold | `Regular ] | `Gray of int | `RGB of int * int * int ] type extended_color = [ color | `RGBA of int * int * int * int ] val color_to_int : color -> int val extended_color_to_int : extended_color -> int