···
1
+
# OxCaml Language Model Context
3
+
OxCaml is Jane Street's enhanced version of OCaml that adds numerous performance and safety features while maintaining OCaml compatibility. This document provides comprehensive guidance for code generation and porting OCaml code to OxCaml.
5
+
## Core OxCaml Philosophy
7
+
OxCaml extends OCaml with:
8
+
- **Zero-allocation programming**: Stack allocation, unboxed types, comprehensive optimization
9
+
- **Parallelism with safety**: Data-race-free parallel programming through modes
10
+
- **Fine-grained control**: Modes, kinds, uniqueness for memory and performance optimization
11
+
- **Enhanced expressiveness**: Comprehensions, SIMD, templates for better abstractions
13
+
## Quick Reference: Key Extensions
15
+
### Stack Allocation (`local` mode)
16
+
- Use `@ local` for values that don't escape scope
17
+
- Enables stack allocation, reducing GC pressure
18
+
- Use `exclave_` to return local values from functions
19
+
- `stack_` forces stack allocation (fails if impossible)
21
+
### Unboxed Types (layouts)
22
+
- `float#`, `int32#`, `int64#` for unboxed numeric types
23
+
- Literals: `#3.14` (float#), `#123l` (int32#), `#456L` (int64#)
24
+
- Unboxed records: `#{ field = value }`
25
+
- Unboxed tuples: `#(a, b, c)`
28
+
- Use `Parallel.fork_join2` for parallel computation
29
+
- Mark data `@ portable` for cross-domain sharing
30
+
- Use `@ contended` for thread-safe mutable data
31
+
- Capsules for complex shared mutable state
34
+
- List: `[ expr for pat in seq when cond ]`
35
+
- Array: `[| expr for pat in seq when cond |]`
36
+
- Range iteration: `for i = 1 to n`
37
+
- Parallel iteration: `for x in xs and y in ys`
40
+
- Vector types: `float32x4#`, `int32x4#`, etc.
41
+
- Load from memory: `Float32x4.String.get`
42
+
- Operations: `Float32x4.add`, `Float32x4.mul`
43
+
- Use `[@unboxed]` for C interop
45
+
## Mode System Reference
47
+
### Locality Axis (scope)
48
+
- `global` (default): May escape scope
49
+
- `local`: Cannot escape scope, enables stack allocation
51
+
### Contention Axis (thread safety)
52
+
- `uncontended` (default): Single thread access
53
+
- `shared`: Multiple threads read-only
54
+
- `contended`: Multiple threads with writes
56
+
### Portability Axis (thread movement)
57
+
- `nonportable` (default): Cannot move between threads
58
+
- `portable`: May move across thread boundaries
60
+
### Uniqueness Axis (aliasing)
61
+
- `aliased` (default): Multiple references
62
+
- `unique`: Single reference only
65
+
- Linearity: `many` (default) vs `once` (single use)
66
+
- Yielding: `unyielding` (default) vs `yielding` (effects)
67
+
- Visibility: `read_write` (default) vs `read` vs `immutable`
68
+
- Statefulness: `stateful` (default) vs `observing` vs `stateless`
70
+
## Kind System Reference
73
+
- `value`: Standard OCaml values
74
+
- `immediate`: Int-like types
75
+
- `float64`, `float32`: Unboxed floats
76
+
- `bits64`, `bits32`: Unboxed integers
77
+
- `word`: Machine word
78
+
- `vec128`, `vec256`: SIMD vectors
79
+
- `any`: Maximum layout
81
+
### Kind Abbreviations
82
+
- `immediate`: Values like `int`, `bool`
83
+
- `immutable_data`: Plain immutable data
84
+
- `mutable_data`: Plain mutable data
85
+
- `any_non_null`: Any layout excluding NULL
87
+
## Migration Guidelines: OCaml to OxCaml
89
+
### 1. Performance Optimization
91
+
**Stack Allocation:**
95
+
let temp = expensive_computation data in
100
+
let temp @ local = expensive_computation data in
101
+
extract_result temp
104
+
**Unboxed Numeric Code:**
107
+
let distance x1 y1 x2 y2 =
108
+
sqrt ((x2 -. x1) ** 2.0 +. (y2 -. y1) ** 2.0)
111
+
let distance x1 y1 x2 y2 =
112
+
Float_u.sqrt (Float_u.add
113
+
(Float_u.pow (Float_u.sub x2 x1) #2.0)
114
+
(Float_u.pow (Float_u.sub y2 y1) #2.0))
117
+
**Array Processing with SIMD:**
120
+
let add_arrays a b = Array.map2 (+.) a b
123
+
module F32x4 = Ocaml_simd_sse.Float32x4
124
+
let add_vectors v1 v2 = F32x4.add v1 v2
127
+
### 2. Parallel Programming
129
+
**Basic Parallelism:**
132
+
let map_reduce f reduce_f init list =
133
+
List.fold_left (fun acc x -> reduce_f acc (f x)) init list
136
+
let parallel_map_reduce par f reduce_f init list =
137
+
let process chunk =
138
+
List.fold_left (fun acc x -> reduce_f acc (f x)) init chunk
143
+
let mid = List.length list / 2 in
144
+
let left, right = List.split_at mid list in
145
+
let left_result, right_result =
146
+
Parallel.fork_join2 par
147
+
(fun _ -> process left)
148
+
(fun _ -> process right)
150
+
reduce_f left_result right_result
153
+
**Shared Mutable State:**
156
+
let shared_counter = ref 0
157
+
let increment () = incr shared_counter
160
+
let shared_counter = Atomic.make 0
161
+
let increment () = Atomic.incr shared_counter
164
+
### 3. Loop Transformation
166
+
**Comprehensions:**
169
+
let result = ref [] in
172
+
if condition i j then
173
+
result := (f i j) :: !result
179
+
[ f i j for i = 1 to n for j = 1 to m when condition i j ]
185
+
list |> List.filter predicate |> List.map transform
188
+
[ transform x for x in list when predicate x ]
191
+
### 4. Memory Management
193
+
**Unique Resources:**
195
+
(* Define safe resource management *)
196
+
type buffer : value
198
+
val create : size:int -> buffer @ unique
199
+
val free : buffer @ unique -> unit
200
+
val write : buffer @ unique -> string -> buffer @ unique
202
+
(* Use with functional threading *)
203
+
let process_data size data =
206
+
|> write " processed"
207
+
|> fun buf -> let result = extract buf in free buf; result
210
+
**Immutable Arrays:**
213
+
let readonly_data = [| 1; 2; 3; 4 |]
216
+
let readonly_data = [: 1; 2; 3; 4 :]
221
+
### Mode Annotations
223
+
let func (param @ local) : result @ local = ...
224
+
let value : type @ modes = ...
225
+
let (pattern @ modes) = expression
226
+
function_name @ modes arg1 arg2
229
+
### Kind Annotations
231
+
type ('a : float64) vector
232
+
val process : ('a : immediate) -> unit
233
+
let func (type (a : value) (b : bits32)) (x : a) (y : b) = ...
236
+
### Templates (for mode/kind polymorphism)
238
+
let%template[@mode m = (global, local)] identity
239
+
: 'a. 'a @ m -> 'a @ m = fun x -> x
241
+
module%template[@kind k = (value, float64)] Math = struct
242
+
let add x y = (Float.add [@kind k]) x y
246
+
### Unboxed Type Usage
249
+
let pi = #3.14159 (* float# *)
250
+
let count = #42l (* int32# *)
253
+
type point = #{ x : float#; y : float# }
254
+
let origin = #{ x = #0.0; y = #0.0 }
257
+
let coords = #(#1.0, #2.0, #3.0)
260
+
## Error Handling Patterns
262
+
### Zero Allocation Checking
264
+
let[@zero_alloc] fast_math x y = x + y * 2
265
+
let[@zero_alloc assume] external_func x = C.some_func x
268
+
### Custom Error Messages
270
+
let process (x : (_ : immediate)[@error_message "requires immediate type"]) = x
273
+
## Performance Considerations
275
+
1. **Stack vs Heap**: Use `@ local` for temporary values
276
+
2. **Unboxed vs Boxed**: Use unboxed types (`#` suffix) for numeric code
277
+
3. **Parallel vs Sequential**: Use `Parallel.fork_join2` for independent tasks
278
+
4. **SIMD**: Use vector types for data-parallel numeric operations
279
+
5. **Zero Allocation**: Mark performance-critical code with `[@zero_alloc]`
280
+
6. **Immutable Arrays**: Use `[: ... :]` for read-only data
284
+
### Stack Allocation
285
+
- Don't use `@ local` values in tail calls (use `[@nontail]`)
286
+
- Avoid partial application with local parameters
287
+
- Thread unique values through function calls, don't store in loops
290
+
- Mark shared data as `@ portable contended`
291
+
- Use capsules for complex mutable state
292
+
- Ensure functions are `@ portable` for parallel use
295
+
- Can't be used in tuples or variant constructors (current limitation)
296
+
- Limited container type support
297
+
- No polymorphic operations (comparison, marshaling)
300
+
- Use locally abstract types for multiple kinds
301
+
- Prefer mono-attributes for instantiation
302
+
- Test all generated template instances
307
+
- `Parallel`: Parallel computation primitives
308
+
- `Atomic`: Thread-safe atomic operations
309
+
- `Float_u`, `Int32_u`, etc.: Unboxed numeric operations
310
+
- `ocaml_simd`: SIMD vector operations
311
+
- `Capsule`: Safe sharing of mutable state
316
+
module F32x4 = Ocaml_simd_sse.Float32x4
319
+
This reference enables effective OxCaml code generation that leverages the language's advanced features while maintaining safety and performance.