• No results found

The operational semantics in this chapter formalise a set of core pattern abstractions. Pat- tern expressions can be created by combining these abstractions. So far, the only way for abstracting these pattern expressions, i.e., to hide their implementation and make them appear as built-in patterns, is through a meta-language that is different from the pattern formalism. This section extends the pattern formalism with a mechanism for pattern ab- straction.

3.7.1 References

References provide a simple form of pattern abstraction: a name is associated with a pat- tern in such a way that the occurrence of the name is resolved to the pattern before match- ing or instantiation. An example is the pattern empty which was defined in Section 3.4 as a reference to the pattern !↵.

There are several ways to implement references in the pattern formalism. One way is to define the mapping between a name and a pattern as part of the operational semantics: every reference is defined as an inference rule with a conclusion hname, s, i m/i! result and a single premise hpattern, s, i m/i! result. This means that a name is replaced with a pattern by an operational rule of the system. Using this technique implies that the concept of reference is not part of the formalism. Adding new references means extending the formalism.

An alternative is the use of a meta-language to define references directly as trans- formations. Above, the meta-language operator “=)” was used for this purpose. The meta-language expression name =) pattern means that an occurrence of name can be rewritten to pattern. The extensibility mechanism defined in this section makes ref- erences explicit in the pattern formalism so that no external meta-language is needed – the pattern formalism is the meta-language. This means that the formalism can be ex- tended from within. Reference resolution is a pattern-based meta-transformation with the left-hand side naming the pattern on the right-hand side.

The meta-functionality introduced in Section 3.6 enables transformations of patterns using patterns. Such meta-transformations are a suitable basis for implementing mappings from pattern references to patterns. For instance, the meta-transformation

empty ) quote(!↵)

implements the above example using the quotation functionality described in the pre- vious section. The left-hand side matches the atom empty and the right-hand side pro- duces the pattern !↵.

3.7.2 Statically Parameterised References

Formalising references as transformations provides not only the advantage that the ref- erence resolution is defined by means of the pattern formalism but also that, in addition to simple name to pattern mappings, more powerful pattern abstractions can be defined. Parameterised references allow the passing of arguments during reference resolution. The arguments are used as values to instantiate variables in the meta-pattern on the right hand

side of the transformation. For example, the pattern operator ? which tries to match its argument can be defined as an unconditional transformation on a reference that consists of the operator name and a variable:

qq((uq(p:↵))?) ) qq(or([uq(p:↵),⇠(✏)]))

A reference to this pattern is ref((b)?) which is transformed into or([b,⇠(✏)]). The un- quote on the right-hand side leads to the instantiation of the variable during the trans- formation. Otherwise, the variable itself would be part of the transformation result. The arguments passed to a parameterised reference are static in the sense that the argument values are contained literally in the pattern expression. The semantics of the ref operator will be defined in the next subsection.

3.7.3 Dynamically Parameterised References

Dynamically parameterised references contain variables that are instantiated in the con- text of the current store before resolution. This enables values created from a previous match to be used as reference arguments. For example, matching the reference containing pattern⇠([f:↵, ref(rest(uq(f:↵))) first yields a binding for the variable f which is then passed to the referenced pattern rest. The definitions in this subsection not only formalise dynamically parameterised references but also parameterless and statically parametrised references as these are special cases of the former.

The ref operator surrounds its operand with a quasiquote before instantiating it. Parts surrounded with an unquote, such as the variable in the example above, are “activated” which means that variables are replaced with values bound in the current store. This im- plements the dynamic parametrisation. The actual reference resolution is performed by a meta-pattern that defines meta-transformations from references to patterns. Such a pat- tern can be constructed from individual meta-transformations using choice. It has the form or([m1, ..., mn])where m1, ..., mnare meta-transformations such as those for ? and empty defined above. Creating and manipulating this pattern, e.g., in order to add new references, can be expressed using meta-meta-transformations. The actual process of ref- erence definition and manipulation is, however, outside the scope of this formalisation.

To be able to define reference resolution, let the pattern pref srefer to the meta-pattern that defines how to resolve references. This pattern is matched with the result of instan- tiating the reference; the matching result is the outcome of the resolution process. It is matched with the input sequence to produce the overall result of matching the reference.

hqq(p), ✏, ini i ! hsii hall(pref s), si, ini m ! hrref, ✏, refi hrref, sin, ini m ! result href(p), sin, ini m

! result REFERENCESUCCESS

hqq(p), ✏, i! ?i href(p), sin, ini m! ? REFERENCEDYNAMIC? hqq(p), ✏, i! hsi ii hall(pref s), si, ini m ! ? href(p), sin, ini m ! ? REFERENCERESOLVE?

The instantiation semantics of references are very similar to the matching semantics. The actual reference resolution follows the same steps as in the matching case, the only dif- ference is that the result of resolving the reference is instantiated rather than matched.

hqq(p), ✏, ini! hsi ii hall(pref s), si, ini m ! hrref, ✏, refi hrref, sin, ini i ! result href(p), sin, ini i ! result R EFERENCEINST hqq(p), ✏, i! ?i href(p), sin, ini i ! ? REFERENCEINSTDYNAMIC? hqq(p), ✏, i! hsi ii hall(pref s), si, ini m ! ? href(p), sin, ini i ! ? REFERENCEINSTRESOLVE?

In the next chapter references will be used extensively to define productions of grammars. Chapter 5 provides examples of using dynamically parameterised references to avoid left- recursive definitions.