Closed TimSoethout closed 7 years ago
@TimSoethout thanks for your report. This is an area of the language where the compiler (in particular the type checker) is not yet completely mature. @mahills could you have a look at this? Maybe also a good occasion to finalize all the common keyword related issues.
I'm adding support for this, but the ability to add parameters like this could create problems -- I would assume that adding a parameter x
to Tree
would break any production that includes a label x
on a nonterminal (e.g., syntax B = myB: "this" x:A "that"
). This would be very non-local, so it would make sense to discuss this. We already have this problem with keyword params on ADTs, but at least in that case we don't have subtyping.
Cool!!
This feature is truly missing for a predictable and complete language design, one where concrete trees can always play the role of abstract data types. That's the goal.
I agree with your assessment, same rules apply for syntax trees as for abstract data. And the fields on Tree can and should not be shadowed by any user defined fields on non-terminals since that would break the dynamic semantics of generic code which operates on the Tree level but of course is always applied to concrete instances.
Finally this feature will interact later with data dependent parsers in some way or another. But that is as of yet unclear.
I don't think non locality is an issue, much. We can either prohibit interaction at the usage site, which can become cumbersome but it's ready to implement, or allow the user to disambiguate in case of multiple resolutions. So you'd have to type 'x.Tree::field' if field occurs in both Tree and a non terminal in scope..
I'm more concerned about the fact that adding the keyword parameter in one file could break other files, including library files that the user can't change. They would still be responsible for fixing it, and could (since it would be their addition that would have broken it), but it could be confusing.
I don't get that. If one module only has one of the definitions in scope, then out only sees that definition right? Ah.. I see.. The names could overlap dynamically and cancel each other out of we use the same mechanism for both levels in the type hierarchy...
We might: prefix non terminal fields with a unique prefix?
Add another layer of wrapping, trees with parameters nested around constructors with keyword parameters, or vice versa..
Something to think about indeed! Good point.
Right -- it could be that module M1
is fine, and M2
is fine, but when I import both into M3
it breaks because of a parameter name conflict. We already have this as an issue with ADTs, the issue here is the indirection -- adding something to Tree
could break non-Tree
types.
Statically we should resolve it with qualified names I think. And dynamically we will also need a prefix..
We can definitely resolve it, I guess part of the question is whether we want to. Resolving it would imply that we keep two or three copies of a parameter, e.g., the version declared on Tree
, the common parameter declared on the type, and a production-specific parameter, all of which could have different types. Whether the prefix is needed or not would then depend on whether there is an issue (you could always use it, but it would be cumbersome if not needed).
Context: branch tree-keyword-parameters
When I add a keyword parameter on my concrete syntax type, the compiler will complain. The interpreter works fine.
The compiler will complain on the last line with
Obviously it is there via the keyword parameter on
Tree
.