Section 15A: Attributes & Comments
Goal: Implement approved attribute syntax changes and comment restrictions
Source:
docs/ori_lang/proposals/approved/
15A.1 Simplified Attribute Syntax
Proposal: proposals/approved/simplified-attributes-proposal.md
Change attribute syntax from #[name(...)] to #name(...). Attributes are now generalizable to all declarations.
// Before
#[derive(Eq, Clone)]
#[skip("reason")]
// After
#derive(Eq, Clone)
#skip("reason")
Key Design Decisions
- Generalized attributes: Any attribute can appear before any declaration
- Compiler validation: The compiler validates which attributes are valid for which declarations
- Positioning: Attributes must appear immediately before the declaration they modify
Implementation
NOTE (verified 2026-03-29): LLVM sub-items throughout this section are IRRELEVANT — attributes are parsed metadata consumed by the parser/typechecker, not LLVM IR constructs. LLVM codegen never sees attributes or comments. All LLVM sub-items below are marked N/A.
-
Implement: Update lexer to emit
Hashtoken instead ofHashBracket(verified 2026-03-29)- Rust Tests:
ori_lexer/src/cooker/tests.rs—test_hash_tokenverifiesRawTag::HashproducesTokenKind::Hash; 31 lexer tests pass - Ori Tests: 125+ existing spec test files exercise
#skip,#compile_fail,#fail,#derive,#repr,#target,#cfg,#fbip - N/A
LLVM Support: attributes are frontend metadata, not LLVM IR constructs - N/A
LLVM Rust Tests: see above - N/A
AOT Tests: see above
- Rust Tests:
-
Implement: Update parser to parse
#name(...)syntax (verified 2026-03-29)- Rust Tests:
ori_parse/src/grammar/attr/tests.rs— 14 tests cover both bracket and bracketless syntax; semantic pins:test_parse_skip_attribute_no_brackets,test_parse_compile_fail_attribute_no_brackets,test_parse_derive_attribute_no_brackets - Ori Tests: grammar.ebnf line 239:
attribute = "#" identifier [ "(" ... ) ] . - N/A
LLVM Support: attributes are frontend metadata, not LLVM IR constructs - N/A
LLVM Rust Tests: see above - N/A
AOT Tests: see above
- Rust Tests:
-
Implement: Generalize attributes to all declarations (functions, types, traits, impls, tests, constants) (verified 2026-03-29)
- Rust Tests:
test_attributes_on_declarationsin parser tests - Ori Tests: grammar.ebnf line 233:
declaration = { attribute } [ "pub" ] ( function | type_def | trait_def | impl_block | ... ) . - N/A
LLVM Support: attributes are frontend metadata, not LLVM IR constructs - N/A
LLVM Rust Tests: see above - N/A
AOT Tests: see above
- Rust Tests:
-
Implement: Attribute validation (which attributes valid for which declarations) — PARTIAL (verified 2026-03-29): unknown attributes rejected (E1006), file-level validation exists, but no per-declaration target validation (e.g.,
#deriveon a function is not caught)- Rust Tests:
test_parse_unknown_attribute,test_file_attr_invalid_kind_reports_errorin parser tests - Ori Tests:
tests/compile-fail/invalid_attribute_target.ori— GAP: no test for invalid attribute targets - Per-declaration attribute-target validation (e.g., reject
#deriveon functions,#skipon types) - N/A
LLVM Support: attributes are frontend metadata, not LLVM IR constructs - N/A
LLVM Rust Tests: see above
- Rust Tests:
-
Implement: Support migration: accept both syntaxes temporarily (verified 2026-03-29)
- Rust Tests:
ori_parse/src/grammar/attr/tests.rs— tests cover both#[name(...)]and#name(...)forms;uses_bracketsflag threads through parsing - Ori Tests: 104 test files use old
#[derive(...)], 21 use new#derive(...)— both work - N/A
LLVM Support: attributes are frontend metadata, not LLVM IR constructs - N/A
LLVM Rust Tests: see above - N/A
AOT Tests: see above
- Rust Tests:
-
Implement: Add deprecation warning for bracket syntax — NOT IMPLEMENTED (verified 2026-03-29): parser silently accepts both forms, no warning infrastructure. Note: 104 test files still use old syntax; migration should precede or accompany this.
-
Implement: Update
ori fmtto auto-migrate — NOT IMPLEMENTED (verified 2026-03-29): no migration logic inori_fmtto convert#[name(...)]to#name(...) -
/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 (15A.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-15A.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 15A.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.
15A.2 function_seq vs function_exp Formalization
Proposal: proposals/approved/function-seq-exp-distinction.md
Formalize the distinction between sequential patterns and named-expression patterns.
function_seq (special syntax): run, try, match, catch
function_exp (named args): recurse, parallel, spawn, timeout, cache, with, for
function_val (positional): — REMOVED by int, float, str, byteas proposal
NOTE: The
asconversion proposal (proposals/approved/as-conversion-proposal.md) removesfunction_valentirely. Type conversions now usex as T/x as? Tsyntax, eliminating the special case for positional arguments.
Implementation
NOTE (verified 2026-03-29): LLVM sub-items throughout this section are IRRELEVANT — FunctionSeq/FunctionExp are AST nodes, not LLVM constructs. All LLVM sub-items below are marked N/A.
-
Implement: Verify AST has separate
FunctionSeqandFunctionExptypes (verified 2026-03-29)- Rust Tests:
test_function_exp_kind_namesinori_ir/src/ast/patterns/exp/tests.rsverifies all 15 variants; AST tests atast/tests.rslines 48-50 verify enum equality - Evidence:
FunctionSeqinori_ir/src/ast/patterns/seq/mod.rs,FunctionExp/FunctionExpKind(15 variants) inori_ir/src/ast/patterns/exp/mod.rs,ExprKind::FunctionSeq(FunctionSeqId)atast/expr.rsline 338 - N/A
LLVM Support: AST-level concern, not LLVM - N/A
LLVM Rust Tests: see above - N/A
AOT Tests: see above
- Rust Tests:
-
Implement: Parser allows positional for type conversions only (verified 2026-03-29) — OBE:
function_valremoved byasproposal; type conversions now useExprKind::Castwithas/as?syntax- Evidence: No
function_valcategory in AST; grammar usescast_expressionforas/as? - N/A
LLVM Support: AST-level concern, not LLVM - N/A
LLVM Rust Tests: see above - N/A
AOT Tests: see above
- Evidence: No
-
Implement: Parser enforces named args for all other builtins (verified 2026-03-29)
- Evidence:
FunctionExprequiresNamedExprRange(propsfield) — all properties are named expressions withname: valueformat - N/A
LLVM Support: AST-level concern, not LLVM - N/A
LLVM Rust Tests: see above - N/A
AOT Tests: see above
- Evidence:
-
Implement: Add clear error message for positional args in builtins (verified 2026-03-29) — PARTIAL: parser produces errors for positional arguments where named are required, but no dedicated compile-fail test exists
- Evidence: parser rejects positional args in function_exp contexts
- Ori Tests:
tests/compile-fail/builtin_positional_args.ori— GAP: no dedicated test file - N/A
LLVM Support: AST-level concern, not LLVM - N/A
LLVM Rust Tests: see above
15A.3 Inline Comments Prohibition
Comments must appear on their own line. Inline comments are not allowed.
// This is valid
let x = 42
let y = 42 // SYNTAX ERROR
Implementation
SPEC/IMPL GAP (verified 2026-03-29): The spec (
07-lexical-elements.mdsection 7.1) says “Inline comments (comments following code on the same line) are not permitted.” However, the compiler accepts them silently. The lexer classifies comments by content markers only, with no position-based validation.
NOTE (verified 2026-03-29): LLVM sub-items are IRRELEVANT — comment handling is a lexer concern, not LLVM. All LLVM sub-items below are marked N/A.
-
Implement: Update lexer to reject inline comments — NOT IMPLEMENTED (verified 2026-03-29): lexer has no logic to detect whether non-whitespace preceded
//on the same line- Rust Tests:
ori_lexer/src/comments/— inline comment position detection - Ori Tests:
tests/compile-fail/inline_comments.ori - N/A
LLVM Support: lexer-level concern, not LLVM - N/A
LLVM Rust Tests: see above
- Rust Tests:
-
Implement: Add clear error message for inline comments — NOT IMPLEMENTED (verified 2026-03-29): no error code assigned, no diagnostic message exists
- N/A
LLVM Support: lexer-level concern, not LLVM - N/A
LLVM Rust Tests: see above
- N/A
-
/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 (15A.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-15A.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 15A.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.
15A.4 Simplified Doc Comment Syntax
Proposal: proposals/approved/simplified-doc-comments-proposal.md
Simplify doc comment syntax by removing verbose markers:
// Before
// #Computes the sum.
// @param a The first operand.
// @param b The second operand.
// After
// Computes the sum.
// * a: The first operand.
// * b: The second operand.
Key Design Decisions
- Remove
#marker for descriptions — Unmarked comments before declarations are descriptions - Replace
@param/@fieldwith*— Markdown-like list syntax, context determines meaning - Canonical spacing —
// * name: descriptionwith space after*, colon always required - Non-doc comment separation — Blank line separates non-doc comments from declarations
Implementation
-
Implement: Update
CommentKindenum (verified 2026-03-29)- Replace
DocParam,DocFieldwith unifiedDocMember— done:CommentKindatori_ir/src/comment/mod.rshasRegular,DocDescription,DocMember,DocWarning,DocExample; noDocParam/DocFieldvariants exist -
Remove— NOTE:DocDescriptiondetection from lexerDocDescriptionstill exists in enum and is classified by lexer via#prefix; this is acceptable as the description marker is lightweight - Rust Tests:
ori_ir/src/comment/tests.rs— 9 tests verifyingsort_order()andis_doc()for all variants
- Replace
-
Implement: Update lexer comment classification (verified 2026-03-29)
- Recognize
*as member doc marker — done:classify_and_normalize_comment()inori_lexer/src/comments/mod.rs -
Remove— NOTE: both old and new markers still recognized; removal should NOT happen until migration is complete#,@param,@fieldrecognition - Rust Tests:
ori_lexer/src/comments/tests.rs— 31 classification tests pass
- Recognize
-
Implement: Update formatter doc comment reordering (verified 2026-03-29)
- Update
extract_member_nameto parse* name:syntax — done:extract_member_name_any()atori_fmt/src/comments/mod.rsline 324 handles both formats - Rust Tests:
test_extract_member_name_any_star_format,test_extract_member_name_any_legacy_param,test_extract_member_name_any_legacy_field— 4 formatter comment tests pass
- Update
-
Implement: Support migration from old syntax — PARTIAL (verified 2026-03-29)
- Lexer recognizes both old and new formats during transition — done:
#,@param,@fieldall produce correctCommentKindvariants alongside new*format -
ori fmtconverts old to new automatically — NOT IMPLEMENTED - Add deprecation warning for old format (
#Description,@param,@field) — NOT IMPLEMENTED
- Lexer recognizes both old and new formats during transition — done:
-
N/A
Implement: LLVM backend support(verified 2026-03-29) — IRRELEVANT: comments are lexer/parser/formatter metadata, not LLVM IR constructs -
/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 (15A.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-15A.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 15A.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.
15A.5 Section Completion Checklist
- All implementation items have checkboxes marked
[ ] - All spec docs updated
- CLAUDE.md updated with syntax changes
- Migration tools working
- 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: Attribute syntax, comment rules, and doc comment syntax implemented
- Subsection close-out (15A.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-15A.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 15A.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.