silver
silver copied to clipboard
Non-decorating locals/production attributes
As a part of #751, I've been thinking that we should perhaps have a variant of locals/production attributes that are not decoration sites, and thus can be used to hold a nonterminal without decorating it. This is useful for temporary variables in constructing complex ASTs, or for something like Type
in local resType::Type = ...;
where we want to write e.g. unify(resType, e.typerep)
instead of unify(new(resType), e.typerep)
, and aren't accessing attributes on resType
directly.
Also note the symmetry with translation attributes: we have regular higher-order attributes that aren't decoration sites, and translation attributes that are. This also suggests that the default for locals/production attributes should be to not decorate, and the decorating version should be explicitly opt-in, and only permit decorable types (i.e. non-data NTs, locals with occurs contexts.) This would be another significant breaking change, but hopefully not too painful.
I am still stumped on what the syntax for these variants of local/prod attrs should be, though. One idea was let local foo::Type = ...;
or let production foo::Type = ...;
for the non-decorating versions, and just local foo::Type = ...
or production foo::Type = ...
would be decorating. I don't really like this, though, since it's not super intuitive. Or maybe local decorate foo::Type = ...
/production decorate foo::Type = ...
? Perhaps this also suggests changing the syntax of translation attributes to be consistent.
Thoughts?
I like let local
/ let production
well enough; IMO, let
should be shorthand for let local
if we go that route.
Yeah, the trouble is that
let local resType::Type = ...;
vs.
local resType::Type = ...;
doesn't really say anything about being decorated or not, which might be confusing for new users. Also, which version do you use for something that isn't a nonterminal?
I am currently leaning towards having
local resType::Type = ...;
be non-decorating (and work with any type), while
local decorate resType::Type = ...;
is the decorating version, which requires the type to be a (non-data) nonterminal.
I guess dividing things in this way that also simplifies a presentation of the type rules - local
/production
always just bind the declared type, vs. local decorate
/production decorate
always wrap it in the decorated type constructor.
What about something like
term resType::Type = ...;
(undec)
vs.
local resType::Type = ...;
(dec)
?
Perhaps this clashes with something I'm not aware of.
Having term
as a keyword wouldn't be an issue. But I think for consistency the decorating version should only be used for nonterminals, and the non-decorating version would also be used for other stuff like lists, strings, references etc. that aren't exactly "terms". So I would lean towards changing the syntax for the version that does decorate.
Also we would need to have both local- and production-scoped versions. So we it would need to be something like local term resType::Type = ...
and production term resType::Type = ...
.
Okay, the consensus was
local term resType::Type = ...;
and
production term resType::Type = ...;
for the non-decorating versions. This new syntax will only permit nonterminals. The current local/prod attribute syntax will maintain the semantics of decorating (non-data) nonterminal types, consistent with the behavior of production children.
Changing production
to aspect
(or some other keyword for non-locally-scoped) and renaming new
to term
are items for future consideration. However using term
as a function name would require some workarounds, as term
will now need to be a reserved keyword with the above change.
Since having data nonterminals now muddies the terms vs. trees distinction, I'm leaning back towards "decorated" and "undecorated". So I think I now slightly prefer @RandomActsOfGrammar's suggestion of
local undec resType::Type = ...;
and
production undec resType::Type = ...;
I'm still open to suggestions of better keywords to use here. What about nondec
? That perhaps avoids confusion that a decorated thing is being un-decorated.
Coming back to this as the last dependency of #751. We never really settled on a syntax to use - going with local nondec
and production nondec
unless someone has a better suggestion.
Okay for now I'm going with nondecorated local x::Type = ...;
or nondecorated production x::Type = ...;
. Nondecorated locals can also just be abbreviated as nondecorated x::Type = ...;
.
This looks good to me. I don't remember this option but it seems pretty good.