• Ingen resultater fundet

2.3 Transparency and Coercion

2.3.4 Transparency in gbeta

This section was written to be read and forgotten! It exposes all those coercions between dierent kinds of semantic entities (run-time entities) that transparency is there to hide. These coercions will be inserted by the compiler in the right places, such that names can be used in the same way even though they may be dened as dierent kinds of attributes, e.g., as an object or as a pattern.

However, the details must be described at some point, and that point is this section.

As explained in Sect. 2.2.5, gbeta provides four basic kinds of attributes, namely object, variable object, pattern, and variable pattern. In gure 2.4, the coercion mechanism for execution, assignment, and evaluation (i.e., everything except declarations) is specied. The gure contains much information, so it will be described in details in the following.

The four kinds of attributes are shown, one in each box, using an italic typeface, along with the associated semantic entities, such asobjectorpattern. The arrows between the boxes represent coercions. For example, with a given variable object attribute, an object identier (member of oid) or NONE can be obtainedthat's what a variable object attribute contains; this object iden-tier can then be coerced into an object unless it is NONE, as indicated by the:NONE annotation on the leftmost upward arrow. If object identities are represented simply as memory addresses, the coercion would be a dereferenc-ing operation, but other operations might be used with other representations of object identities. The important thing is that we can get hold of an object.

Coercion happens when a piece of syntax which denotes an attribute is used in some syntactic context. In the general case, that piece of syntax is an Attri-buteDenotation, see the full grammar in App. A, but in the simplied grammar used sofar, it is just aName. There are three dierent syntactic contexts, namely

`Name[]', `Name##', and the default context. The default context applies in all other cases, i.e., for all names not followed by one of those two coercion markers.

The coercion is a journey from one of the boxes to another one, consisting of the actions associated with the arrows on the path. The starting point is

deter-mined by the kind of attribute which theNameis declared to be. For example, it would start in the top left box for an object attribute. The destination of the journey is the box which is marked with the syntactic context, i.e., with `[]',

`##', or `default'. Given a starting point and a destination, the path of arrows is fully determined, and the coercion can be described. The following piece of code uses all paths through a number of examples:

(# i: @integer;

s: ^string;

p: (# #);

pv: ##object do

i; s; p; pv;

i[]; s[]; p[]; pv[];

i##; s##; p##; pv##;

#) Ex.

2-2

The attributes i,s, p, andpvare of all kinds, namely object, variable object, pattern, and variable pattern, respectively. TheDoPartthen systematically puts them into the three dierent syntactic contexts, hence causing coercions from any of the four starting points to any of the three destinations.

The rst imperative, `i', causes the empty coercion, because an object is needed and that is exactly what the attribute already denotes. In contrast, the imperative `pv[]' in the next line of the program causes a coercion with several steps. The starting point is the bottom right box since the attribute is a variable pattern. The destination is the bottom left box, since the coercion marker is `[]'. As a consequence, the following actions are taken: It is checked whether pvis NONE; if it is NONE then a run-time error is raised, otherwise the pattern is obtained. Then the pattern is instantiated, yielding a new object.

Finally the identity of the object is obtained, and that is the result.

Note that an imperative like `s[]' does not do anything, since the object identity is obtained and then immediately discarded, but in order to explain coercion these more or less silly imperatives are the simplest possible examples.

A more useful imperative could be like `pv[]->m', which would perform the same coercion onpvas above and then give the obtained object identity as an argument to the invocation of the methodm.

There is one anomaly in this system, namely that assignment to syntax in a

`[]' or a `##' context requires that this syntax denote a variable attribute of the destination kind, i.e., variable object or variable pattern, respectively. In other words, no coercions are allowed when using one of the two markers on the right hand side of an assignment. For example, with `m->s[]' it is required that s denote a variable object attribute.

The problem is that assignment with non-trivial coercion to, e.g., the lower left box would have unwanted semantics. Consider the case where the attribute denotes a pattern,p, the imperative is `m->p[]', and the evaluation of mdelivers the object identity #. If this were to be allowed, then the assignment should changepin such a way that future evaluations of p[]would deliver#, at least until the next change.

2.3. TRANSPARENCY AND COERCION 35

However, this would not match well with the rest of the language. Whenever an object or object identity is requested from syntax denoting a pattern, the object will be instantiated afresh. So an object identity can be obtained from a pattern, but we cannot change what object it will deliver the next time. In this respect the pattern attribute is similar to an object attributethe object attribute invariably denotes one xed object, and the pattern attribute delivers a dierent object at every request, but both of them have so strict semantic constraints on what object to provide that the semantics of variable assignment is incompatible.

Hence, the situation is similar to that of assigning to a constant attribute in other languages, like `const int i=1; i=2;' in C++, which is of course also rejected at compile-time. Note that languages with accessor methods, e.g. Cecil, have a similar behavior: A constant variable or eld has only a reader accessor, no writer. As a consequence, any attempt to assign to such an attribute will lead to an error because the required method is missing. In those languages it is possible to add a user-dened method with the signature expected of a writer accessor, thus allowing for a user-dened resolution of the conict. A similar approach could be used ingbeta, but such a feature has not yet been designed in detail.

Hence, transparency is very complete for evaluation and for value assign-ment, but the coercion markers `[]' and `##' used on the receiving side of an assignment break the transparency with the current language design.

We have described the coercions associated with execution of code; the rest of this section deals with coercions in declarations. This is simple as there are solely two groups of attributes: The pattern attributes and the variable attributes, both variable objects and patterns, require a pattern on the right hand side of the declaration, and this pattern is obtained by coercion. The object attributes, being the only attributes not yet covered, require an object on the right hand side. Figure 2.5 describes the mechanism. The only dierence between Fig. 2.4 and Fig. 2.5 is the annotation which denes the destination of coercions in dierent contexts; for declarations the destination is determined by theKindof declaration, as introduced in Fig. 2.2 on page 24.

Especially two consequences of this are interesting. The syntaxthis(Name) is used to denote the nearest enclosing object which is statically known to be an instance of a specialization of the pattern obtained from the givenName; it is similar tothisin C++ andselfin Smalltalk, except for the usage of aName to select the right one out of the potentially many enclosing objects. Consider the following example:

link: (# next: ^this(link); value: @integer #) Ex.

2-3

The link pattern represents a basic singly linked list where each link in the list may hold an integervalueand a reference to the nextelement in the list.

Since the qualication of next is obtained from the denotation of the link object itself, it denotes the pattern of that object. This might be link, but in a subpattern of linkit would be that subpattern. In other words, this is a genuine `SelfType' or `MyType' [15]. In the Beta community there has been some discussion about dening a special construct to be able to provide genuine self-types [73], but this has not yet been implemented nor completely designed.

There is a well-known workaround which uses a virtual pattern that the programmer must manually redeclare in all subpatterns, as in the following example:

link:

(# selfType:< link;

next: ^selfType;

value: @integer

#) Ex.

2-4

The workaround is error-prone, and it does not have the right typing proper-ties: The type system cannot assume that the selfTypevirtual is the pattern of the enclosing object, because there is no guarantee that it will actually be that pattern. If the programmer forgets to further-bind the virtual in a new subpattern, it will not anymore be a correct self-type.

Another case where the coercion in connection with declarations is useful, if perhaps not beautiful, is the case where an object attribute has a specication which is a variable object. An example is the following:

(# X: ^somePattern enter X[]

do (# constX: @X do ::: constX ::: #)

#) Ex.

2-5

In the outermostMainPart, the variable objectX can be used for many things, but sometimes it must be assured for application specic reasons that dierent usages of a name actually refer to the very same object. Moreover, this is also valuable in the type analysis, because it may prove that certain patterns are the same even though it is not known what pattern it is, thus proving, e.g., an assignment type safe without exact knowledge about the involved patterns.

To obtain such an immutable object name, we can declare an object attribute which denotes the object available fromXat some point. To do this we need a

2.3. TRANSPARENCY AND COERCION 37 place to put the new declaration. This is achieved by creating an anonymous object, using the inserted item syntax (which denotes a pattern which is then by coercion instantiated and executed), as with (# constX: @X ::: #)in the DoPart. The name constXcan be used in theDoPartof the inserted item, and that name will invariably denote the object which was available from X when the inserted item was created. This is an example of the `snapshot' semantics which is presented and motivated in Sect. 3.9.

Note that a similar semantics with the same syntax is obtained with a dif-ferent approach in [12], which is based on a generalization of the notion of qualications.

Finally, the relation betweengbetacoercion and Beta coercion can be de-scribed. The entity transformations presented in this section have not tradition-ally been described in terms of a consistent coercion scheme in Beta; indeed, not everybody in theBeta community accept this as a natural explanation of the Beta semantics. However, the actual behavior of Beta programs can be described exactly by the gures and explanations in this section, except for a few cases which are prohibited inBeta, namely:

Coercions cannot have variable object as the destination except when the starting point is object. For coercions from pattern and variable pattern, the new operator, `&', must be added in front of the (variable) pattern denotation, like in&p[].

In declarations, only one kind of entity can be usedboth the specication of an object attribute and the qualication of a variable attribute must be a pattern.

Patterns

This chapter deals with patterns in gbeta, and since all the concepts are so tightly integrated this tends to touch on everything; so this is a long chapter with many dierent topics covered in various sections. The overall outline of the chapter is as follows: First there is a presentation of the basic premises and the building blocks from which patterns are constructed. Then properties of patterns as a whole are discussed, and then composition of several patterns into new patterns. Finally there is a discussion of a few satellite topics.

Section 3.1 explains that patterns are values and not objects, and why it is so. It is followed by a presentation of the concept of mixins in general in Sect. 3.2, and Sect. 3.3 gives a presentation of mixins in gbeta, along with the entities which are built out of mixins, namely patterns and their brethren, the objects.

Now that we have the value domain of patterns available the question about equality in that domain arises, and Sect. 3.4 covers both various kinds of equiv-alence which is used for classes and similar entities in other languages, and the very strict equivalence criterion which is used for patterns in gbeta(and in

Beta).

Patterns in gbeta are organized into specialization networks, and this is a signicantly more densely populated universe than the corresponding strictly tree-shaped specialization hierarchies inBeta. The relation between these two is covered in Sect. 3.5. With patterns organized into specialization networks it becomes possible to talk about superpatterns and therefore also about inheri-tance of attributes, as it happens in Sect. 3.6.

This establishes patterns as standalone entities, and Sect. 3.7 builds on this by describing how patterns can be composed into new patterns by means of merging. Any construction of a new pattern, including pattern merging and plain, old inheritance like in Beta, will aect the behavior associated with that pattern when it is used as a method. The topic of Sect. 3.8 is how such composite behavior can be created and explained in terms of the mixins and their do-parts in a pattern, and how that gives rise to a broader notion of specialization of behavior than that of Beta, but one that grows out of the

39

Beta tradition.

Finally there is a treatment of a few additional topics in association with patterns. The rst topic is the notion of object creation by instantiation of patterns, which is covered in Sect. 3.9. After that, Sect. 3.10 goes into more detail about how attributes in objects can be accessed, specifying the local name lookup rules which are the basic elements of all name binding ingbeta. The last section in this chapter, Sect. 3.11 deals with the notion of qualications, similar to such a notion as the declared type of references.

Hence, this chapter covers not only patterns, but also the building blocks from which patterns are built, namely mixins, and the entities which are created according to patterns, namely objects. It should be obvious that patterns are absolutely essential in the design ofgbetaa trait thatgbetahas inherited from

Beta.