Section 13: Conditional Compilation
Goal: Enable platform-specific code and feature flags
Criticality: High — Required for cross-platform support and feature management
Proposal: proposals/approved/conditional-compilation-proposal.md
Design Decisions
| Question | Decision | Rationale |
|---|---|---|
| Syntax | #target(...) and #cfg(...) | Separate platform from features, clear intent |
| File-level | #!target(...) | Directive at top of file |
| OR conditions | any_os, any_arch, any_feature | Essential for real cross-platform code |
| Negation | not_* prefix | not_os, not_debug, not_feature — consistent |
| Families | family: "unix"/"windows"/"wasm" | Group related platforms |
| DCE | Full elimination | False branches not type-checked |
| Feature names | Valid identifiers only | Consistent with Ori naming |
Reference Implementation
Rust
~/projects/reference_repos/lang_repos/rust/compiler/rustc_attr_parsing/src/cfg.rs # cfg parsing
~/projects/reference_repos/lang_repos/rust/compiler/rustc_expand/src/cfg.rs # cfg evaluation
Go
~/projects/reference_repos/lang_repos/golang/src/go/build/constraint/ # Build constraints
~/projects/reference_repos/lang_repos/golang/src/cmd/go/internal/work/build.go # Build tags handling
Swift
# Swift uses #if os(...), #if arch(...), #if canImport(...)
~/projects/reference_repos/lang_repos/swift/lib/Parse/ParseIfConfig.cpp # #if config parsing
~/projects/reference_repos/lang_repos/swift/lib/AST/PlatformKind.cpp # Platform enumeration
13.1 Target Attribute
Spec section: spec/25-conditional-compilation.md § Target Attribute
Syntax
// Operating system
#target(os: "linux")
@linux_specific () -> void = ...
#target(os: "windows")
@windows_specific () -> void = ...
// Architecture
#target(arch: "x86_64")
@x64_specific () -> void = ...
// Target families
#target(family: "unix")
@unix_like () -> void = ...
// Combined (AND)
#target(os: "linux", arch: "x86_64")
@linux_x64 () -> void = ...
Implementation
-
Spec:
spec/25-conditional-compilation.mdClause 25.2 (verified 2026-03-29)- Target attribute syntax
- OS, arch, family values
- Scope rules
-
Lexer/Parser: Parse target attributes (verified 2026-03-29)
-
#target(...)syntax —conditional.rs:parse_target_attr_body() - Named arguments:
os:,arch:,family:— plusnot_os,not_arch,not_family,any_os,any_arch - Apply to items —
Function,TypeDecl,ImplDef,ConstDef,UseDefall havetarget_attr: Option<TargetAttr> - IR:
TargetAttrstruct inori_ir/src/ast/items/function.rs - Attribute dispatch:
AttrKind::Targetinattr/mod.rs - Placement validation:
has_non_conditional_attrs()+ rejection for trait/extend/extern - Rust Tests: 85+ parser tests pass —
attr_validation.rs(32 tests),file_attr.rs(53 tests), semantic pins, diagnostic pins, negative tests (verified 2026-03-29)
-
-
Compiler: Target evaluation — GAP-13-001
- Evaluate against build target — no
evaluate_target()function exists - Prune false branches from AST — all items type-checked regardless of target conditions
- Track for error messages
- Evaluate against build target — no
-
Ori Tests:
tests/spec/conditional/target_basic.ori— GAP-13-006: no Ori spec tests exist- OS-specific code
- Arch-specific code
- Family-specific code
- Combined conditions
-
LLVM Support: LLVM codegen for target attribute
-
LLVM Rust Tests:
ori_llvm/tests/conditional_tests.rs— target attribute codegen -
AOT Tests: No AOT coverage yet
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (13.1) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE/commit-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-13.1 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 13.1: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW. -
Repo hygiene check — run
diagnostics/repo-hygiene.sh --checkand clean any detected temp files.
13.2 OR Conditions
Spec section: spec/25-conditional-compilation.md § OR Conditions
Syntax
// Match any OS in list
#target(any_os: ["linux", "macos", "freebsd"])
@unix_variants () -> void = ...
// Match any architecture
#target(any_arch: ["x86_64", "aarch64"])
@desktop_arch () -> void = ...
Implementation
-
Spec: OR condition semantics — Clause 25.2.5 (verified 2026-03-29)
-
any_os,any_archwith list syntax - List syntax
-
-
Parser: Parse any_* variants (verified 2026-03-29)
- Array literal values —
conditional.rs:parse_attr_string_list() - IR:
TargetAttr::any_osandTargetAttr::any_archareVec<Name> - Rust Tests: 4 parse tests pass — 2-element list, single element, trailing comma (verified 2026-03-29)
- Array literal values —
-
Evaluator: Evaluate OR conditions — GAP-13-001
- Match if any element matches — no evaluation exists
-
Ori Tests:
tests/spec/conditional/target_or.ori— GAP-13-006- any_os conditions
- any_arch conditions
- Combined with AND
-
LLVM Support: LLVM codegen for OR conditions
-
LLVM Rust Tests:
ori_llvm/tests/conditional_tests.rs— OR conditions codegen -
AOT Tests: No AOT coverage yet
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (13.2) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE/commit-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-13.2 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 13.2: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW. -
Repo hygiene check — run
diagnostics/repo-hygiene.sh --checkand clean any detected temp files.
13.3 Negation
Spec section: spec/25-conditional-compilation.md § Negation
Syntax
// Negated conditions
#target(not_os: "windows")
@non_windows () -> void = ...
#target(not_family: "wasm")
@native_only () -> void = ...
#cfg(not_debug)
@release_only () -> void = ...
#cfg(not_feature: "ssl")
@insecure_fallback () -> void = ...
Implementation
-
Spec: Negation semantics — Clause 25.2.6 (verified 2026-03-29)
-
not_*prefix for all condition types - Interaction with OR conditions
-
-
Parser: Parse not_* variants (verified 2026-03-29)
- Target:
not_os,not_arch,not_family—conditional.rs:99-101 - Cfg:
not_debug(bare),not_feature(keyed) —conditional.rs:173-193 - IR:
TargetAttr::not_os/not_arch/not_family,CfgAttr::not_debug/not_feature - Rust Tests: 5 parse tests pass — target negation (3), cfg negation (2) (verified 2026-03-29)
- Target:
-
Evaluator: Evaluate negation — GAP-13-001
- Boolean NOT of underlying condition — no evaluation exists
-
Ori Tests:
tests/spec/conditional/negation.ori— GAP-13-006- not_os, not_arch, not_family
- not_debug, not_release
- not_feature
-
LLVM Support: LLVM codegen for negation
-
LLVM Rust Tests:
ori_llvm/tests/conditional_tests.rs— negation codegen -
AOT Tests: No AOT coverage yet
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (13.3) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE/commit-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-13.3 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 13.3: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW. -
Repo hygiene check — run
diagnostics/repo-hygiene.sh --checkand clean any detected temp files.
13.4 Cfg Attribute
Spec section: spec/25-conditional-compilation.md § Cfg Attribute
Syntax
// Build mode flags
#cfg(debug)
@debug_only () -> void = ...
#cfg(release)
@release_only () -> void = ...
// Feature flags
#cfg(feature: "ssl")
@secure_connect () -> void = ...
#cfg(any_feature: ["ssl", "tls"])
@encrypted_connect () -> void = ...
Implementation
-
Spec: Cfg attribute semantics — Clause 25.3 (verified 2026-03-29)
-
debug,releaseflags -
feature: "name"syntax -
any_feature,not_feature
-
-
Parser: Parse cfg attributes (verified 2026-03-29)
- Boolean flags (debug, release) —
conditional.rs:parse_cfg_attr_body() - Keyed flags (feature: ”…”) — handles
feature,not_feature,any_feature - OR and negation variants
- IR:
CfgAttrstruct inori_ir/src/ast/items/function.rs - Rust Tests: 13+ parse tests pass — cfg on function/type/const/impl/use, feature variants, semantic pins (verified 2026-03-29)
- Boolean flags (debug, release) —
-
Compiler: Cfg evaluation — GAP-13-001, GAP-13-002
-
--releaseflag exists inBuildOptions(verified 2026-03-29) — but NOT connected to cfg evaluation - Accept
--debugflag — debug is default but no explicit flag - Accept
--feature nameflags — current--featuresis for CPU features, not language features - Prune based on configuration — no cfg evaluation logic exists
-
-
Ori Tests:
tests/spec/conditional/cfg_basic.ori— GAP-13-006- debug/release flags
- feature flags
- any_feature, not_feature
-
LLVM Support: LLVM codegen for cfg attribute
-
LLVM Rust Tests:
ori_llvm/tests/conditional_tests.rs— cfg attribute codegen -
AOT Tests: No AOT coverage yet
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (13.4) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE/commit-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-13.4 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 13.4: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW. -
Repo hygiene check — run
diagnostics/repo-hygiene.sh --checkand clean any detected temp files.
13.5 Feature Flags
Spec section: spec/25-conditional-compilation.md § Features
Syntax
# In ori.toml
[features]
default = ["logging"]
logging = []
metrics = ["logging"] # depends on logging
experimental = []
ssl = []
// In code
#cfg(feature: "logging")
@log_message (msg: str) -> void uses Logger = ...
#cfg(not_feature: "logging")
@log_message (msg: str) -> void = () // No-op
// Feature-gated imports
#cfg(feature: "metrics")
use std.metrics { Counter, Gauge }
Feature Name Validation
Feature names must be valid Ori identifiers:
- Start with a letter or underscore
- Contain only letters, digits, and underscores
#cfg(feature: "ssl") // valid
#cfg(feature: "async_io") // valid
#cfg(feature: "my-feature") // error: invalid feature name
Implementation
-
Spec: Feature flag semantics — Clause 25.3.2 (verified 2026-03-29)
- Declaration in ori.toml
- Dependency resolution
- Default features
- Feature name validation —
is_valid_feature_name()inconditional.rs
-
Build system: Feature processing — GAP-13-002
- Parse ori.toml features — no ori.toml parser exists
- Resolve feature dependencies
- Pass to compiler
- Validate feature names — parser-level validation with E0932 (verified 2026-03-29)
-
Compiler: Feature evaluation — GAP-13-002
-
--featureflag — not implemented (current--featuresis for CPU features) -
--no-default-featuresflag -
--all-featuresflag - Rust Tests: 11 feature name validation tests pass — valid names (3), invalid names (5), negation/list contexts (3) (verified 2026-03-29)
-
-
Ori Tests:
tests/spec/conditional/features.ori— GAP-13-006- Basic feature gating
- Feature dependencies
- Default features
-
LLVM Support: LLVM codegen for feature flags
-
LLVM Rust Tests:
ori_llvm/tests/conditional_tests.rs— feature flags codegen -
AOT Tests: No AOT coverage yet
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (13.5) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE/commit-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-13.5 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 13.5: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW. -
Repo hygiene check — run
diagnostics/repo-hygiene.sh --checkand clean any detected temp files.
13.6 File-Level Conditions
Spec section: spec/25-conditional-compilation.md § File-Level Conditions
Syntax
// file: linux_impl.ori
#!target(os: "linux")
// Everything in this file is Linux-only
@epoll_create () -> int = ...
@epoll_wait (fd: int) -> [Event] = ...
The #! prefix indicates a file-level condition. It must appear before any declarations (after comments).
Implementation
-
Spec: File-level condition semantics — Clause 25.5 (verified 2026-03-29)
-
#!syntax - Position requirements
- Interaction with imports
-
-
Lexer: Recognize
#!token (verified 2026-03-29)-
TokenKind::HashBangexists, tested inori_lexer/src/tests.rs:850-885
-
-
Parser: Parse file-level conditions (verified 2026-03-29)
-
#!target(...),#!cfg(...)—mod.rs:parse_file_attribute()handles both, rejects other attrs - IR:
FileAttrenum with Target/Cfg variants,Module::file_attr: Option<FileAttr> - Grammar:
grammar.ebnf:185hasfile_attributeproduction - Rust Tests: 25+ parse tests pass — target/cfg variants, edge cases, rejection tests (verified 2026-03-29)
-
-
Compiler: File-level evaluation — GAP-13-001
- Skip entire file if condition false — files with false conditions still fully type-checked
- Track for IDE support
-
Ori Tests:
tests/spec/conditional/file_level.ori— GAP-13-006- File-level target
- File-level cfg
-
LLVM Support: LLVM codegen for file-level conditions
-
LLVM Rust Tests:
ori_llvm/tests/conditional_tests.rs— file-level conditions codegen -
AOT Tests: No AOT coverage yet
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (13.6) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE/commit-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-13.6 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 13.6: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW. -
Repo hygiene check — run
diagnostics/repo-hygiene.sh --checkand clean any detected temp files.
13.7 Compile-Time Constants
Spec section: spec/25-conditional-compilation.md § Compile-Time Constants
Sync Points: Compile-Time Constants (multi-crate sync required)
Adding $target_os, $target_arch, $target_family, $debug, $release requires:
ori_ir— Represent compile-time constants in AST (distinguish from user$constants)ori_types— Register type signatures ($target_os: str,$debug: bool, etc.) ininfer_ident()ori_eval— Provide runtime values from build configurationori_llvm— Fold to constants during codegen, enable dead branch elimination
Built-in Constants
$target_os: str // "linux", "macos", "windows", etc.
$target_arch: str // "x86_64", "aarch64", etc.
$target_family: str // "unix", "windows", "wasm"
$debug: bool // true in debug builds
$release: bool // true in release builds
Usage
@get_path_separator () -> str =
if $target_os == "windows" then "\\" else "/"
Dead Code Elimination
Branches conditioned on compile-time constants are eliminated and not type-checked:
@get_window_handle () -> WindowHandle =
if $target_os == "windows" then
WinApi.get_hwnd() // Only type-checked on Windows
else
panic(msg: "Not supported on this platform")
Implementation
-
Spec: Compile-time constant semantics — GAP-13-003: zero implementation across all 4 crates (verified 2026-03-29)
- Built-in constant names and types
- DCE rules
- Type-checking behavior
-
Lexer/Parser: Recognize built-in constants
-
$target_os,$target_arch, etc. — no AST representation distinct from user$constants - Treat as config variables
-
-
Type checker: Compile-time evaluation
- Evaluate comparisons at compile time — no type signatures in
infer_ident() - Skip type-checking false branches
- Eliminate dead code
- Rust Tests: Compile-time constant evaluation
- Evaluate comparisons at compile time — no type signatures in
-
Ori Tests:
tests/spec/conditional/constants.ori- $target_os checks
- $target_arch checks
- $debug/$release checks
- Dead branch elimination
-
LLVM Support: LLVM codegen for compile-time constants — no constant folding or DCE
-
LLVM Rust Tests:
ori_llvm/tests/conditional_tests.rs— compile-time constants codegen -
AOT Tests: No AOT coverage yet
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (13.7) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE/commit-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-13.7 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 13.7: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW. -
Repo hygiene check — run
diagnostics/repo-hygiene.sh --checkand clean any detected temp files.
13.8 Build Configuration
Spec section: spec/25-conditional-compilation.md § Build Configuration
CLI Flags
# Target specification
ori build --target linux-x86_64
ori build --target macos-aarch64
ori build --target windows-x86_64
# Features
ori build --feature ssl --feature async
ori build --no-default-features --feature minimal
# Build mode
ori build --debug # sets cfg(debug)
ori build --release # sets cfg(release)
# Custom cfg flags
ori build --cfg experimental
Project Configuration
# ori.toml
[package]
name = "myapp"
version = "1.0.0"
[features]
default = ["ssl"]
ssl = []
async = ["dep:async-runtime"]
experimental = []
[target.linux]
dependencies = ["libc"]
[target.windows]
dependencies = ["winapi"]
Implementation
-
Spec: Build configuration — Clauses 25.8-25.9 (verified 2026-03-29)
- ori.toml format
- CLI flag reference
- Precedence rules
-
Build system: Configuration processing — GAP-13-002
- Parse ori.toml — no ori.toml parser exists
- Merge with CLI flags
- Pass to compiler — build config not connected to conditional compilation evaluator
- Rust Tests: Build configuration processing
-
Compiler: Accept configuration
-
--targetflag —parse_args.rs:20, parsed intoBuildOptions::target(verified 2026-03-29) -
--featureflag — not implemented for conditional compilation -
--releaseflag —parse_args.rs:16-19(verified 2026-03-29) — but not connected to cfg evaluation -
--debugflag — not implemented as explicit flag (debug is default) -
--no-default-features/--all-featuresflags -
--cfgflag
-
-
Ori Tests: Integration tests — GAP-13-006
- Build with features
- Cross-compilation cfg
- Custom cfg values
-
LLVM Support: LLVM codegen for build configuration
-
LLVM Rust Tests:
ori_llvm/tests/conditional_tests.rs— build configuration codegen -
AOT Tests: No AOT coverage yet
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (13.8) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE/commit-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-13.8 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 13.8: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW. -
Repo hygiene check — run
diagnostics/repo-hygiene.sh --checkand clean any detected temp files.
13.9 Diagnostics
Spec section: spec/25-conditional-compilation.md § Diagnostics
Error Messages
// Clear errors for cfg mismatch
#target(os: "linux")
@linux_only () -> void = ...
// On Windows:
// error: function `linux_only` is not available on this platform
// --> src/main.ori:5:1
// |
// 5 | linux_only()
// | ^^^^^^^^^^ requires #target(os: "linux")
// |
// = note: current target: windows-x86_64
// = help: this function is only available on Linux
Invalid Feature Names
#cfg(feature: "my-feature")
// error: invalid feature name "my-feature"
// --> src/main.ori:1:15
// |
// 1 | #cfg(feature: "my-feature")
// | ^^^^^^^^^^^^ feature names must be valid identifiers
// |
// = help: use "my_feature" instead
Implementation
-
Diagnostics: Condition-aware error messages
- Show active configuration when relevant
- Suggest alternative platforms/features
- Validate feature names — E0932 registered and emitted by parser (verified 2026-03-29)
-
Lints: Condition validation
- Warn on impossible conditions
- Warn on unknown OS/arch values — no validation of OS/arch string values
- Error on invalid feature names — E0932 (verified 2026-03-29)
- Rust Tests: Feature name validation tests pass (verified 2026-03-29)
-
Error codes: GAP-13-005 — missing error codes from spec
- E0930: Invalid target OS — spec defines it, not registered in
ori_diagnostic - E0931: Invalid target architecture — spec defines it, not registered in
ori_diagnostic - E0932: Invalid feature name — registered and working (verified 2026-03-29)
- E0933: File-level condition must be first — spec defines it, not registered in
ori_diagnostic - BUG: Parser uses generic E1006 for target parameter errors instead of domain-specific E0930/E0931
- E0930: Invalid target OS — spec defines it, not registered in
-
Ori Tests:
tests/compile-fail/conditional/— GAP-13-006- Platform mismatch errors
- Invalid feature names
- Unknown condition values
-
LLVM Support: LLVM codegen for condition diagnostics
-
LLVM Rust Tests:
ori_llvm/tests/conditional_tests.rs— condition diagnostics codegen -
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (13.9) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE/commit-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-13.9 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 13.9: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW. -
Repo hygiene check — run
diagnostics/repo-hygiene.sh --checkand clean any detected temp files.
13.10 compile_error Built-in
CROSS-REFERENCE: Section 11.8 also covers
compile_errorin the FFI context. Implementation should be done once and shared; avoid duplicate work.
Proposal: proposals/approved/additional-builtins-proposal.md
Syntax
@compile_error (msg: str) -> Never
Causes a compile-time error with the given message. Valid only in compile-time evaluable contexts.
Constraints
// ERROR: compile_error in unconditional code
@bad () -> void = compile_error(msg: "always fails")
// OK: compile_error in dead branch
@platform_check () -> void =
if $target_os == "windows" then
compile_error(msg: "Windows not supported")
else
real_impl()
// OK: compile_error in #target block
#target(os: "windows")
@platform_specific () -> void = compile_error(msg: "Not supported")
Implementation
-
Spec: Add
compile_errortospec/annex-c-built-in-functions.md— GAP-13-004: zero implementation (verified 2026-03-29)- Syntax and return type — listed in ori-syntax.md prelude but not in Annex C
- Context restrictions (conditional compilation only)
- Error message format
-
Lexer/Parser: Reserve
compile_erroras built-in- Cannot define function with this name — not reserved, no parser recognition
-
Compiler: compile_error evaluation
- Type checker: not registered in
infer_ident(), no type signature(str) -> Never - Evaluator: not registered in
function_val.rs, not in eval dispatch - Detect in conditional compilation branches
- Verify not in runtime-reachable code
- Emit compile-time error with user message
- Rust Tests: compile_error evaluation tests
- Type checker: not registered in
-
Ori Tests:
tests/spec/conditional/compile_error.ori- In #target blocks
- In #cfg blocks
- In if $constant branches
- Compile-fail tests:
tests/compile-fail/compile_error_unconditional.ori
-
LLVM Support: LLVM codegen for compile_error
- Should never reach LLVM (compile-time only)
-
LLVM Rust Tests:
ori_llvm/tests/conditional_tests.rs— verify compile_error not in codegen -
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (13.10) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE/commit-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-13.10 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 13.10: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW. -
Repo hygiene check — run
diagnostics/repo-hygiene.sh --checkand clean any detected temp files.
Verification Summary (2026-03-29)
Overall: ~30% complete. Parser layer substantially done with 85+ passing Rust tests. Semantic evaluation entirely absent.
GAP Items
- GAP-13-001: Parse-to-Evaluation Gap [CRITICAL] — Parsed
TargetAttr/CfgAttrstructs stored on AST nodes but never evaluated. All conditional code always type-checked and compiled. Need evaluation/pruning pass before type-checking. Affects 13.1-13.6. - GAP-13-002: Build System Integration Gap [MAJOR] — No
--feature nameflag (current--featuresis CPU features), no--no-default-features/--all-features/--cfg/--debugflags, no ori.toml parser, build config not passed to evaluator. Affects 13.4, 13.5, 13.8. - GAP-13-003: Compile-Time Constants Not Implemented [MAJOR] —
$target_os/$target_arch/$target_family/$debug/$releasehave zero implementation across ori_ir, ori_types, ori_eval, ori_llvm. Affects 13.7. - GAP-13-004: compile_error Built-in Not Implemented [MAJOR] — Documented in prelude/ori-syntax.md but has no implementation in any phase. Cross-ref with Section 11.8. Affects 13.10.
- GAP-13-005: Error Codes Not Registered [MINOR] — Spec defines E0930 (Invalid target OS), E0931 (Invalid target arch), E0933 (File-level condition must be first), but only E0932 is registered. Parser uses generic E1006 for target param errors. Affects 13.9.
- GAP-13-006: No Ori-Level Spec Tests [MINOR] —
tests/spec/conditional/does not exist. All testing is Rust-level parser tests. Affects all subsections.
Section Completion Checklist
- All items above have all checkboxes marked
[x] - Spec written:
spec/25-conditional-compilation.md(verified 2026-03-29) - Grammar:
grammar.ebnfhasfile_attributeproduction (verified 2026-03-29) - Proposal:
proposals/approved/conditional-compilation-proposal.mdexists (verified 2026-03-29) - CLAUDE.md updated with conditional compilation syntax — ori-syntax.md has Conditional Compilation section (verified 2026-03-29)
-
#target(...)works on items -
#cfg(...)works on items -
#!target(...)works on files - OR conditions work (
any_*) - Negation works (
not_*) - Target families work
- Feature flags work
- Compile-time constants work
- Dead code elimination works
- Build system integration complete
- All tests pass:
./test-all.sh -
/tpr-reviewpassed — independent Codex review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — implementation hygiene review clean (phase boundaries, SSOT, algorithmic DRY, naming). MUST run AFTER/tpr-reviewis clean. -
/improve-toolingretrospective completed — MANDATORY at section close, after both reviews are clean. Reflect on the section’s debugging journey (whichdiagnostics/scripts you ran, which command sequences you repeated, where you added ad-hocdbg!/tracingcalls, where output was hard to interpret) and identify any tool/log/diagnostic improvement that would have made this section materially easier OR that would help the next section touching this area. Implement every accepted improvement NOW (zero deferral) and commit each via SEPARATE/commit-push. The retrospective is mandatory even when nothing felt painful — that is exactly when blind spots accumulate. See.claude/skills/improve-tooling/SKILL.md“Retrospective Mode” for the full protocol.
Exit Criteria: Can build a cross-platform CLI tool with platform-specific implementations
Example: Cross-Platform Path Handling
// Platform-specific path separator using compile-time constant
@get_path_separator () -> str =
if $target_os == "windows" then "\\" else "/"
// Platform-specific home directory using target attribute
#target(family: "unix")
@home_dir () -> Option<str> = Env.get(key: "HOME")
#target(os: "windows")
@home_dir () -> Option<str> = Env.get(key: "USERPROFILE")
// Platform-specific file operations
#target(family: "unix")
@set_permissions (path: str, mode: int) -> Result<void, Error> uses FileSystem = {
// Unix chmod
Unix.chmod(path: path, mode: mode)
}
#target(os: "windows")
@set_permissions (path: str, mode: int) -> Result<void, Error> uses FileSystem =
// Windows handles permissions differently
Ok(())
// Debug-only logging
#cfg(debug)
@debug_log (msg: str) -> void = print(msg: `[DEBUG] {msg}`)
#cfg(not_debug)
@debug_log (msg: str) -> void = ()