This document outlines the core architectural constraints, design patterns, and development workflows for Project Lirien. These rules must be strictly adhered to during all future development to maintain mathematical soundness, type safety, and the "Python x Rust" developer experience.
- Logic Verification: A path-aware, flow-sensitive system using Z3 to prove the absence of logical errors, out-of-bounds accesses, and refinement type violations. Safety must be mathematically provable in Z3 using
Context::thread_local(). - Refinement Types: Lirien uses refinement types (liquid types) to attach logical predicates to data. Z3 verifies that all assignments and function calls satisfy these predicates across all reachable paths.
The Intermediate Representation (IR) enforces strict SSA form.
- Values Are Immutable: Once a
Valueis assigned viaget_def, it can never be reassigned. - Explicit Joins: Control flow joins must be handled explicitly via
Phinodes. - No Variable Mutation: Do not mutate variables in the IR; instead, create a new
Valueand update the block'svariable_defsmapping.
Lirien structs are compiled to flat, C-compatible memory layouts.
- Use Byte Offsets: Nested structures are inline. The IR must calculate the absolute byte offset from the root object (
StructOffsetorStructLoad) rather than chaining pointer dereferences. - Never Clobber Pointers: A
StructSetmodifies the value at an offset; it does not overwrite the root object's pointer address.
- Specialization Over Virtualization: Lirien uses
typing.Protocolfor static dispatch. The monomorphization engine must clone and specialize functions for every unique struct type passed to a Protocol parameter. - Static Call Mapping: The IR builder must resolve Protocol method calls to direct
Callinstructions using the mangled nameClassName_methodName.
- Zero-Overhead Optionals:
Optional[Box[T]]andBox[T] | Nonemust be represented as raw 64-bit pointers whereNoneis0x0. - Mandatory Verification: The Z3 verifier must prove non-nullity before any
PointerLoadorPointerStoreinstruction. The IR builder must automatically insert these checks for.valor field access.
- Flattening: Both
NamedTupleand standardTuplemust be recursively flattened into individual primitive values for function parameters and return values. - ABI Consistency: Small aggregates (<= 16 bytes, or 2 registers) are passed by value in registers. Larger aggregates must use return-by-pointer (SRet) but remain flattened as arguments.
- Unpacking Support: The IR must support
TupleExtractfor both memory-allocated and register-flattened tuples by correctly identifying the register slice or memory offset.
The Python-side DSL must feel like native Python, hiding all low-level C-ABI details.
- No Explicit ctypes in User Code: Users should never have to manually call
ctypes.pointerorctypes.addressof. - Native Types: Always use Lirien-native types (
i64,u8,f32,bool) in annotations. Do not exposectypes.c_int64to the user. - Automatic Unwrapping: The
@verifydecorator must automatically resolve Lirien objects to their underlying memory buffers before calling the JIT function.
- Dynamic Structure Generation: The
@structdecorator dynamically generates actypes.Structureclass behind the scenes. - Inlined Nested Structs: Nested structs are inlined by placing the child's
__lirien_ctypes__directly into the parent's_fields_list.
- Rust First: Always run
cargo checkbefore runningmaturin develop. Never attempt to build the Python module if the Rust core is in an inconsistent or failing state. - Maturin Reflection: After changes to the Rust core are verified, you must run
maturin developto reflect these changes in the Python environment. - Tool Usage: Using Python scripts,
sed, orcatto edit or update files is strictly banned. Use native tool functions likereplaceorwrite_filedirectly.
- No Standard Print Statements: Do not use
println!oreprintln!. - Tracing Logger: Use the
tracingcrate for all logging (e.g.,info!(target: "lirien::jit", ...)). - Source Location Mapping: All IR instructions must carry a
SourceLocationto map errors back to the Python source line.
When adding a new capability to the DSL:
- Update
TypeandInstructionKindinsrc/ssa/ir.rs. - Update the AST
visitor.rsto generate the new IR. - Update the
CFGBuilderlayout engine if the size/alignment changes. - Update the Z3 formal model in
src/verification/z3/(arithmetic, memory, or control_flow). - Update the Cranelift lowering in
src/backend/cranelift/lower/. - Update
src/ssa/optimization/dce.rsandtype_propagation.rsto ensure the instruction is handled. - Write a Python integration test verifying the full pipeline.
- No Explicit Context: The project uses
z3-rsv0.20.0, which is configured for ergonomics usingthread_localcontexts. You must not pass&Contextto AST constructors (e.g.,BV::from_i64,Bool::new_const). It usesContext::thread_local()internally. - No Context Reintroduction: Do not ever re-introduce
ctxarguments to the logic layers. This rule is absolute and permanent.
- Zero Warnings (Rust): The project maintains a strict zero-warning policy. All compiler warnings and Clippy lints must be resolved before committing. Use
cargo clippy -- -D warningsto verify. - Zero Warnings (Python): The project maintains a strict zero-warning policy for Python library code. You must run
ruff checkto verify all style and lint rules are met before committing. - Full Test Suite: Never assume a refactor is correct by running a single subfolder of tests. You must run the entire suite using
PYTHONPATH=./python python3 -m unittest discover tests/python. - No Shortcuts: Validation is not "it compiled". Validation is "all 200+ integration tests passed".
- Framework: Use the standard Python
unittestlibrary. Do not usepytest. - Execution: Run tests using
PYTHONPATH=./python python -m unittest discover tests/python. - Structure: Each test file must be runnable directly (e.g.,
if __name__ == "__main__": unittest.main()).
- Absolute Law: If the user tells you a bug is in the
git diff, or points you to a specific file or cause, investigate exactly what they told you immediately. The user's diagnosis is the highest signal. - Do Not Stall or Loop: Do not fall back on generic heuristics, infinite test running scripts, or over-analyzing irrelevant files to "buy time". If your automated approach fails or infinite-loops, and the user gives you a direct hint, immediately pivot and follow their explicit path.
- Consult Rules First: You must read and abide by the rules in this
GEMINI.mdfile before attempting to execute tasks. Do not assume standard generic workflows without verifying the project's exact required sequence. - Acknowledge Flaws: If you fail to follow these rules, recognize that it is a critical flaw and fundamentally dangerous to the codebase. Do not bullshit the user or feign blindness.
- Proactive Instrumentation: When modifying or debugging Python-side logic (FFI, decorators, signatures), you must include temporary
printstatements to trace data flow, type resolutions, and internal state. Never operate blind on the Python side.
- Format: Git commit messages must follow the conventional commit format:
<type>(<scope>): <description>(or<type>: <description>if scope is absent). - Case Sensitivity: The description must be in all lowercase.
- Structure: Commit messages must consist of a subject line, followed by a blank line, and a body with bullet points starting with
-detailing the specific modifications. - Examples:
-
feat(type-system): implement non-pointer value-type optionals (T | None) - Updated type parsing in metadata.rs to yield Type::Optional for non-pointer-like types - Implemented type propagation for Type::Optional under StructLoad and StructSet - Updated visit_compare in binary.rs to load the 1-byte boolean has_value tag - Added unit tests in test_null_safety.py to verify compiler, verifier, and FFI -
feat(compiler): implement JIT kernel fusion for element-wise tensor operations - Defined FusedExpr and InstructionKind::TensorFused in lirien-ir instruction macros - Implemented tensor kernel fusion pass in lirien-ir - Added Z3 dimension verification for TensorFused in lirien-verify - Implemented Cranelift code generation for TensorFused in lirien-backend
-