日本ソフトウェア科学会第 31 回大会 (2014 年度) 講演論文集

Visibility of Context-oriented Behavior andState in L
Robert Hirschfeld

Hidehiko Masuhara

Atsushi Igarashi

Tim Felgentreff
One of the properties of context-oriented programming languages is the composition of partial module
definitions. While in most such language extensions the state and behavior introduced by partial definitions
are treated equally at the module level, we propose a refinement of that approach to allow for both public
and restricted visibility of methods and local and shared visibility of fields in our experimental language L.
Furthermore, we propose a new lookup mechanism to reduce the risk of name captures.

1 Introduction
Context-oriented Programming (COP) is an approach to software modularity [4]. COP languages
and systems provide constructs and mechanisms to
combine and abstract behavioral variations, which
can be activated and deactivated according to computational context at run-time.
Most COP language extensions are add-ons toother modularity mechanisms provided by thehost language—usually classes in an contemporary
object-orienged environment.
L is our exploration of the design of a COP language that tries to avoid asymmetry between module constructs for capturing partial or full implementations of system properties [6]. Instead of having COP constructs adding behavioral variations
to a base system implemented using other composition mechanisms, L systems are based only on
partial objects and layers.
So far, state and behavior introduced by differ-ent partial definitions are treated almost as if they
originate from one and the same defining module,with the exception that they can be dynamically
activated and deactivate depending on the execution context on an individual basis. Visibility control respects the constraints imposed by the hostlanguage, but usually does not go beyond that.
In a more dynamic execution environment wherecomposition units can be added to and withdrawn
from the system at run-time, it seems desirable
to assist developers with additional visibility constructs that allow them to describe which units of
behavior and state to be made available to or hidefrom other parts of a composition.
With Lfour (our fourth version of L) we propose
a new visibility mechanism and lookup mechanismthat allow for that.
In the following we describe our proposal in moredetail by discussing an example and describing arevised lookup mechanism in its support.

2 Visibility
文脈指向言語 L における挙動と状態のアクセス制御

Robert Hirschfeld and Tim Felgentreff, HassoPlattner-Institute, University of Potsdam.
増原英彦, 東京工業大学大学院情報理工学研究科, Department of Mathematical and Computing Sciences,
Tokyo Institute of Technology.
五十嵐淳, 京都大学大学院情報学研究科, Department ofCommunications and Computer Engineering, Kyoto
University.

We want to control visibility for both behavior
and state with respect to the objects and layers
they are defined in and used. (In this text we use
the terms behavior/methods and state/fields interchangebly.)2. 1 Behavior
For behavior we want to allow for partial method
definitions to contribute to the public interface ofan object, either by changing the way the object
responds to a message received or by allowing an
object to respond to entirely new messages it was
not able to understand so far.
On the other hand, we want to explicitly markmethods to be only accessible from within a set ofpartial definitions. To not complicate matters unnecessarily, we want to ensure that the visibilityof methods can be restricted to a particular layer
implementation.
We introduce two method markers named public and restricted —public for partial method definitions of the former kind and restricted for thelatter.
Methods marked public can be accessed not
only from anywhere in the layer they are definedin but also from any other partial definition in
any other layer, assuming that the current layercomposition—usually established by a sequence of
preceding with or without constructs—was set up
accordingly.
If a method is marked restricted, it can be only
activated if the corresponding message received
originated from the same layer that defines thatmethod. It is important to not that restricted
methods cannot be called via next, or put differently, methods from one layer can only proceedto public methods if available. (next [7] Is similar to CLOS call-next-method [9] or ContextFJs
proceed) [6] in that it invokes the next available
partial method defintion of the same name and signature in the current composition.)
Also, restricted methods when called within theirdefining layer have precedence over other public
partial definitions of the same method from outerlayers to prevent name captures.
For example as shown in Figure 1, method m2
of object O1 and layer L3 calls m1 and m3 directly
since both methods are declared restricted and in
the same layer as the calling m2 and so are considered first.
2. 2 StateFor state we want to enable the interaction of partial definitions via side effects since sharing fields
between methods has been shown convenient and is

L4
L3
L2
L1
f1

f2

f3

f4

m1 m2 m3 m4
O1

field accesssame field
method call (regular)
method call (via next)

Fig. 1shared field (circle, empty)
local field (polygon, empty)
public method (circle, filled)
restricted method (polygon, filled)

Composition with (L4 L3 L2 L1).

common practice in object-oriented programmingfrom its inception.
But we also want to confine state so that is is only
visible from within a particular partial definition—
for now from within a partial object definition.
We provide two field markers named shared andlocal —shared for field declarations of the former
kind and local for the latter.
Fields marked shared can be accessed from allpartial definitions of an object if declared there as
such. All these partial definitions then refer to one
and the same field meaning that, if changed fromwithin one partial definition, this modification is
the same to all partial definitions that participate
in sharing that field.
From outside a partial object definition, all fields
marked local cannot be accessed directly. With
that, state is not only confined to a particular object but also to a specific layer.
In Figure 1 one can see that only the fields declared in L3 (f1, f2, and f3) can be accessed frommethods defined there.
When layered, field declarations can shadow eachother. While there is no such mechanism like next
for fields, sharing resembles next since it allows
implicit state propagation in-between participating
partial definitions. However, there is an importantdifference between the two: While control propagation via next can only proceed to layers more innerthan the current one, state propagation (via side
effects) goes both inward and outward.

layer L1 {object O1 {shared var f1 , f2 , f3 , f4 ;public setVars ( _f1 , _f2 , _f3 , _f4 ) {f1 = _f1 ;f2 = _f2 ;f3 = _f3 ;f4 = _f4 ;}public m1 () { ↑ ’ L1O1m1 ’; }public m2 () { ↑ ’ L1O1m2 ’; }public m3 () { ↑ ’ L1O1m3 ’; }public m4 () { ↑ ’ L1O1m4 ’; }}}Listing 1

layer L2
object O1 {local var f2 , f3 , f4 ;public setVars ( _f2 , _f3 , _f4 )f2 = _f2 ;f3 = _f3 ;f4 = _f4 ;}restricted m2 () { ↑ ’ L2O1m2 ’;
restricted m3 () { ↑ ’ L2O1m3 ’;
restricted m4 () { ↑ ’ L2O1m4 ’;}}
Listing 2

{

}
}
}

Layer L2.

Layer L1.

3 Composition Example
We illustrate some of the consequences of the application of public/restricted and shared /local in
the following rather abstract example. We show
both a textual representation and a corresponding
visual illustration of a composition of layers of partial object definitions.
The values assigned to fields and returned frommethods are strings encoded as follows: ‘L’ stands
for layer, ‘O’ for object, ‘f’ for field, and ‘m’ formethod. And the digits following the latter further qualify the respective layer, object, field, or
method. For example, ‘L3O1f2’ was assigned tofield f2 of object O1 in layer L3 and ‘L4O1m3’ isreturned from method m3 of object O1 in layer L4.
Layer L1 (Listing 1) provides partial definitions
for object O1. There are four variables f1, f2,
f3, and f4, that can be set via the public method
setVars, and three more methods m2, m3, and m4.
All fields are shared fields so they can be altered
not only from within O1 of L1, but also by otherpartial definitions of O1, assuming that f1 is declared there to be a public field also. All methods
are public methods and with that contribute to O1’s
public interface—that is, the interface that can beaccessed from outside of L1 if L1 is activated.
Layer L2 (Listing 2) defines only local fields (f2,
f3, and f4) and restricted methods (m2, m3, andm4) for object O1 so that L2’s partial definition of
O1 cannot directly cause side effects with other partial definitions of O1 and does not add to O1’s public
interface.
Layers L3 and L4 (Listing 3) provide another mix
of shared and local fields and public and restricted
methods to make the composition discussed morelayer L3
object O1 {shared var f2 ;local var f1 , f3 ;public setVars ( _f1 , _f2 , _f3 )f1 = _f1 ;f2 = _f2 ;f3 = _f3 ;}restricted m1 () { ↑ ’ L3O1m1 ’;// *** point of interest ***public m2 () {return’* ’ + f1 + ’_ ’ + f2 + ’_ ’’= ’ + m1 () + ’_ ’ + next ()m3 () + ’_ ’ + m4 () + ’* ’;}restricted m3 () { ↑ ’ L3O1m3 ’;
}
}

{

}

+ f3 ++ ’_ ’ +}layer L4 {object O1 {shared var f1 , f2 ;local var f3 ;public setVars ( _f1 , _f2 , _f3 ) {f1 = _f1 ;f2 = _f2 ;f3 = _f3 ;}public m1 () { ↑ ’ L4O1m1 ’; }restricted m3 () { ↑ ’ L4O1m3 ’; }}}Listing 3

Layers L3 and L4.

interesting.
While the assignment of fields and the implementation of methods follows the simple pattern mentioned above, method m2 of object O1 in layer L3(L3.O1.m2) is different in that it returns a stringthat assembles the values of all of the fields accessible from that method and of all of the return values of the methods that can be called from partial
method m2 defined in layer L3 for object O1. Also,
m2 is declared public and so can be called also fromcode outside of L1.
We compose the layers described above using
a sequence of with statements with interspersed
method calls for setting newly introduced instanceturn values provided by the other methods callable
local var o = new O1 ();from there. (Even though m2 could call m2, it doeswith ( L1 ) {not in our example to avoid infinite recursion.)o . setVars (’ L1O1f1 ’ , ’ L1O1f2 ’ , ’ L1O1f3 ’ , ’ L1O1f4 ’);After adding layers L3 and L4 to our composition// <1 >
with ( L2 ) {(see Figure 1 for a more visual illustration), calls too . setVars (method m2 show the values of all accessible fields’ L2O1f2 ’ , ’ L2O1f3 ’ , ’ L2O1f4 ’);// <2 >
andthe return values of all methods callable fromwiht ( L3 ) {o . setVars (m2 with L3 and L4 activated. As with the previous’ L3O1f1 ’ , ’ L3O1f2 ’ , ’ L3O1f3 ’);compositions, fields f1, f2, and f3 hold the content// <3 >
o . m2 ();just assigned via setVars (all starting with ‘L3’).
// = > ’* L 3 O 1 f 1 _ L 3 O 1 f 2 _ L 3 O 1 f 3 =\// L 3 O 1 m 1 _ L 1 O 1 m 2 _ L 3 O 1 m 3 _ L 1 O 1 m 4 * ’
For the methods, calling m1 and m3 from L3.O1.m2
wiht ( L4 ) {invokes restricted methods m1 and m3 from the sameo . setVars (’ L4O1f1 ’ , ’ L4O1f2 ’ , ’ L4O1f3 ’);layer m2’s definition is located. The invocation of// <4 >
o . m2 ();next from L3.O1.m2 will skip L2.O1.m2 since it is// = > ’* L 3 O 1 f 1 _ L 4 O 1 f 2 _ L 3 O 1 f 3 =\restricted to L2.O1 (!) and proceed to the next// L 3 O 1 m 1 _ L 1 O 1 m 2 _ L 3 O 1 m 3 _ L 1 O 1 m 4 * ’}public version of m2, which is the one defined in// <5 >
o . m2 ();L1.O1.
// = > ’* L 3 O 1 f 1 _ L 4 O 1 f 2 _ L 3 O 1 f 3 =\With the activation of layer L4 (<4>), the value// L 3 O 1 m 1 _ L 1 O 1 m 2 _ L 3 O 1 m 3 _ L 1 O 1 m 4 * ’}returned by m2 is based on the current values of// <6 >
L3.O1.f1, L3.O1.f2, and L3.O1.f3. This is be}// <7 >
cause the m2 executed is that found in L3.O1 and}Listing 4

Composition.

variables or fields 4.
We now explain the visibility of fields and partial
methods as the system composition evolves. Afterthe activation of layer L1 and the initialization of
the instance variables accessible from object O1’s
definition in L1 (<1>), the values that can be retrieved from fields f1, f2, f3, and f4 are the ones
set via the preceeding invocation of setVars.
The situation after activating layer L2 <2> is similar. Here it is important to note that partial definitions introduced by L2 for object O1 can only
access fields f2, f3, and f4 but not f1 since f1 is
not declared for O1 in L2.
With the activation of layer L3 and the initialization of the fields declared for object O1 (<4>),
we can again only access fields explicitly declaredin that partial definition (L3 and O1). But here
field f2 is marked shared and so shares its valueof other public fields of the same name declared inother partial definitions of O1—currently (<4>) in
L1 and later (<5>) L4.
When calling m2 at <4>, we activate m2 of O1 in L3(L3.O1.m2), which will construct a string showing
the content the fields are referring to and the re-so m2 has only access to fields defined by L3.O1.
Here, ‘L4O1f2’ is the value set for L4.O1.f2 after
activating L4 (<4>), thus ‘L4’ at the beginning of
the string. Since L4.O1.f2 and L3.O1.f2 (and also
L1.O1.f1) are all declared shared, assignments toany one of them will also be an assignment to allof them!
After leaving the scope of L4—now with L3 being the outermost layer of our composition (<5>)
again—the result of calling m2 from here shows thatthe side effect caused by L4 via the assignmet to f2
shared between L4.O1, L3.O1, and L1.O1 was preserved across layer activation/deactivation.
At <6> the values of f2, f3, and f4) were notaffected by side effects since all of L2.O1’s fields are
local. However, at <7> with all fields of L1.O1 being
shared, previous assignmets initiated from partial
definitions located in other layers but L1 show also
in L1.O1.

4 Lookup
One of the core mechanisms of COP language
extensions is the method lookup in layer compositions. This lookup mechanism corresponds roughly
to the one employed by plain object-oriented programming languages such as Smalltalk [3]. Here,the system starts its search for a method to be executed in response to a message received in the classof the receiver object.
The mechanism employed in most of the COP
systems including ours work informally as follows:
For each message received by an object the lookup
tries to find a matching method implementation
starting from the outermost layer of the current
layer composition. If such method is found, it isinvoked. With the exception of next, which proceeds to the next layers closer to the object to finda partial method with the same name and invokesthat implementation if found, all subsequent message sends (including the ones sent to the current
receiver object itself) cause the lookup mechanism
to start over from the outermost to the innermost
layer until a corresponding method implementation
is found or the end of the lookup chain is reached(which usually leads to a run-time error to be dealt
with by the system).
If employed as described above, our lookup leaves
us with a high risk of name captures of restricted
methods by other public methods with the same
name introduced by other layers that contribute to
the same object and composed after.
In our example in Listing 4 at <4>, if lookup
would follow the algorithm described above, thecall to m1 originating from m2 (L3.O1.m2) would
start from the outermost layer, here L4, and findits public partial implementation of m1 of O1 in L4(Figure 2). This might lead to surprises since theintent of declaring L3.O1.m2 to be restricted is tomake sure that, while callable from L3.O1.m1 (samelayer), it can neither be invoked directly from outside of L3 nor the invocation be taken over by outercode.
For Lfour we changed partial method lookup as
follows: (1) First check if the method to be called is
implemented in the same layer as the method fromwhich the message was sent. (2) If there is such amethod, continue execution with that method, otherwise (3) proceed with the lookup starting with theoutermost layer of the current composition.
This change was inspired again by the lookup of
Smalltalk—in this case in the context of messages
sent to super instead of self. As in many objectoriented languages, self (or this) and super referto the receiver of a message. The difference withmessages sent to super is that lookup does not startin the class of the receiver but in the superclass ofthe class that implements the method where the

L4
L3
L2
L1
f1

f2

f3

f4

m1 m2 m3 m4
O1
shared field (circle, empty)
local field (polygon, empty)
public method (circle, filled)
restricted method (polygon, filled)

field accesssame field
method call (regular)
method call (via next)

Fig. 2

Old Lookup.

f2

f4

L4
L3
L2
L1
f1

f3

m1 m2 m3 m4
O1
shared field (circle, empty)
local field (polygon, empty)
public method (circle, filled)
restricted method (polygon, filled)

field accesssame field
method call (regular)
method call (via next)

Fig. 3

New Lookup.

message send originates from, even if that particular method has been overridden in one or more
subclasses.
With that new lookup in place, name captures
like the one described above can be avoided (Figure 3).

5 Related Work
Scala’s traits [8] can be considered partial object
definitions without dynamic activation (that is, theapplication of a trait must be specified statically
before an instantiation). Even though a trait canoverride a public method in the base class, it can
only do so when this trait and the base class ex-tend the same interface that declares the method
to be overridden. This means that overriding public methods is possible only for cases known andplanned for in advance. In addition, a trait cannot
declare a restricted method when a base class declares a public method with the same name, even
if that name is not in their common interfaces.
An instance variable or state declaration in Scala
has two roles: creation of accessors and allocationof a store location. Since Scala treats accessors as
regular methods, they follow the visibility rules formethods. Consequently, it is not possible in Scalafor two modules to declare a shared instance variable without having a common interface in advance.
Ruby’s modules [2] can be considered partial object definition without dynamic activation. Definitions in a module included later always precede
the ones of modules included earlier; even if definitions are restricted. Surprisingly, restricted methods cannot be accessed even from the methods inthe same module.
Instance variables in Ruby (those accessed withthe @ mark before their names) are always shared
among modules.
There is no visibility control mechanism except explicitly declared accessor
methods.
Python’s multiple inheritance mechanism [11]can be regarded a composition of partial class definitions. Method visibility in Python is achieved bynaming conventions and renaming. When a classdeclares a method with a name beginning with double underscores, the name becomes unique to thatclass even if other classes used the same name including underscores. This makes name clashes between public and restricted methods impossible, atthe cost of inconvenience to the programmers.
Instance variables in Python are treated thesame as methods. Double underscores make thename unique to class, which effectively makes it restricted. Otherwise, instance variables are basicallyshared.

6 Discussion and Outlook
For explaining the application of public and restricted for methods and shared and local for fields,
we decided to always use these keywords everywhere in our code examples. We are aware of theverbosity such keywords introduce and so suggest
as the default to assume methods to be restricted

and fields to be local if not marked otherwise.
To avoid confusion with other established uses ofrestricted as an access modifier in languages likeJava [1] or C++ [10], we are reviewing alternative
names, but so far have not decided yet.
To reduce verbosity even more, we are considering the following replacements in future versions of
L: + for public, - for restricted, * for shared, and /for local.
Another simplification we are contemplating is
the use of shared (+) and local (-) not only for fields
but also for methods.
Furthermore, the mechanisms to control visibility need to be integrated with our proposal on layer
and object refinement [7].
To allow for partial definitions to provide an interface that cannot be layered any further once activated, we are investigating some form of final toallow for that at the level of methods, objects, andlayers.
After our rather informal investigation of possible language designs, we need to both work on both
L’s foundations [5] for clarifying some of our ideas
and on implementations to better understand theirapplicability.

Acknowledgments
This paper is based upon work supported in partby the Hasso Plattner Design Thinking Research
Program (HPDTRP).
References[ 1 ] Arnold, K., Gosling, J., and Holmes, D.:
The Java Programming Language, 4th Edition,
Addison-Wesley, 2005.
[ 2 ] Flanagan, D. and Matsumoto, Y.: The Ruby
Programming Language, O’Reilly, 2008.
[ 3 ] Goldberg, A. and Robson, D.: Smalltalk-80:
The Language and its Implementation, AddisonWesley, 1983.
[ 4 ] Hirschfeld, R., Costanza, P., and Nierstrasz, O.:
Context-oriented Programming., Journal of Object
Technology, Vol. 7, No. 3(2008), pp. 125–151.
[ 5 ] Hirschfeld, R., Igarashi, A., and Masuhara, H.:
ContextFJ: A Minimal Core Calculus for Contextoriented Programming, Proceedings of FOAL’11,
ACM, 2011.
[ 6 ] Hirschfeld, R., Masuhara, H., and Igarashi, A.:
L—Context-oriented Programming With Only Layers, Proceedings of COP’13, ACM, 2013.
[ 7 ] Hirschfeld, R., Masuhara, H., and Igarashi, A.:Layer and Object Refinement for Context-oriented
Programming in L, Proceedings of 95th IPSJ Workshop on Programming, IPSJ, 2013.
[ 8 ] Odersky, M.: The Scala Language Specification
Version 2.9, Technical report, Programming Methods Laboratory LAMP, EPFL, 2014.
[ 9 ] Steele Jr., G. L.(ed.): Common Lisp: The Lan-guage, 2nd Edition, Digital Press, 1990.
[10] Stroustrup, B.: The C++ Programming Language, 4th Edition, Addison-Wesley, 2013.
[11] van Rossum, G. and Drake Jr., F. L.: The
Python Language Reference, Technical report,
Python Software Foundation, 2014.