this repo has no description

various

+387 -1
+205
doc/demo6_porting_workshop.mld
··· 1 + {0 OxCaml Porting Workshop: From OCaml Library Code to OxCaml-Compatible Code} 2 + 3 + @x-ocaml.universe ./universe-oxcaml 4 + @x-ocaml.worker ./universe-oxcaml/worker.js 5 + 6 + This page is a hands-on tutorial for common migration patterns seen in real 7 + ports from the OxCaml opam overlay (e.g. [re], [uutf], [zarith], [dune], 8 + [ppxlib], [notty-community]). 9 + 10 + {1 How to use this page} 11 + 12 + - Read each pattern. 13 + - Run the example cells. 14 + - Edit the {e exercise} cells and re-run. 15 + - Compare with the {e test} cells. 16 + 17 + {1 Pattern 1: Eta-expansion of partial applications} 18 + 19 + A frequent OxCaml fix is turning a stored partial application into an explicit 20 + function value. 21 + 22 + {2 Before (classic style)} 23 + 24 + {@ocaml interactive run-on=click[ 25 + let add x y = x + y 26 + let add10 = add 10 27 + let () = Printf.printf "add10 7 = %d\n" (add10 7) 28 + ]} 29 + 30 + {2 After (eta-expanded style)} 31 + 32 + {@ocaml interactive[ 33 + let add x y = x + y 34 + let add10 y = add 10 y 35 + let () = Printf.printf "add10 7 = %d\n" (add10 7) 36 + ]} 37 + 38 + {2 Exercise} 39 + 40 + Rewrite [mk_printer] to be eta-expanded. 41 + 42 + {@ocaml exercise id=eta1[ 43 + let with_prefix p s = p ^ s 44 + let mk_printer p = with_prefix p 45 + (* TODO: eta-expand mk_printer *) 46 + ]} 47 + 48 + {@ocaml test for=eta1[ 49 + let f = mk_printer "[INFO] " in 50 + assert (f "ready" = "[INFO] ready") 51 + ]} 52 + 53 + {1 Pattern 2: Portable API boundaries} 54 + 55 + In real ports, many interfaces add [@@ portable] and related mode-safe 56 + annotations on externals and public signatures. 57 + 58 + This toy module shows the shape. 59 + 60 + {@ocaml interactive[ 61 + module Stable_string : sig 62 + type t = string 63 + val concat : t -> t -> t 64 + end = struct 65 + type t = string 66 + let concat a b = a ^ b 67 + end 68 + 69 + let () = print_endline (Stable_string.concat "mode-" "safe") 70 + ]} 71 + 72 + In real libraries this often appears on externals and mli declarations 73 + (e.g. [re], [spawn], [uutf]). 74 + 75 + {2 Exercise} 76 + 77 + Separate API boundary from implementation for later portability annotation work. 78 + 79 + {@ocaml exercise id=portable_api[ 80 + module type S = sig 81 + type t 82 + val make : string -> t 83 + val show : t -> string 84 + end 85 + 86 + module M : S = struct 87 + type t = string 88 + let make s = s 89 + let show t = t 90 + end 91 + ]} 92 + 93 + {@ocaml test for=portable_api[ 94 + let v = M.make "ok" in 95 + assert (M.show v = "ok") 96 + ]} 97 + 98 + {1 Pattern 3: [local_] parameters and non-escaping use} 99 + 100 + In OxCaml ports, [local_] is used where values must not escape their region. 101 + 102 + {@ocaml interactive[ 103 + let sum_pair (p @ local) = 104 + let a, b = p in 105 + a + b 106 + 107 + let () = 108 + let p = (20, 22) in 109 + Printf.printf "sum_pair = %d\n" (sum_pair p) 110 + ]} 111 + 112 + Real examples: [uutf] callback folder types, [zarith] conversion APIs. 113 + 114 + {2 Exercise} 115 + 116 + Implement a local consumer that does not let its argument escape. 117 + 118 + {@ocaml exercise id=local1[ 119 + let use_point (p @ local) = 120 + let x, y = p in 121 + (* TODO: return Manhattan norm *) 122 + x + y 123 + ]} 124 + 125 + {@ocaml test for=local1[ 126 + assert (use_point (3, 4) = 7) 127 + ]} 128 + 129 + {1 Pattern 4: Heap-mutable vs stack-local style} 130 + 131 + A common migration theme is reducing shared mutable state and making data flow 132 + more explicit. 133 + 134 + {@ocaml interactive[ 135 + let sum_ref n = 136 + let total = ref 0 in 137 + for i = 1 to n do 138 + total := !total + i 139 + done; 140 + !total 141 + 142 + let sum_mutable n = 143 + let mutable total = 0 in 144 + for i = 1 to n do 145 + total <- total + i 146 + done; 147 + total 148 + 149 + let () = 150 + Printf.printf "sum_ref 10 = %d\n" (sum_ref 10); 151 + Printf.printf "sum_mutable 10 = %d\n" (sum_mutable 10) 152 + ]} 153 + 154 + Real-world analogues include [re] and [notty-community], where updates can be 155 + much deeper (atomics, immutable arrays, lock-free structures). 156 + 157 + {1 Pattern 5: Runtime-aware compatibility shims} 158 + 159 + Some ports add runtime4/runtime5 compatibility shims. 160 + 161 + Toy shape: 162 + 163 + {@ocaml interactive[ 164 + module Runtime = struct 165 + let is_multicore = false 166 + let recommended_domains () = if is_multicore then 8 else 1 167 + end 168 + 169 + let () = 170 + Printf.printf "recommended domains: %d\n" (Runtime.recommended_domains ()) 171 + ]} 172 + 173 + Real examples: [backoff], [re]. 174 + 175 + {1 Pattern 6: PPX / AST-heavy libraries need dedicated migration} 176 + 177 + If your package pattern-matches deeply on Parsetree nodes, expect a larger 178 + migration (as seen in [ppxlib], [sedlex], [gen_js_api], [lwt_ppx]). 179 + 180 + This workshop does not emulate full AST migration, but the practical takeaway 181 + is: 182 + 183 + - budget extra time, 184 + - upgrade wildcard matches and constructors carefully, 185 + - isolate AST adapters in one place. 186 + 187 + {1 Migration checklist (copy/paste)} 188 + 189 + {@ocaml interactive run-on=click[ 190 + let checklist = [ 191 + "1. Build under OxCaml and collect first errors"; 192 + "2. Apply eta-expansion fixes"; 193 + "3. Add/adjust portable API boundaries"; 194 + "4. Introduce local_/global_ where lifetimes matter"; 195 + "5. Audit mutable shared state"; 196 + "6. Add runtime compatibility shims if needed"; 197 + "7. For PPX/AST code: do focused migration pass"; 198 + ] in 199 + List.iter print_endline checklist 200 + ]} 201 + 202 + {1 Next step} 203 + 204 + If you want, create a package-specific workshop page by copying this file and 205 + replacing toy examples with snippets from your real library diff.
+162
doc/demo7_oxcaml_porting_real.mld
··· 1 + {0 OxCaml Porting: Real Snippets from Real Libraries} 2 + 3 + @x-ocaml.universe ./universe-oxcaml 4 + @x-ocaml.worker ./universe-oxcaml/worker.js 5 + 6 + This workshop uses real migration snippets taken from the OxCaml opam overlay. 7 + Each section links to the exact patch file. 8 + 9 + {1 Notes} 10 + 11 + - Cells are runnable where practical. 12 + - Some snippets are simplified for teaching. 13 + - For library-dependent examples, use [#require "..."] first. 14 + 15 + {1 1) Eta-expansion (Dune ecosystem)} 16 + 17 + Real patch: 18 + {{:https://github.com/oxcaml/opam-repository/blob/main/packages/dune/dune.3.21.0%2Box/files/oxcaml-dune.patch}dune.3.21.0+ox / oxcaml-dune.patch} 19 + 20 + Core change pattern from the patch: 21 + 22 + {[ 23 + - let unlink_exn = if Stdlib.Sys.win32 then win32_unlink else Unix.unlink 24 + + let unlink_exn = if Stdlib.Sys.win32 then win32_unlink else fun s -> Unix.unlink s 25 + 26 + - let create_process = ... Unix.create_process prog args 27 + + let create_process stdin stdout stderr = ... Unix.create_process prog args stdin stdout stderr 28 + ]} 29 + 30 + Runnable miniature: 31 + 32 + {@ocaml[ 33 + let unlink_like win32_unlink is_win = 34 + if is_win then win32_unlink else fun s -> "unlink " ^ s 35 + 36 + let () = print_endline (unlink_like (fun s -> "win-unlink " ^ s) false "tmp.txt") 37 + ]} 38 + 39 + {1 2) [local_] callback shape (uutf)} 40 + 41 + Real patch: 42 + {{:https://github.com/oxcaml/opam-repository/blob/main/packages/uutf/uutf.1.0.3%2Box/files/uutf-locals.patch}uutf.1.0.3+ox / uutf-locals.patch} 43 + 44 + Core change pattern from the patch: 45 + 46 + {[ 47 + - type 'a folder = 'a -> int -> [ `Uchar of Uchar.t | `Malformed of string ] -> 'a 48 + + type 'a folder = 'a -> local_ (int -> [ `Uchar of Uchar.t | `Malformed of string ] -> 'a) 49 + 50 + - val fold_utf_8 : ... -> 'a folder -> 'a -> string -> 'a 51 + + val fold_utf_8 : ... -> local_ 'a folder -> 'a -> string -> 'a 52 + ]} 53 + 54 + Pedagogical simplified version: 55 + 56 + {@ocaml[ 57 + type 'a folder = 'a -> local_ (int -> char -> 'a) 58 + 59 + let fold_chars (f : local_ 'a folder) acc s = 60 + let rec go i a = 61 + if i = String.length s then a 62 + else go (i + 1) (f a i s.[i]) 63 + in 64 + go 0 acc 65 + 66 + let () = 67 + let count acc _i _c = acc + 1 in 68 + Printf.printf "len=%d\n" (fold_chars count 0 "oxcaml") 69 + ]} 70 + 71 + {1 3) [global_] fields + local comparators (zarith)} 72 + 73 + Real patch: 74 + {{:https://github.com/oxcaml/opam-repository/blob/main/packages/zarith/zarith.1.12%2Box/files/zarith-local.patch}zarith.1.12+ox / zarith-local.patch} 75 + 76 + Core change pattern from the patch: 77 + 78 + {[ 79 + - type t = { num: Z.t; den: Z.t } 80 + + type t = { global_ num: Z.t; global_ den: Z.t } 81 + 82 + - let compare x y = ... 83 + + let compare__local (local_ x) (local_ y) = ... 84 + + let compare x y = compare__local x y 85 + ]} 86 + 87 + Teaching-scale analogue: 88 + 89 + {@ocaml[ 90 + type frac = { global_ num : int; global_ den : int } 91 + 92 + let compare__local (local_ a) (local_ b) = compare (a.num * b.den) (b.num * a.den) 93 + let compare_frac a b = compare__local a b 94 + 95 + let () = 96 + let a = { num = 1; den = 2 } in 97 + let b = { num = 2; den = 3 } in 98 + Printf.printf "compare_frac=%d\n" (compare_frac a b) 99 + ]} 100 + 101 + {1 4) Portability + runtime compatibility shims (re/backoff family)} 102 + 103 + Representative sources: 104 + 105 + - {{:https://github.com/oxcaml/opam-repository/blob/main/packages/re/re.1.14.0%2Box/files/re%2Blib%2Bimport.ml.patch}re.1.14.0+ox / import shim} 106 + - {{:https://github.com/oxcaml/opam-repository/blob/main/packages/backoff/backoff.0.1.1%2Box/files/backoff.patch}backoff.0.1.1+ox / runtime shim} 107 + 108 + Typical shape: runtime probing + portability-safe fallback. 109 + 110 + {@ocaml[ 111 + module Runtime = struct 112 + let runtime5 = false 113 + let recommended_domain_count () = if runtime5 then 8 else 1 114 + end 115 + 116 + let () = Printf.printf "domains=%d\n" (Runtime.recommended_domain_count ()) 117 + ]} 118 + 119 + {1 5) Optional [#require] cells for real libraries} 120 + 121 + Use these when your universe includes the package. 122 + 123 + {@ocaml run-on=click[ 124 + #require "re";; 125 + let r = Re.(compile (seq [str "ox"; str "caml"])) 126 + let () = Printf.printf "re ok: %b\n" (Re.execp r "oxcaml") 127 + ]} 128 + 129 + {@ocaml run-on=click[ 130 + #require "uutf";; 131 + let n = Uutf.String.fold_utf_8 (fun acc _ _ -> acc + 1) 0 "hello" 132 + let () = Printf.printf "uutf count=%d\n" n 133 + ]} 134 + 135 + {1 6) Exercise: classify a snippet} 136 + 137 + Given a change, classify it as one of: 138 + 139 + - eta-expansion 140 + - portability annotation 141 + - local/global lifetime annotation 142 + - runtime shim 143 + 144 + {@ocaml exercise id=classify1[ 145 + let classify_change s = 146 + if String.contains s '@' then "portability annotation" 147 + else if String.contains s '_' then "eta-expansion" 148 + else "runtime shim" 149 + ]} 150 + 151 + {@ocaml test for=classify1[ 152 + assert (classify_change "let f x = g a x" = "eta-expansion") 153 + ]} 154 + 155 + {1 7) Where to browse more real patches} 156 + 157 + - OxCaml opam overlay packages directory: 158 + {{:https://github.com/oxcaml/opam-repository/tree/main/packages}github.com/oxcaml/opam-repository/packages} 159 + - Deep taxonomy notes generated locally: 160 + [/cache/jons-agent/oxcaml-research/oxcaml-opam/TAXONOMY.md] 161 + - Deep fork+portability audit: 162 + [/cache/jons-agent/oxcaml-research/oxcaml-opam/DEEP-DIVE.md]
+18
doc/dune
··· 1 1 (documentation 2 2 (package odoc-interactive-extension)) 3 + 4 + ; Build a jtw universe with yojson for the demo pages. 5 + ; The universe directory contains worker.js, findlib_index.json, 6 + ; and lib/ with CMIs, META files, and .cma.js archives. 7 + ; 8 + ; Usage: 9 + ; dune build odoc-interactive-extension/doc/universe 10 + ; 11 + ; After building, deploy to the doc HTML output (see below). 12 + (rule 13 + (targets 14 + (dir universe)) 15 + (action 16 + (run jtw opam -o universe yojson))) 17 + 18 + ; After building, deploy to the doc HTML output: 19 + ; cp -r _build/default/odoc-interactive-extension/doc/universe \ 20 + ; _build/default/_doc/_html/odoc-interactive-extension/
+2 -1
dune-project
··· 1 - (lang dune 3.18) 1 + (lang dune 3.21) 2 2 (using dune_site 0.1) 3 + (using directory-targets 0.1) 3 4 (name odoc-interactive-extension) 4 5 (generate_opam_files true) 5 6