This file provides guidelines for AI agents generating or modifying code in this library.
skip-lite/
├── lib/marshal_cache/ # Marshal_cache module
│ ├── marshal_cache_stubs.cpp
│ ├── marshal_cache.ml
│ └── marshal_cache.mli
└── test/ # Test suite
This library contains C++ code that interfaces with the OCaml runtime. The OCaml garbage collector (GC) can move values in memory at any allocation point. Incorrect handling causes memory corruption and segfaults.
-
Do not use
String_val(v)across allocations// BAD - s becomes dangling after allocation const char* s = String_val(str_val); caml_copy_string(other); // GC may move str_val use(s); // CRASH
-
Do not nest allocations inside
Store_field// BAD - tuple address computed before caml_copy_string runs Store_field(tuple, 0, caml_copy_string(s));
-
Do not raise custom exceptions directly from C
// BAD - complex allocation sequence + longjmp = corruption value args = caml_alloc_tuple(2); Store_field(args, 0, caml_copy_string(path)); caml_raise_with_arg(*exn, args);
-
Do not assume values survive across
caml_callback*// BAD - callback can trigger GC value result = caml_callback(closure, arg); use(String_val(some_other_value)); // may be stale
-
Copy OCaml strings to C++ strings immediately
std::string s(String_val(str_val)); // Safe copy caml_alloc(...); use(s.c_str());
-
Allocate values before storing
value str = caml_copy_string(s); Store_field(tuple, 0, str);
-
Raise simple exceptions, convert in OCaml
// C++: raise Failure with structured message std::string msg = path + ": " + error; caml_failwith(msg.c_str());
(* OCaml: catch and convert *) try ... with Failure msg -> raise (Cache_error (parse msg))
-
Use
CAMLparam/CAMLlocalfor values that must survive allocationsCAMLparam1(input); CAMLlocal2(result, temp); // Now result and temp are updated if GC moves them
When adding new modules to skip-lite:
- Create a new directory under
lib/(e.g.,lib/new_module/) - Add a
dunefile with appropriate(public_name skip-lite.new_module) - Follow the same FFI safety patterns as
Marshal_cache - Add tests in
test/ - Update README.md with module documentation
Run tests with:
dune runtestAll tests must pass before committing changes.