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: 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- 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- 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)
- 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: 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
- 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: 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: 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: 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- 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 — 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
- 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 — 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: 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: 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: 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: 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
- N/A
Implement: LLVM backend support— IRRELEVANT: comments are lexer/parser/formatter metadata, not LLVM IR constructs
-
Implement: Update
CommentKindenum- 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
- 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
- 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
- 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:
-
/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
Exit Criteria: Attribute syntax, comment rules, and doc comment syntax implemented
- 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. - 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.