Context
DD-50 introduced Rule 2: if in expression position with no else
branch is a compile error. Example:
(bind x (if cond value)) ;; should be a compile error per Rule 2
The current implementation in both compilers emits a runtime
throw new TypeError("COMPILE_ERROR: ...") as an MVP
stand-in. The throw fires at runtime if the path is ever executed,
which is semantically correct (the program is broken) but
architecturally imprecise — DD-50's spec called for a true
compile-time error.
What needs to change
Replace the runtime-throw stand-in with a true compile-time
diagnostic emitted via the existing diagnostic channel before
emit, modelled on:
- Rust:
crates/lykn-lang/src/analysis/match_check.rs
(exhaustiveness check pattern) or
crates/lykn-lang/src/analysis/scope.rs (collision detection
from DD-49 Rule 6).
- JS: equivalent diagnostic-emitting path in the JS surface
expander.
After this change, the existing test that asserts on the
COMPILE_ERROR throw output should still pass (or be updated to
assert on the analysis-pass diagnostic instead).
Files
crates/lykn-lang/src/emitter/forms.rs — emit_if_expression
and convert_to_expression (search for COMPILE_ERROR:).
packages/lang/surface.js — search for COMPILE_ERROR: and
the if-handler's no-else error path.
crates/lykn-lang/src/analysis/ — natural home for the new
analysis pass.
Scope
Medium. Self-contained refactor; existing test coverage from
DD-50.5 and DD-50.5 addendum protects regression.
References
Context
DD-50 introduced Rule 2:
ifin expression position with no elsebranch is a compile error. Example:
The current implementation in both compilers emits a runtime
throw new TypeError("COMPILE_ERROR: ...")as an MVPstand-in. The throw fires at runtime if the path is ever executed,
which is semantically correct (the program is broken) but
architecturally imprecise — DD-50's spec called for a true
compile-time error.
What needs to change
Replace the runtime-throw stand-in with a true compile-time
diagnostic emitted via the existing diagnostic channel before
emit, modelled on:
crates/lykn-lang/src/analysis/match_check.rs(exhaustiveness check pattern) or
crates/lykn-lang/src/analysis/scope.rs(collision detectionfrom DD-49 Rule 6).
expander.
After this change, the existing test that asserts on the
COMPILE_ERROR throw output should still pass (or be updated to
assert on the analysis-pass diagnostic instead).
Files
crates/lykn-lang/src/emitter/forms.rs—emit_if_expressionand
convert_to_expression(search forCOMPILE_ERROR:).packages/lang/surface.js— search forCOMPILE_ERROR:andthe if-handler's no-else error path.
crates/lykn-lang/src/analysis/— natural home for the newanalysis pass.
Scope
Medium. Self-contained refactor; existing test coverage from
DD-50.5 and DD-50.5 addendum protects regression.
References
docs/design/05-active/0050-position-aware-compilation-of-conditional-and-block-forms.mdRule 2