diff --git a/Jenkinsfile b/Jenkinsfile index 79037b558..e4d75a5e9 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -31,7 +31,7 @@ def runCompileTestsAtO1 = false catchError { withEnv([ 'CXX=clang++-6.0', - 'MACOS_SWITCH=stanc3-ocaml5.5', + 'MACOS_SWITCH=stanc3-ocaml5.5-nobase', 'GIT_AUTHOR_NAME=Stan Jenkins', 'GIT_AUTHOR_EMAIL=mc.stanislaw@gmail.com', 'GIT_COMMITTER_NAME=Stan Jenkins', @@ -280,7 +280,7 @@ catchError { export PATH=/Users/jenkins/brew/bin:$PATH eval $(opam env --switch="$MACOS_SWITCH" --set-switch) opam update - opam install dune + opam install -y dune dune-build-info ''' withEnv([ 'SDKROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX10.11.sdk', diff --git a/docs/core_ideas.mld b/docs/core_ideas.mld index 580113495..9511493d5 100644 --- a/docs/core_ideas.mld +++ b/docs/core_ideas.mld @@ -4,29 +4,30 @@ This is not meant to be tutorial on the OCaml language itself, but rather on som features and libraries of Stanc3 which may not be familiar to developers who do have some OCaml exposure. -{1 The Jane Street standard library} +{1 Labeled standard library} -We use Jane Street's {{:https://ocaml.janestreet.com/ocaml-core/v0.14/doc/core/index.html}Core} -standard library. There are a few differences from the OCaml standard library which are instantly noticeable: +We have a module called [Std] which is used throughout the code base. +This is built on the OCaml standard library, but with a few differences: {ul {- Most higher-order functions such as [List.map] take a {i named} function argument. This means a call like [List.map square [1;2;3]] will look like [List.map ~f:square [1;2;3]].} -{- Core defaults to safe operations which return {i options} rather than possibly erring. +{- A few operations are renamed. In "normal" OCaml, [List.hd] has type ['a list -> 'a]. A call [List.hd []] will throw an exception. - By contrast, in the Jane Street libraries, the same function has type ['a list -> 'a option]. + By contrast, in [Std], the same function has type ['a list -> 'a option]. - Usually, a function with the suffix [_exn] recovers the original signature, e.g. [List.hd_exn : 'a list -> 'a ].} + When we have overriden the standard name, a function with the suffix [_exn] recovers the original + signature, e.g. [List.hd_exn : 'a list -> 'a ].} } -If for some reason you {e need} functionality from the OCaml standard library that is not available in Jane Street -(be sure to triple check), you can use the module [Stdlib] to access the built-in versions. +If for some reason you {e need} functionality from the OCaml standard library that is not available from +our re-exports, you can use the module [Stdlib] to access the built-in versions. -There are a few other things we gain from these libraries. The most important idea to understand is {b deriving}. +Another difference between our code base and 'normal' OCaml is our use of {b deriving}. {2 Deriving functions} diff --git a/docs/dependencies.mld b/docs/dependencies.mld index 61aa1be97..d2961b96b 100644 --- a/docs/dependencies.mld +++ b/docs/dependencies.mld @@ -12,7 +12,6 @@ These are automatically installed through the [scripts/install_ocaml.sh] and - OCaml 5.5.0 - Dune 3.5+ -- {{:https://ocaml.org/p/base/v0.17.3/doc/index.html}Base} v0.17.3 (a standard library replacement) - {{:http://gallium.inria.fr/~fpottier/menhir/manual.html}Menhir} 20260209 (a parser generator and parsing library) - {{:https://github.com/ocaml-ppx/ppx_deriving}ppx_deriving} 6.1.1 (a tool for generating boilerplate code) - {{:https://erratique.ch/software/fmt}fmt} 0.11.0 (a library for pretty-printing of formatted text) diff --git a/docs/index.mld b/docs/index.mld index 5aa30e030..de23dc17c 100644 --- a/docs/index.mld +++ b/docs/index.mld @@ -50,6 +50,7 @@ All contributions must follow the {{:https://github.com/stan-dev/stan/wiki/AI-Co The major code sections of the compiler are as follows (these are links): {!modules: +Std Driver Frontend Middle diff --git a/dune-project b/dune-project index 39ead62a7..8844ec25d 100644 --- a/dune-project +++ b/dune-project @@ -15,8 +15,6 @@ (depends (ocaml (= 5.5.0)) - (base - (= v0.17.3)) (menhir (= 20260209)) (fmt @@ -29,10 +27,8 @@ (= 6.1.1)) ppx_compare ppx_sexp_conv - ppx_expect - ppx_inline_test - ppx_pipebang - ppx_sexp_value + ppx_expect_nobase + (ppx_sexp_value :with-test) (ocamlformat (and :with-dev-setup diff --git a/scripts/docker/ci/Dockerfile b/scripts/docker/ci/Dockerfile index 595f5ad5e..c1e5bc2f6 100644 --- a/scripts/docker/ci/Dockerfile +++ b/scripts/docker/ci/Dockerfile @@ -21,9 +21,9 @@ RUN mkdir -p -m 755 /etc/apt/keyrings && wget -qO- https://cli.github.com/packag && apt update \ && apt install gh -y -# opam -RUN bash -c "printf '\n' | sh <(curl -fsSL https://opam.ocaml.org/install.sh)" +# opam +RUN bash -c "printf '\n' | sh <(curl -fsSL https://opam.ocaml.org/install.sh) " USER ubuntu WORKDIR /home/ubuntu diff --git a/scripts/install_build_deps.sh b/scripts/install_build_deps.sh index 0d83289ce..093c7cabc 100755 --- a/scripts/install_build_deps.sh +++ b/scripts/install_build_deps.sh @@ -5,9 +5,10 @@ set -e eval $(opam env) -opam pin -y base v0.17.3 --no-action +# until next versions of the _nobase packages are published, this avoids a heavy opam-core dependency +opam pin -y ppx_expect_nobase https://github.com/Kakadu/ppx_expect_nobase.git#3436e63f7c94887da735818933c5db138e1dac1a --no-action -opam install -y dune base.v0.17.3 menhir.20260209 ppx_deriving.6.1.1 fmt.0.11.0 yojson.3.0.0 cmdliner.2.1.1\ - ppx_compare ppx_sexp_conv ppx_expect ppx_inline_test ppx_pipebang ppx_sexp_value +opam install -y dune menhir.20260209 ppx_deriving.6.1.1 fmt.0.11.0 yojson.3.0.0 cmdliner.2.1.1\ + ppx_compare ppx_sexp_conv ppx_expect_nobase eval $(opam env) diff --git a/scripts/install_build_deps_windows.sh b/scripts/install_build_deps_windows.sh index 82a907b7e..fc145ed9a 100755 --- a/scripts/install_build_deps_windows.sh +++ b/scripts/install_build_deps_windows.sh @@ -13,10 +13,9 @@ opam repository add windows https://github.com/ocaml-cross/opam-cross-windows.git opam pin add -y ocaml-windows 5.5.0 # Install dependencies -opam install -y base.v0.17.3 base-windows.v0.17.3 menhir.20260209 menhir-windows.20260209 fmt.0.11.0\ - fmt-windows.0.11.0 yojson.3.0.0 yojson-windows.3.0.0 cmdliner.2.1.1 cmdliner-windows.2.1.1\ - ppx_deriving.6.1.1 ppx_deriving-windows.6.1.1 ppx_compare ppx_compare-windows ppx_sexp_conv\ - ppx_sexp_conv-windows ppx_expect ppx_expect-windows ppx_inline_test ppx_inline_test-windows ppx_pipebang\ - ppx_pipebang-windows ppx_sexp_value ppx_sexp_value-windows +opam install -y menhir.20260209 menhir-windows.20260209 fmt.0.11.0 fmt-windows.0.11.0\ + yojson.3.0.0 yojson-windows.3.0.0 cmdliner.2.1.1 cmdliner-windows.2.1.1 ppx_deriving.6.1.1\ + ppx_deriving-windows.6.1.1 ppx_compare ppx_compare-windows ppx_sexp_conv ppx_sexp_conv-windows\ + ppx_expect_nobase ppx_expect_nobase-windows eval $(opam env) diff --git a/scripts/install_ci_deps.sh b/scripts/install_ci_deps.sh index 5d3e506fd..87602bb53 100755 --- a/scripts/install_ci_deps.sh +++ b/scripts/install_ci_deps.sh @@ -6,4 +6,4 @@ set -e # ocamlformat, bisect_ppx, and odoc are needed for CI and useful for developers opam pin -y ocamlformat 0.29.0 --no-action opam pin -y bisect_ppx https://github.com/aantron/bisect_ppx.git#7061d643ff492b0045796357ee6917ded21fb1f0 --no-action -opam install -y ocamlformat bisect_ppx odoc sherlodoc menhirformat +opam install -y ocamlformat bisect_ppx odoc sherlodoc menhirformat ppx_sexp_value diff --git a/src/analysis_and_optimization/dune b/src/analysis_and_optimization/dune index dc235fed2..14136b53b 100644 --- a/src/analysis_and_optimization/dune +++ b/src/analysis_and_optimization/dune @@ -7,4 +7,4 @@ (inline_tests) (modules_without_implementation monotone_framework_sigs) (preprocess - (pps ppx_compare ppx_sexp_conv ppx_expect))) + (pps ppx_compare ppx_sexp_conv ppx_expect_nobase))) diff --git a/src/core/Core.ml b/src/core/Core.ml deleted file mode 100644 index 7cd205e56..000000000 --- a/src/core/Core.ml +++ /dev/null @@ -1,98 +0,0 @@ -(** This module is intended to be a drop-in replacement for our previous use of - [core] from Jane Street. This lightweight module only depends on Base and - Sexplib0. *) - -include Base - -(** We make a few modules look more like their Core equivalents *) - -module Set = struct - include Set - - let of_map_keys m = Set.Poly.of_list (Map.keys m) - - module Poly = struct - include Set.Poly - - let sexp_of_t sexp_of_elt s = - List.sexp_of_t sexp_of_elt (Base.Set.to_list s) - end -end - -module Map = struct - include Map - - module Poly = struct - include Map.Poly - - let sexp_of_t sexp_of_key sexp_of_data m = - List.sexp_of_t - (fun (k, v) -> Sexp.List [sexp_of_key k; sexp_of_data v]) - (Base.Map.to_alist m) - end -end - -module String = struct - include Base.String - - module Table = struct - include Base.Hashtbl.M (Base.String) - - let create () = Base.Hashtbl.create (module Base.String) - let of_alist_exn l = Base.Hashtbl.of_alist_exn (module Base.String) l - end - - module Hash_set = struct - include Base.Hash_set.M (Base.String) - - let create () = Base.Hash_set.create (module Base.String) - end - - module Set = struct - include Base.Set.M (Base.String) - - let of_list l = Base.Set.of_list (module Base.String) l - let empty = Base.Set.empty (module Base.String) - let sexp_of_t t = Base.Set.sexp_of_m__t (module Base.String) t - let union_list l = Base.Set.union_list (module Base.String) l - end - - module Map = struct - include Base.Map.M (Base.String) - - let empty = Base.Map.empty (module Base.String) - let of_alist_exn l = Base.Map.of_alist_exn (module Base.String) l - let of_alist_reduce l = Base.Map.of_alist_reduce (module Base.String) l - end -end - -module Sexp = struct - include Base.Sexp - - let of_string = Sexplib0.Sexp_conv.sexp_of_string -end - -(** And declare some free functions that Core does *) - -let fst3 (v, _, _) = v -let sprintf = Printf.sprintf -let print_s s = Stdlib.print_endline (Sexplib0.Sexp.to_string_hum s) - -(** Finally, we re-export a bunch of stuff from Stdlib that Base shadowed *) - -module Format = Stdlib.Format -module Printexc = Stdlib.Printexc -module Fun = Stdlib.Fun -module Marshal = Stdlib.Marshal -module Printf = Stdlib.Printf -module Scanf = Stdlib.Scanf -module Obj = Stdlib.Obj -module Dynarray = Stdlib.Dynarray - -let ( ^^ ) = Stdlib.( ^^ ) -let ( ** ) = Stdlib.( ** ) -let exit = Stdlib.exit -let print_endline = Stdlib.print_endline -let print_string = Stdlib.print_string - -type ('a, 'b) result = ('a, 'b) Stdlib.result diff --git a/src/core/dune b/src/core/dune deleted file mode 100644 index 546a8d53e..000000000 --- a/src/core/dune +++ /dev/null @@ -1,6 +0,0 @@ -(library - (name core) - (public_name stanc.core) - (libraries base sexplib0) - (instrumentation - (backend bisect_ppx))) diff --git a/src/driver/dune b/src/driver/dune index 18a85e0a8..8dcd24239 100644 --- a/src/driver/dune +++ b/src/driver/dune @@ -9,7 +9,4 @@ stan_math_backend analysis_and_optimization) (instrumentation - (backend bisect_ppx)) - (inline_tests) - (preprocess - (pps ppx_inline_test))) + (backend bisect_ppx))) diff --git a/src/frontend/dune b/src/frontend/dune index 2d97c8456..74f8ae63d 100644 --- a/src/frontend/dune +++ b/src/frontend/dune @@ -10,8 +10,7 @@ (pps ppx_compare ppx_sexp_conv - ppx_expect - ppx_sexp_value + ppx_expect_nobase ppx_deriving.fold ppx_deriving.show ppx_deriving.map))) diff --git a/src/middle/UnsizedType.ml b/src/middle/UnsizedType.ml index 511fdc212..3b459ed95 100644 --- a/src/middle/UnsizedType.ml +++ b/src/middle/UnsizedType.ml @@ -139,19 +139,19 @@ let lub_ad_type xs = let%expect_test "lub_ad_type1" = let ads = [DataOnly; DataOnly; DataOnly; AutoDiffable] in let lub = lub_ad_type ads in - print_s [%sexp (lub : autodifftype option)]; + print_s (sexp_of_option sexp_of_autodifftype lub); [%expect "(AutoDiffable)"] let%expect_test "lub_ad_type2" = let ads = [DataOnly; DataOnly; DataOnly] in let lub = lub_ad_type ads in - print_s [%sexp (lub : autodifftype option)]; + print_s (sexp_of_option sexp_of_autodifftype lub); [%expect "(DataOnly)"] let%expect_test "lub_ad_type3" = let ads = [AutoDiffable; DataOnly; DataOnly; DataOnly] in let lub = lub_ad_type ads in - print_s [%sexp (lub : autodifftype option)]; + print_s (sexp_of_option sexp_of_autodifftype lub); [%expect "(AutoDiffable)"] (** Given two types find the minimal type both can convert to *) @@ -311,6 +311,6 @@ let enumerate_tuple_names_io name (ut : t) = let%expect_test "tuple names" = let t = UArray (UTuple [UInt; UArray (UTuple [UReal; UComplex]); UVector]) in let res = enumerate_tuple_names_io "foo" t in - [%sexp (res : string list)] |> print_s; + print_s (sexp_of_list sexp_of_string res); [%expect {| (foo.1 foo.2.1 foo.2.2 foo.3) |}] diff --git a/src/middle/dune b/src/middle/dune index 6ffa9ac01..827ed8476 100644 --- a/src/middle/dune +++ b/src/middle/dune @@ -9,8 +9,7 @@ (pps ppx_compare ppx_sexp_conv - ppx_expect - ppx_sexp_value + ppx_expect_nobase ppx_deriving.map ppx_deriving.fold ppx_deriving.create diff --git a/src/stan_math_backend/Cpp.ml b/src/stan_math_backend/Cpp.ml index 6d5af9873..f0ad078f1 100644 --- a/src/stan_math_backend/Cpp.ml +++ b/src/stan_math_backend/Cpp.ml @@ -794,7 +794,7 @@ module Tests = struct let vector = (row_vector Double).:{Literal "3"} in let values = [Literal "1"; Var "a"; Literal "3"] in let e = (vector << values).@!("finished") in - print_s [%sexp (e : expr)]; + print_s (sexp_of_expr e); print_endline ""; Printing.pp_expr Fmt.stdout e; [%expect diff --git a/src/stan_math_backend/Transform_Mir.ml b/src/stan_math_backend/Transform_Mir.ml index 75c5b0b06..f89c56901 100644 --- a/src/stan_math_backend/Transform_Mir.ml +++ b/src/stan_math_backend/Transform_Mir.ml @@ -756,7 +756,7 @@ let%expect_test "Flatten slists" = |> s ] |> flatten_slists_list) in let open Sexp_conv in - print_s [%sexp (stmt : (unit, unit) Stmt.t list)]; + print_s (sexp_of_list (Stmt.sexp_of_t sexp_of_unit sexp_of_unit) stmt); [%expect {| (((pattern @@ -1005,7 +1005,7 @@ let%expect_test "collect vars expr" = let%expect_test "insert before" = let l = [1; 2; 3; 4; 5; 6] |> insert_before (( = ) 6) [999] in let open Sexp_conv in - [%sexp (l : int list)] |> print_s; + print_s (sexp_of_list sexp_of_int l); [%expect {| (1 2 3 4 5 999 6) |}] let map_prog_stmt_lists f (p : ('a, 'b, 'c) Program.t) = diff --git a/src/stan_math_backend/dune b/src/stan_math_backend/dune index 7b63437c6..986edd53a 100644 --- a/src/stan_math_backend/dune +++ b/src/stan_math_backend/dune @@ -14,9 +14,4 @@ numbering) (inline_tests) (preprocess - (pps - ppx_sexp_conv - ppx_expect - ppx_sexp_value - ppx_deriving.make - ppx_deriving.show))) + (pps ppx_sexp_conv ppx_expect_nobase ppx_deriving.make ppx_deriving.show))) diff --git a/src/stan_math_signatures/dune b/src/stan_math_signatures/dune index 5907d2451..10b12808f 100644 --- a/src/stan_math_signatures/dune +++ b/src/stan_math_signatures/dune @@ -5,10 +5,7 @@ (instrumentation (backend bisect_ppx)) (modules :standard \ generate) - (private_modules generated_signatures) - (inline_tests) - (preprocess - (pps ppx_inline_test))) + (private_modules generated_signatures)) (executable (name generate) diff --git a/stanc.opam b/stanc.opam index 50174fbf4..6be66136c 100644 --- a/stanc.opam +++ b/stanc.opam @@ -8,7 +8,6 @@ bug-reports: "https://github.com/stan-dev/stanc3/issues" depends: [ "dune" {>= "3.12"} "ocaml" {= "5.5.0"} - "base" {= "v0.17.3"} "menhir" {= "20260209"} "fmt" {= "0.11.0"} "yojson" {= "3.0.0"} @@ -16,10 +15,8 @@ depends: [ "ppx_deriving" {= "6.1.1"} "ppx_compare" "ppx_sexp_conv" - "ppx_expect" - "ppx_inline_test" - "ppx_pipebang" - "ppx_sexp_value" + "ppx_expect_nobase" + "ppx_sexp_value" {with-test} "ocamlformat" {with-dev-setup & = "0.29.0"} "menhirformat" {with-dev-setup} "bisect_ppx" {with-dev-setup} diff --git a/test/integration/dune b/test/integration/dune index 1e428d779..9622ecdba 100644 --- a/test/integration/dune +++ b/test/integration/dune @@ -1,6 +1,6 @@ (executable (name run_bin_on_args) - (libraries core unix)) + (libraries std unix)) (cram (applies_to :whole_subtree) diff --git a/test/integration/run_bin_on_args.ml b/test/integration/run_bin_on_args.ml index e86711cbd..5c066874d 100644 --- a/test/integration/run_bin_on_args.ml +++ b/test/integration/run_bin_on_args.ml @@ -1,37 +1,32 @@ -module Caml_unix = Unix -open Core +open Std let string_of_status = function - | Caml_unix.WEXITED i -> sprintf "[exit %n]" i - | WSIGNALED i -> sprintf "[signal %n]" i - | WSTOPPED i -> sprintf "[stopped %n]" i + | Unix.WEXITED i -> Printf.sprintf "[exit %n]" i + | WSIGNALED i -> Printf.sprintf "[signal %n]" i + | WSTOPPED i -> Printf.sprintf "[stopped %n]" i let run_capturing_output cmd = - let noflags = Array.create ~len:0 "" in - let stdout, stdin, stderr = Caml_unix.open_process_full cmd noflags in + let noflags = Array.make 0 "" in + let stdout, stdin, stderr = Unix.open_process_full cmd noflags in let chns = [stdout; stderr] in let out = List.map ~f:In_channel.input_lines chns |> List.concat in let status = - string_of_status (Caml_unix.close_process_full (stdout, stdin, stderr)) - in + string_of_status (Unix.close_process_full (stdout, stdin, stderr)) in let out = out @ [status] in String.concat ~sep:"\n" out let () = - let args = Sys.get_argv () in + let args = Sys.argv in let binary = args.(1) in let dirs = Array.(sub args ~pos:2 ~len:(length args - 2)) in - Array.stable_sort ~compare:String.compare dirs; + Array.stable_sort ~cmp:String.compare dirs; Array.iter dirs ~f:(fun arg -> let arg = String.chop_prefix_if_exists arg ~prefix:"./" in let cmd = binary ^ " " ^ arg in let short_cmd = (* when displaying the command in the output file, we clean up the binary name *) - let binary = - String.split_on_chars binary ~on:['/'] |> List.rev |> List.hd_exn - in - let binary = - String.substr_replace_first binary ~pattern:".exe" ~with_:"" in + let binary = String.split_last ~sep:"/" binary |> Option.get |> snd in + let binary = String.replace_first binary ~sub:".exe" ~by:"" in binary ^ " " ^ arg in Printf.printf " $ %s\n%s\n" short_cmd (run_capturing_output cmd)) diff --git a/test/stancjs/dune b/test/stancjs/dune index c1ee584ed..06bbc7e6a 100644 --- a/test/stancjs/dune +++ b/test/stancjs/dune @@ -1,6 +1,6 @@ (executable (name run_js_on_args) - (libraries core unix) + (libraries std unix) (modes exe)) (rule diff --git a/test/stancjs/run_js_on_args.ml b/test/stancjs/run_js_on_args.ml index 17a171839..30dffb821 100644 --- a/test/stancjs/run_js_on_args.ml +++ b/test/stancjs/run_js_on_args.ml @@ -1,18 +1,18 @@ -module Caml_unix = Unix -open Core +open Std let run_capturing_output cmd = - let env = [| "PATH=" ^ (Sys.getenv "PATH" |> Option.value ~default:"") |] in - let stdout, stdin, stderr = Caml_unix.open_process_full cmd env in + let env = + [| "PATH=" ^ (Sys.getenv_opt "PATH" |> Option.value ~default:"") |] in + let stdout, stdin, stderr = Unix.open_process_full cmd env in let chns = [stdout; stderr] in let out = List.map ~f:In_channel.input_lines chns in - ignore (Caml_unix.close_process_full (stdout, stdin, stderr)); + ignore (Unix.close_process_full (stdout, stdin, stderr)); String.concat ~sep:"\n" (List.concat out) let () = - let args = Sys.get_argv () in + let args = Sys.argv in let files = Array.(sub args ~pos:1 ~len:(length args - 1)) in - Array.stable_sort ~compare:String.compare files; + Array.stable_sort ~cmp:String.compare files; Array.iter files ~f:(fun arg -> let arg = String.chop_prefix_if_exists arg ~prefix:"./" in let cmd = "node " ^ arg in diff --git a/test/unit/dune b/test/unit/dune index 9ad1a5948..6801cfd28 100644 --- a/test/unit/dune +++ b/test/unit/dune @@ -9,4 +9,4 @@ analysis_and_optimization) (inline_tests) (preprocess - (pps ppx_expect ppx_inline_test ppx_sexp_value))) + (pps ppx_expect_nobase ppx_sexp_value)))