melt-umn / silver

An attribute grammar-based programming language for composable language extensions
http://melt.cs.umn.edu/silver/
GNU Lesser General Public License v3.0
57 stars 7 forks source link

Non-decorating locals/production attributes #796

Closed krame505 closed 3 months ago

krame505 commented 1 year ago

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?

remexre commented 1 year ago

I like let local / let production well enough; IMO, let should be shorthand for let local if we go that route.

krame505 commented 1 year ago

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.

krame505 commented 1 year ago

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.

unironically commented 11 months ago

What about something like term resType::Type = ...; (undec) vs. local resType::Type = ...; (dec) ? Perhaps this clashes with something I'm not aware of.

krame505 commented 11 months ago

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 = ....

krame505 commented 11 months ago

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.

krame505 commented 8 months ago

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.

krame505 commented 4 months ago

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.

krame505 commented 4 months ago

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 = ...;.

ericvanwyk commented 4 months ago

This looks good to me. I don't remember this option but it seems pretty good.