Implementation plan for RFC #77: Assign Param Syntax (constructors only) #4986
Closed
SeanTAllen
started this conversation in
ponyc
Replies: 2 comments
-
|
The broader plan that includes |
Beta Was this translation helpful? Give feedback.
0 replies
-
|
Closing. We want the fun/be as well. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
This is a revised implementation plan for RFC #77 (issue #4318), scoped to constructors only. The previous plan (#4985) included
funandbemethods, but the RFC's motivation and examples all focus on constructors, andletfields (the primary use case) can only be assigned once, makingfun/besupport only useful forvarfields — something the RFC never discusses.What this is
Assign params let you write
this.field_namein a constructor parameter position. The compiler infers the type from the field declaration, generates a hygienic name for the actual parameter, and prependsfield = consume paramto the constructor body. The whole thing is sugar — it's gone by the time the scope pass runs.The before/after tells the story:
You can mix assign params with regular params and give them default values:
Implementation approach
The implementation is a new token type (
TK_ASSIGN_PARAM) that lives between the parser and sugar passes. The sugar pass replaces everyTK_ASSIGN_PARAMwith a normalTK_PARAMplus aconsume-based assignment at the top of the constructor body. Everything downstream sees vanilla parameters.Parser
A new
assignparamrule handlesthis.field_name [= default]. To keep assign params out of FFI parameter lists (which share theparamsrule), I'm adding amethodparamsrule that accepts both regular and assign params, used only in method declarations. The originalparamsrule stays untouched for FFI.The parser accepts assign params in any method's parameter list at the grammar level. The constructor-only restriction is enforced in the sugar pass, where
funandbemethods with assign params get a clear error: "assign parameters are only allowed in constructors." This gives a better error message than rejecting at parse time, where the context for a good message isn't available.Sugar pass
A new
sugar_assign_paramsfunction runs insugar_new(and insugar_be/sugar_funjust for error reporting), after docstring extraction but beforecheck_method.For each assign param in a constructor, it:
$0$1style names frompackage_hygienic_id)TK_PARAMand swaps it infield = consume $hygienic_idto the bodyNamed arguments are excluded naturally since hygienic names can't be written at call sites.
Field initializer interaction
There's a coupling between
sugar_entity(which prependsfield = init_valueto all constructor bodies for fields with default values) and the assign param transformation. If a field has both a declaration-site initializer and an assign param, the assign param wins —sugar_assign_paramsremoves the field initializer from the body to prevent double-assignment errors onletfields.Cap lifting for sendable contexts
Actor constructors and iso/trn/val class constructors require sendable parameters. When a field has a non-sendable cap, the param type gets lifted:
ref→iso,trn→iso,box→val. For unqualified types (where the cap isTK_NONEat sugar time), it conservatively lifts toiso. For complex types like type aliases where the cap isn't directly accessible, the type is left as-is and the existingflatten_sendable_paramscheck reports a clear error.Key design decisions
fun/beis a separate decision. Using assign params infunorbeproduces a clear error.TK_ASSIGN_PARAM) rather than a flag onTK_PARAM. The treecheckdef can validate it, and it's unambiguous during the parse → sugar window.methodparamsparser rule keeps assign params out of FFI declarations.Differences from the broader plan (#4985)
fun/beget an errorconstructor_needs_sendablereplacesmethod_needs_sendable, scoped to match only what the flatten pass checks (class + actor constructors)remove_field_init_from_bodyno longer needs a constructor guardfunandbeusageFiles touched
The change spans the parser (
parser.c,token.h,lexer.c,treecheckdef.h,frame.c) and the sugar pass (sugar.c). Tests go inparse_entity.cc,sugar.cc,badpony.cc, andtest/full-program-tests/. Plus an example program and release notes.Beta Was this translation helpful? Give feedback.
All reactions