Section 15B: Function Syntax
Goal: Implement function-related syntax proposals
Source:
docs/ori_lang/proposals/approved/
15B.1 Remove Dot Prefix from Named Arguments
Proposal: proposals/approved/remove-dot-prefix-proposal.md
Change named argument syntax from .name: value to name: value. All functions require named arguments — no exceptions.
// Before
fetch_user(.id: 1)
print("Hello") // positional was allowed for built-ins
// After
fetch_user(id: 1)
print(msg: "Hello") // named required everywhere
Key Design Decisions
- All functions require named arguments (built-ins, user-defined, methods)
- Only function variable calls allow positional:
let f = x -> x + 1; f(5) - Type conversions use
assyntax (see 15D), not function calls - No positional shorthand (
foo(x)meaningfoo(x: x)is NOT supported — but see 15B.5 forfoo(x:)punning with trailing colon)
Implementation
Parser (dot removal done, enforcement needed)
-
Done: Parser accepts
IDENTIFIER ':'instead of'.' IDENTIFIER ':'- Basic syntax change already implemented
-
Implement: Enforce named arguments for built-in functions
- Rust Tests:
ori_parse/src/grammar/call.rs— builtin named arg enforcement - Ori Tests:
tests/spec/expressions/builtin_named_args.ori - Ori Tests:
tests/compile-fail/builtin_positional_args.ori
- Rust Tests:
-
Implement: Allow positional only for function variable calls
- Rust Tests:
ori_parse/src/grammar/call.rs— function var positional - Ori Tests:
tests/spec/expressions/function_var_positional.ori
- Rust Tests:
-
Implement: Clear error message when positional used incorrectly
- Rust Tests:
ori_diagnostic/src/problem.rs— positional arg error - Ori Tests:
tests/compile-fail/positional_arg_error.ori
- Rust Tests:
Built-in Function Updates
-
Implement: Update
printto requiremsg:parameter- Ori Tests:
tests/spec/expressions/print_named.ori
- Ori Tests:
-
Implement: Update
lento requirecollection:parameter- Ori Tests:
tests/spec/expressions/len_named.ori
- Ori Tests:
-
Implement: Update
is_emptyto requirecollection:parameter -
Implement: Update
assertto requirecondition:parameter- Ori Tests:
tests/spec/expressions/assert_named.ori
- Ori Tests:
-
Implement: Update
assert_eqto requireactual:,expected:parameters -
Implement: Update
assert_neto requireactual:,unexpected:parameters -
Implement: Update
assert_some,assert_noneto requireoption:parameter -
Implement: Update
assert_ok,assert_errto requireresult:parameter -
Implement: Update
assert_panicsto requiref:parameter -
Implement: Update
assert_panics_withto requiref:,msg:parameters -
Implement: Update
panicto requiremsg:parameter -
Implement: Update
compare,min,maxto requireleft:,right:parameters -
Implement: Update
repeatto requirevalue:parameter
Formatter
- Implement: Width-based stacking rule (inline if fits, stack if not)
- Rust Tests:
ori_formatter/src/— width-based stacking - Ori Tests: formatter integration tests
- Rust Tests:
Migration Tool
- Implement:
ori migrate remove-dot-prefixcommand- Finds
.identifier:patterns and removes the dot --dry-runflag for preview
- Finds
Documentation & Tests
- Implement: Update all existing tests to use named arguments for built-ins
- Implement: Update spec examples to use named arguments everywhere
- Implement: Update CLAUDE.md examples (partially done)
15B.2 Default Parameter Values
Proposal: proposals/approved/default-parameters-proposal.md
Allow function parameters to specify default values, enabling callers to omit arguments.
@greet (name: str = "World") -> str = `Hello, {name}!`
greet() // "Hello, World!"
greet(name: "Alice") // "Hello, Alice!"
Parser
-
Implement: Extend
paramproduction to accept= expressionafter type- Rust Tests:
ori_parse/src/grammar/decl.rs— default parameter parsing - Ori Tests:
tests/spec/declarations/default_params.ori - LLVM Support: LLVM codegen for default parameter parsing
- LLVM Rust Tests:
ori_llvm/tests/default_params_tests.rs— default parameter parsing codegen - AOT Tests:
ori_llvm/tests/aot/— default parameter parsing end-to-end
- Rust Tests:
-
Implement: Parse default expressions with correct precedence
- Rust Tests:
ori_parse/src/grammar/decl.rs— default expression precedence - Ori Tests:
tests/spec/declarations/default_params_precedence.ori - LLVM Support: LLVM codegen for default expression precedence
- LLVM Rust Tests:
ori_llvm/tests/default_params_tests.rs— default expression precedence codegen - AOT Tests:
ori_llvm/tests/aot/— default expression precedence end-to-end
- Rust Tests:
Type Checker
-
Implement: Verify default expression has parameter’s type
- Rust Tests:
ori_types/src/check/params.rs— default type checking - Ori Tests:
tests/compile-fail/default_param_type_mismatch.ori - LLVM Support: LLVM codegen for default type checking
- LLVM Rust Tests:
ori_llvm/tests/default_params_tests.rs— default type checking codegen
- Rust Tests:
-
Implement: Verify default doesn’t reference other parameters
- Rust Tests:
ori_types/src/check/params.rs— default param reference checking - Ori Tests:
tests/compile-fail/default_param_references_other.ori - LLVM Support: LLVM codegen for default param reference checking
- LLVM Rust Tests:
ori_llvm/tests/default_params_tests.rs— default param reference checking codegen
- Rust Tests:
-
Implement: Track which parameters have defaults for call validation
- Rust Tests:
ori_types/src/check/call.rs— optional parameter tracking - Ori Tests:
tests/spec/expressions/call_with_defaults.ori - LLVM Support: LLVM codegen for optional parameter tracking
- LLVM Rust Tests:
ori_llvm/tests/default_params_tests.rs— optional parameter tracking codegen
- Rust Tests:
-
Implement: Capability checking for default expressions
- Rust Tests:
ori_types/src/check/params.rs— default capability checking - Ori Tests:
tests/spec/capabilities/default_param_capabilities.ori - LLVM Support: LLVM codegen for default capability checking
- LLVM Rust Tests:
ori_llvm/tests/default_params_tests.rs— default capability checking codegen
- Rust Tests:
Call Site Validation
-
Implement: Required parameters (no default) must be provided
- Rust Tests:
ori_types/src/check/call.rs— required param validation - Ori Tests:
tests/compile-fail/missing_required_param.ori - LLVM Support: LLVM codegen for required param validation
- LLVM Rust Tests:
ori_llvm/tests/default_params_tests.rs— required param validation codegen
- Rust Tests:
-
Implement: Allow omitting parameters with defaults
- Rust Tests:
ori_types/src/check/call.rs— optional param omission - Ori Tests:
tests/spec/expressions/omit_default_params.ori - LLVM Support: LLVM codegen for optional param omission
- LLVM Rust Tests:
ori_llvm/tests/default_params_tests.rs— optional param omission codegen - AOT Tests:
ori_llvm/tests/aot/— optional param omission end-to-end
- Rust Tests:
-
Implement: Clear error message when required param missing
- Rust Tests:
ori_diagnostic/src/problem.rs— missing param error - Ori Tests:
tests/compile-fail/missing_required_param_message.ori - LLVM Support: LLVM codegen for missing param error
- LLVM Rust Tests:
ori_llvm/tests/default_params_tests.rs— missing param error codegen
- Rust Tests:
Code Generation
-
Implement: Insert default expressions for omitted arguments
- Rust Tests:
ori_llvm/src/codegen/call.rs— default insertion - Ori Tests:
tests/spec/expressions/default_insertion.ori - LLVM Support: LLVM codegen for default insertion
- LLVM Rust Tests:
ori_llvm/tests/default_params_tests.rs— default insertion codegen - AOT Tests:
ori_llvm/tests/aot/— default insertion end-to-end
- Rust Tests:
-
Implement: Evaluate defaults at call time (not definition time)
- Rust Tests:
ori_llvm/src/codegen/call.rs— call-time evaluation - Ori Tests:
tests/spec/expressions/default_call_time_eval.ori - LLVM Support: LLVM codegen for call-time evaluation
- LLVM Rust Tests:
ori_llvm/tests/default_params_tests.rs— call-time evaluation codegen - AOT Tests:
ori_llvm/tests/aot/— call-time evaluation end-to-end
- Rust Tests:
-
Implement: Correct evaluation order (explicit args first, then defaults in param order)
- Rust Tests:
ori_llvm/src/codegen/call.rs— evaluation order - Ori Tests:
tests/spec/expressions/default_eval_order.ori - LLVM Support: LLVM codegen for evaluation order
- LLVM Rust Tests:
ori_llvm/tests/default_params_tests.rs— evaluation order codegen - AOT Tests:
ori_llvm/tests/aot/— evaluation order end-to-end
- Rust Tests:
Trait Method Defaults
-
Implement: Allow defaults in trait method signatures
- Rust Tests:
ori_parse/src/grammar/trait.rs— trait method default parsing - Ori Tests:
tests/spec/traits/method_defaults.ori - LLVM Support: LLVM codegen for trait method defaults
- LLVM Rust Tests:
ori_llvm/tests/default_params_tests.rs— trait method defaults codegen - AOT Tests:
ori_llvm/tests/aot/— trait method defaults end-to-end
- Rust Tests:
-
Implement: Allow implementations to override/remove defaults
- Rust Tests:
ori_types/src/check/impl.rs— impl default override - Ori Tests:
tests/spec/traits/impl_override_defaults.ori - LLVM Support: LLVM codegen for impl default override
- LLVM Rust Tests:
ori_llvm/tests/default_params_tests.rs— impl default override codegen - AOT Tests:
ori_llvm/tests/aot/— impl default override end-to-end
- Rust Tests:
-
Implement: Trait object calls use trait’s declared default
- Rust Tests:
ori_llvm/src/codegen/dyn_dispatch.rs— dyn default dispatch - Ori Tests:
tests/spec/traits/dyn_trait_defaults.ori - LLVM Support: LLVM codegen for dyn default dispatch
- LLVM Rust Tests:
ori_llvm/tests/default_params_tests.rs— dyn default dispatch codegen - AOT Tests:
ori_llvm/tests/aot/— dyn default dispatch end-to-end
- Rust Tests:
15B.3 Multiple Function Clauses
Proposal: proposals/approved/function-clauses-proposal.md
Allow functions to be defined with multiple clauses that pattern match on arguments.
@factorial (0: int) -> int = 1
@factorial (n) -> int = n * factorial(n - 1)
@abs (n: int) -> int if n < 0 = -n
@abs (n) -> int = n
Parser
-
Implement: Allow
match_patternin parameter position (clause_param)- Rust Tests:
ori_parse/src/grammar/decl.rs— clause parameter parsing - Ori Tests:
tests/spec/declarations/function_clauses.ori - LLVM Support: LLVM codegen for clause parameter parsing
- LLVM Rust Tests:
ori_llvm/tests/function_clauses_tests.rs— clause parameter parsing codegen - AOT Tests:
ori_llvm/tests/aot/— clause parameter parsing end-to-end
- Rust Tests:
-
Implement: Parse
ifguard clause betweenwhere_clauseand=- Rust Tests:
ori_parse/src/grammar/decl.rs— guard clause parsing - Ori Tests:
tests/spec/declarations/function_clause_guards.ori - LLVM Support: LLVM codegen for guard clause parsing
- LLVM Rust Tests:
ori_llvm/tests/function_clauses_tests.rs— guard clause parsing codegen - AOT Tests:
ori_llvm/tests/aot/— guard clause parsing end-to-end
- Rust Tests:
-
Implement: Group multiple declarations with same name into single function
- Rust Tests:
ori_parse/src/grammar/decl.rs— clause grouping - Ori Tests:
tests/spec/declarations/function_clause_grouping.ori - LLVM Support: LLVM codegen for clause grouping
- LLVM Rust Tests:
ori_llvm/tests/function_clauses_tests.rs— clause grouping codegen - AOT Tests:
ori_llvm/tests/aot/— clause grouping end-to-end
- Rust Tests:
Semantic Analysis
-
Implement: Validate all clauses have same parameter count
- Rust Tests:
ori_types/src/check/clauses.rs— parameter count validation - Ori Tests:
tests/compile-fail/clause_param_count_mismatch.ori - LLVM Support: LLVM codegen for parameter count validation
- LLVM Rust Tests:
ori_llvm/tests/function_clauses_tests.rs— parameter count validation codegen
- Rust Tests:
-
Implement: Validate all clauses have same return type
- Rust Tests:
ori_types/src/check/clauses.rs— return type validation - Ori Tests:
tests/compile-fail/clause_return_type_mismatch.ori - LLVM Support: LLVM codegen for return type validation
- LLVM Rust Tests:
ori_llvm/tests/function_clauses_tests.rs— return type validation codegen
- Rust Tests:
-
Implement: Validate all clauses have same capabilities (
uses)- Rust Tests:
ori_types/src/check/clauses.rs— capability validation - Ori Tests:
tests/compile-fail/clause_capability_mismatch.ori - LLVM Support: LLVM codegen for capability validation
- LLVM Rust Tests:
ori_llvm/tests/function_clauses_tests.rs— capability validation codegen
- Rust Tests:
-
Implement: First clause rules (visibility, generics, types)
- Rust Tests:
ori_types/src/check/clauses.rs— first clause signature - Ori Tests:
tests/spec/declarations/first_clause_rules.ori - LLVM Support: LLVM codegen for first clause rules
- LLVM Rust Tests:
ori_llvm/tests/function_clauses_tests.rs— first clause rules codegen
- Rust Tests:
-
Implement: Type inference for subsequent clause parameters
- Rust Tests:
ori_types/src/check/clauses.rs— clause type inference - Ori Tests:
tests/spec/declarations/clause_type_inference.ori - LLVM Support: LLVM codegen for clause type inference
- LLVM Rust Tests:
ori_llvm/tests/function_clauses_tests.rs— clause type inference codegen
- Rust Tests:
-
Implement: Error if visibility/generics repeated on subsequent clauses
- Rust Tests:
ori_types/src/check/clauses.rs— duplicate modifier errors - Ori Tests:
tests/compile-fail/clause_duplicate_modifiers.ori - LLVM Support: LLVM codegen for duplicate modifier errors
- LLVM Rust Tests:
ori_llvm/tests/function_clauses_tests.rs— duplicate modifier errors codegen
- Rust Tests:
Exhaustiveness & Reachability
-
Implement: Exhaustiveness checking across all clauses
- Rust Tests:
ori_types/src/check/exhaustiveness.rs— clause exhaustiveness - Ori Tests:
tests/compile-fail/clause_non_exhaustive.ori - LLVM Support: LLVM codegen for clause exhaustiveness
- LLVM Rust Tests:
ori_llvm/tests/function_clauses_tests.rs— clause exhaustiveness codegen
- Rust Tests:
-
Implement: Unreachable clause detection and warnings
- Rust Tests:
ori_types/src/check/exhaustiveness.rs— unreachable clause warning - Ori Tests:
tests/warnings/unreachable_clause.ori - LLVM Support: LLVM codegen for unreachable clause warning
- LLVM Rust Tests:
ori_llvm/tests/function_clauses_tests.rs— unreachable clause warning codegen
- Rust Tests:
Code Generation
-
Implement: Desugar clauses to single function with
match- Rust Tests:
ori_llvm/src/codegen/clauses.rs— clause desugaring - Ori Tests:
tests/spec/declarations/clause_desugaring.ori - LLVM Support: LLVM codegen for clause desugaring
- LLVM Rust Tests:
ori_llvm/tests/function_clauses_tests.rs— clause desugaring codegen - AOT Tests:
ori_llvm/tests/aot/— clause desugaring end-to-end
- Rust Tests:
-
Implement: Function clause
ifguards (compile to match arm guards)- Rust Tests:
ori_llvm/src/codegen/clauses.rs— guard desugaring - Ori Tests:
tests/spec/declarations/guard_desugaring.ori - LLVM Support: LLVM codegen for guard desugaring
- LLVM Rust Tests:
ori_llvm/tests/function_clauses_tests.rs— guard desugaring codegen - AOT Tests:
ori_llvm/tests/aot/— guard desugaring end-to-end
- Rust Tests:
Integration
-
Implement: Named argument reordering before pattern matching
- Rust Tests:
ori_llvm/src/codegen/call.rs— argument reordering - Ori Tests:
tests/spec/expressions/clause_named_args.ori - LLVM Support: LLVM codegen for argument reordering
- LLVM Rust Tests:
ori_llvm/tests/function_clauses_tests.rs— argument reordering codegen - AOT Tests:
ori_llvm/tests/aot/— argument reordering end-to-end
- Rust Tests:
-
Implement: Default parameter filling before pattern matching
- Rust Tests:
ori_llvm/src/codegen/call.rs— default filling with clauses - Ori Tests:
tests/spec/expressions/clause_default_params.ori - LLVM Support: LLVM codegen for default filling with clauses
- LLVM Rust Tests:
ori_llvm/tests/function_clauses_tests.rs— default filling codegen - AOT Tests:
ori_llvm/tests/aot/— default filling with clauses end-to-end
- Rust Tests:
-
Implement: Tests target function name (cover all clauses)
- Rust Tests:
ori_types/src/check/test.rs— clause test targeting - Ori Tests:
tests/spec/testing/clause_tests.ori - LLVM Support: LLVM codegen for clause test targeting
- LLVM Rust Tests:
ori_llvm/tests/function_clauses_tests.rs— clause test targeting codegen - AOT Tests:
ori_llvm/tests/aot/— clause test targeting end-to-end
- Rust Tests:
15B.4 Positional Lambdas for Single-Parameter Functions
Proposal: proposals/approved/single-lambda-positional-proposal.md
Allow omitting parameter names when calling single-parameter functions with inline lambda expressions.
// Before (required)
items.map(transform: x -> x * 2)
items.filter(predicate: x -> x > 0)
// After (allowed)
items.map(x -> x * 2)
items.filter(x -> x > 0)
The Rule
When ALL of the following are true:
- Function has exactly one explicit parameter (excluding
selffor methods) - The argument expression is a lambda literal
THEN: The parameter name may be omitted.
What Counts as a Lambda?
Lambda expressions (allowed positional):
x -> expr(single parameter)(a, b) -> expr(multiple parameters)() -> expr(no parameters)(x: int) -> int = expr(typed lambda)
NOT lambda expressions (named arg required):
- Variables holding functions:
let f = x -> x + 1; list.map(f) - Function references:
list.map(double)
Type Checker
-
Implement: Check for lambda-literal positional argument exception in call resolution
- Rust Tests:
ori_types/src/infer/ (calls)— lambda positional arg tests - Ori Tests:
tests/spec/expressions/lambda_positional.ori - LLVM Support: LLVM codegen for lambda positional args
- LLVM Rust Tests:
ori_llvm/tests/call_tests.rs— lambda positional arg codegen - AOT Tests:
ori_llvm/tests/aot/— lambda positional arg end-to-end
- Rust Tests:
-
Implement: Verify callee has exactly 1 explicit parameter (exclude
self)- Rust Tests:
ori_types/src/infer/ (calls)— single param check - Ori Tests:
tests/spec/expressions/lambda_positional_single_param.ori - LLVM Support: LLVM codegen for single param check
- LLVM Rust Tests:
ori_llvm/tests/call_tests.rs— single param check codegen
- Rust Tests:
-
Implement: Verify argument expression is a
LambdaExprAST node- Rust Tests:
ori_types/src/infer/ (calls)— lambda detection - Ori Tests:
tests/spec/expressions/lambda_positional_detection.ori - LLVM Support: LLVM codegen for lambda detection
- LLVM Rust Tests:
ori_llvm/tests/call_tests.rs— lambda detection codegen
- Rust Tests:
-
Implement: Reject positional for function references/variables (not lambda literals)
- Rust Tests:
ori_types/src/infer/ (calls)— function reference rejection - Ori Tests:
tests/compile-fail/positional_function_reference.ori - LLVM Support: LLVM codegen for function reference rejection
- LLVM Rust Tests:
ori_llvm/tests/call_tests.rs— function reference rejection codegen
- Rust Tests:
Error Messages
- Implement: Clear error when using positional non-lambda for single-param function
- Rust Tests:
ori_diagnostic/src/problem.rs— positional non-lambda error - Ori Tests:
tests/compile-fail/positional_non_lambda_message.ori
- Rust Tests:
error[E2011]: named arguments required for direct function calls
--> src/main.ori:5:12
|
5 | items.map(double)
| ^^^^^^
|
= help: use named argument syntax: `map(transform: double)`
= note: positional arguments are only allowed for inline lambda
expressions, not function references
Edge Cases
-
Implement: Nested lambdas work correctly
- Ori Tests:
tests/spec/expressions/lambda_positional_nested.ori - LLVM Support: LLVM codegen for nested lambdas
- LLVM Rust Tests:
ori_llvm/tests/call_tests.rs— nested lambdas codegen - AOT Tests:
ori_llvm/tests/aot/— nested lambdas end-to-end
- Ori Tests:
-
Implement: Chained method calls with lambdas
- Ori Tests:
tests/spec/expressions/lambda_positional_chained.ori - LLVM Support: LLVM codegen for chained lambdas
- LLVM Rust Tests:
ori_llvm/tests/call_tests.rs— chained lambdas codegen - AOT Tests:
ori_llvm/tests/aot/— chained lambdas end-to-end
- Ori Tests:
-
Implement: Lambda returning lambda
- Ori Tests:
tests/spec/expressions/lambda_returning_lambda.ori - LLVM Support: LLVM codegen for lambda returning lambda
- LLVM Rust Tests:
ori_llvm/tests/call_tests.rs— lambda returning lambda codegen - AOT Tests:
ori_llvm/tests/aot/— lambda returning lambda end-to-end
- Ori Tests:
Documentation
- Implement: Update spec
09-expressions.mdwith lambda positional exception - Implement: Update
CLAUDE.mdwith lambda positional syntax
15B.5 Argument Punning (Call Arguments)
Proposal: proposals/approved/argument-punning-proposal.md
Allow omitting the value in a named function argument when the argument name matches the variable name: f(x:) for f(x: x). Parser-only desugaring — type checker, evaluator, and LLVM see the expanded form.
// Before:
conv2d(input: input, weight: weight, bias: bias, stride: 2)
// After:
conv2d(input:, weight:, bias:, stride: 2)
Parser
-
Implement: In call argument parsing, when
name:followed by,or), create syntheticExpr::Ident- Rust Tests:
ori_parse/src/grammar/expr/postfix/tests.rs— punned call arg parsing - Ori Tests:
tests/spec/expressions/argument_punning.ori
- Rust Tests:
-
Implement: Mixed punned and explicit arguments parse correctly
- Ori Tests:
tests/spec/expressions/argument_punning_mixed.ori
- Ori Tests:
-
Implement:
f(x)positional unchanged (no regression)- Ori Tests:
tests/spec/expressions/positional_arg_regression.ori
- Ori Tests:
Error Messages
-
Implement:
f(x:)whenxnot in scope produces “cannot find valuex”- Ori Tests:
tests/compile-fail/punning_not_in_scope.ori
- Ori Tests:
-
Implement:
f(x:)when function has no paramxproduces existing “unknown parameter” error- Ori Tests:
tests/compile-fail/punning_unknown_param.ori
- Ori Tests:
Formatter
-
Implement: Detect
name == value_identin call args and emitname:form- Rust Tests:
ori_fmt/src/formatter/— call arg punning canonicalization
- Rust Tests:
-
Implement: Preserve
f(x: other)— no punning when names differ- Rust Tests:
ori_fmt/src/formatter/— non-punning preservation
- Rust Tests:
Documentation
- Implement: Update spec
09-expressions.mdwith call argument punning - Implement: Update
grammar.ebnfwith optional expression innamed_arg - Implement: Update
.claude/rules/ori-syntax.mdwith punning syntax
15B.6 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
Exit Criteria: Function syntax proposals implemented