The concrete syntax only allows attributes on tags/constructors/fields
(Rtag, Otag), not on inherited subtypes (Rinherit, Oinherit); we add
this as new enforced invariant in ast_invariants.
Now that each node that supports attributes also has a location,
we want to make the attributed node's location robustly available
to AST traversal functions.
The best way to do this would be to change the "attributes" traverser
to take the node's location as extra parameter. However, doing this
changes the type of the traverser interface, with a risk of breaking
user code. This may be the right long-term change, but for now
we go with something weaker: we ensure that the attributes of a node
are always traversed right after the node's location, which lets
user track attributed location (if they wish) through a side-effect.
Florian Angeletti and myself ran into a problem when trying to use attributes
for ellision of parts of manual example. We wanted to be turn any ast-node
marked with the [@ellipsis] attribute into "..." in the rendering of the
corresponding code block, but for this we need the location of the
attributed node, and it turns out that some constructions supported
attributes without carrying a location:
- Rtag in row_field
- Otag in object_field
- type_exception record
- type_extension record
We added locations in all those positions, guaranteeing the invariant
that all nodes to which attributes can be attached have a precise
position.
This commits extends the pattern syntax to support local open in
patterns. Four new constructions mirroring the expression constructions
are added
* `M.(pattern)`
* `M.[pattern_list]` ⟺ M.([pattern_list])
* `M.{labeled_pattern_list}` ⟺ M.({label_pattern_list})
* `M.[| .. |] ⟺ M.( [| .. |] )
At the typing phase, the construction `M.(pattern)` brings all
identifiers defined within M inside the scope and then proceed with the
typing of `pattern`. All others constructions are desugared to the
`M.(..)` construction during parsing.
Questionable implementation details:
* Currently, the local pattern open use the `type_open` function like
the local expression pattern. However, this implies that values defined
inside `M` are also brought to the scope. A specialized
`type_open_for_pattern` would be more efficient.