Phase B Performance Optimizations:
Drop Specialization:
- Add specialized decref functions: lux_decref_list, lux_decref_closure,
lux_decref_string, lux_decref_boxed
- Inline drop logic eliminates polymorphic dispatch through lux_drop
- Forward type declarations (typedef struct X_s X) for proper C ordering
Ownership Transfer (Last-Use Optimization):
- Track variable types in var_types HashMap for type inference
- When assigning let b = a where a is RC-tracked:
- Unregister source variable from RC cleanup
- Register destination variable instead
- Prevents double-free and eliminates unnecessary incref/decref pairs
Also:
- Fix type inference for variable references in infer_expr_type
- Add is_rc_tracked() and unregister_rc_var() helper functions
- Update REFERENCE_COUNTING.md with Phase B progress
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add escape_c_keyword() to mangle C reserved words (double, int, etc.)
- Implement toString() mapping to lux_int_to_string()
- Add string concatenation detection for BinaryOp::Add using lux_string_concat()
- Add is_string_expr() helper for string expression detection
- Update infer_expr_type() for toString, string concat, and if expressions
- Implement complex conditionals RC handling: use if-statements instead of
ternaries when branches create RC values to avoid allocating unused branches
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add pop_rc_scope_except() to skip decref'ing returned variables
- Block expressions now properly preserve returned RC variables
- Function returns skip cleanup for variables being returned
- Track function return types for call expression type inference
- Function calls returning RC types now register for cleanup
- Fix main() entry point to call main_lux() when present
Test result: [RC] No leaks: 17 allocs, 17 frees
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
ADT values with pointer fields (like recursive Tree types) now properly
manage memory:
- Assign unique type tags (starting at 100) to each ADT type
- Track which ADTs have pointer fields that need cleanup
- Generate lux_drop_adt() function with per-ADT drop logic
- Allocate ADT pointer fields with lux_rc_alloc instead of malloc
- Track ADT variables with pointer fields in scope
- Emit field cleanup code at scope exit (switch on tag, decref fields)
Test results:
- ADT test: [RC] No leaks: 6 allocs, 6 frees
- List test: [RC] No leaks: 31 allocs, 31 frees
- Closure test: [RC] No leaks: 8 allocs, 8 frees
- All 263 tests pass
Remaining: early returns, complex conditionals.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Closures and their environments are now properly reference-counted:
- Allocate closures with lux_rc_alloc(sizeof(LuxClosure), LUX_TAG_CLOSURE)
- Allocate environments with lux_rc_alloc(sizeof(LuxEnv_N), LUX_TAG_ENV)
- Enable Lambda in expr_creates_rc_value() to track closure variables
- Add lux_decref() after List higher-order operations (map, filter, fold,
find, any, all) to clean up inline lambdas
Test results:
- Closure test: [RC] No leaks: 8 allocs, 8 frees
- List RC test: [RC] No leaks: 31 allocs, 31 frees
- All 263 tests pass
Remaining for full memory safety: ADT RC, early returns, conditionals.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add scope tracking for reference-counted variables in the C backend:
- Add RcVariable struct and rc_scopes stack to CBackend
- Track RC variables when assigned in let bindings
- Emit lux_decref() calls when scopes exit (functions, blocks)
- Add memory tracking counters (alloc/free) for leak detection
- Fix List.filter to incref elements before copying (prevents double-free)
- Handle return values by incref/decref to keep them alive through cleanup
The RC system now properly frees memory at scope exit. Verified with
test showing "[RC] No leaks: 28 allocs, 28 frees".
Remaining work: early returns, complex conditionals, closures, ADTs.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements Phase 1-3 of the RC system for automatic memory management:
- Add LuxRcHeader with refcount and type tag for all heap objects
- Add lux_rc_alloc, lux_incref, lux_decref, and lux_drop functions
- Update list allocation to use RC (lux_list_new uses lux_rc_alloc)
- List operations (concat, reverse, take, drop) now incref shared elements
- Update boxing functions (box_int, box_bool, box_float) to use RC
- String operations (concat, int_to_string, readLine) return RC strings
- File and HTTP operations return RC-managed strings
The infrastructure is ready for automatic decref insertion at scope exit
(Phase 4) and closure RC (Phase 5) in future work.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement HTTP client using POSIX sockets:
- Http.get(url) - GET request
- Http.post(url, body) - POST request
- Http.put(url, body) - PUT request
- Http.delete(url) - DELETE request
Features:
- Self-contained implementation (no libcurl dependency)
- URL parsing for host, port, and path
- HTTP/1.1 protocol with Connection: close
- Response body extraction
All Http operations use evidence passing for handler customization.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New effects with evidence passing support:
Random effect:
- int(min, max) - random integer in range
- float() - random float 0-1
- bool() - random boolean
Time effect:
- now() - milliseconds since epoch
- sleep(ms) - pause execution
File effect:
- read(path) - read file contents
- write(path, content) - write file
- append(path, content) - append to file
- exists(path) - check if file exists
- delete(path) - delete file
- isDir(path) - check if directory
- mkdir(path) - create directory
Also fixed:
- Function calls as statements now properly emit in generated C
- Return type inference for all effect operations
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
C backend now fully threads evidence through effectful function calls:
- Track effectful functions via effectful_functions HashSet
- Add has_evidence flag to track context during code generation
- Add LuxEvidence* ev parameter to effectful function signatures
- Transform effect operations to use ev->console->print() when evidence available
- Update function calls to pass evidence (ev or &default_evidence)
- Update main entry point to pass &default_evidence
Generated code now uses zero-cost evidence passing:
void greet_lux(LuxEvidence* ev) {
ev->console->print(ev->console->env, "Hello!");
}
This completes the evidence passing implementation for both interpreter
(O(1) HashMap lookup) and C backend (direct function pointer calls).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Interpreter changes:
- Add evidence HashMap for O(1) handler lookup instead of O(n) stack search
- Update eval_run to manage evidence when entering/exiting run blocks
- Modify handle_effect to use evidence.get() instead of stack iteration
C backend infrastructure:
- Add handler structs (LuxConsoleHandler, LuxStateHandler, LuxReaderHandler)
- Add LuxEvidence struct containing pointers to all handlers
- Add default handlers that delegate to built-in implementations
- Add Console.readLine built-in implementation
Documentation:
- Create docs/EVIDENCE_PASSING.md explaining design and implementation
- Update docs/C_BACKEND.md with current progress
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements full pattern matching with variable binding for the C backend:
- Extract variable bindings from patterns (Var, Constructor, Tuple, Record)
- Infer C types for bound variables using variant field type tracking
- Handle recursive ADTs with pointer fields and heap allocation
- Dereference pointer bindings automatically for value semantics
Key implementation details:
- variant_to_type: Maps variant names to parent type for tag generation
- variant_field_types: Maps (type, variant) to field types for inference
- Recursive type fields use Type* pointers with malloc/memcpy
- Pattern bindings dereference pointers to maintain value semantics
Examples that now work:
- match opt { Some(x) => x, None => 0 }
- match tree { Leaf(n) => n, Node(l, r) => sum(l) + sum(r) }
Updates documentation to reflect C backend progress.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement closures/lambdas in the C code generator:
- Add LuxClosure struct (env pointer + function pointer)
- Add ClosureInfo to track closure metadata during generation
- Implement free variable analysis to find captured variables
- Generate environment structs for each lambda's captured vars
- Generate lambda implementation functions
- Support indirect closure calls via function pointer casting
- Track functions returning closures for proper type inference
Example: fn(x) => x + n compiles to a LuxEnv struct holding n,
a lambda_N function taking env + x, and closure allocation code.
Limitations: No memory management (closures leak), types
mostly hardcoded to LuxInt.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove Cranelift JIT compiler and expose the existing C backend as the
compilation target. Generated C code can be compiled with GCC/Clang.
Changes:
- Remove cranelift-* dependencies from Cargo.toml
- Delete src/compiler.rs (565 lines of Cranelift code)
- Add compile_to_c() function with -o and --run flags
- Fix C backend name mangling (main -> main_lux) to avoid conflicts
- Update CLI help text and documentation
Usage:
lux compile <file.lux> # Output C to stdout
lux compile <file.lux> -o out.c # Write to file
lux compile <file.lux> --run # Compile and execute
C backend supports: functions, basic types, operators, if/then/else,
records, enums, Console.print. Future work: closures, lists, patterns.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Test effect with operations: assert, assertEqual, assertNotEqual,
assertTrue, assertFalse, fail
- Implement Test effect handlers in interpreter with TestResults tracking
- Add values_equal method for comparing Value types in tests
- Update lux test command to discover and run test_* functions
- Create example test files: test_math.lux, test_lists.lux
- Add TESTING_DESIGN.md documentation
- Fix AST mismatches in C backend and compiler.rs for compatibility
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>