=Paper= {{Paper |id=Vol-3627/paper13 |storemode=property |title=Pharo: a Reflective Language - A First Systematic Analysis of Reflective APIs |pdfUrl=https://ceur-ws.org/Vol-3627/paper13.pdf |volume=Vol-3627 |authors=Iona Thomas,Stéphane Ducasse,Pablo Tesone,Guillermo Polito |dblpUrl=https://dblp.org/rec/conf/iwst/ThomasDTP23 }} ==Pharo: a Reflective Language - A First Systematic Analysis of Reflective APIs== https://ceur-ws.org/Vol-3627/paper13.pdf
                                Pharo: a Reflective Language – A First Systematic
                                Analysis of Reflective APIs
                                Iona Thomas1 , Stéphane Ducasse1 , Pablo Tesone1 and Guillermo Polito1
                                1
                                    Univ Lille, Inria, CNRS, Centrale Lille, UMR 9189 - CRIStAL.


                                                                         Abstract
                                                                         Reflective operations are powerful APIs that let developers build advanced tools or architecture. Re-
                                                                         flective operations are used for implementing tools and development environments (e.g., compiler, de-
                                                                         bugger, inspector) or language features (e.g., distributed systems, exception, proxy, aspect-oriented pro-
                                                                         gramming). In addition, languages are evolving, introducing better concepts, and revising practices and
                                                                         APIs. As such, since 2008 Pharo evolved and was built on Squeak which changed from the original
                                                                         Smalltalk reflective APIs. Pharo has one of the largest reflective feature sets ranging from structural
                                                                         reflection to on-demand stack reification. In addition, new metaobjects got integrated such as first-class
                                                                         instance variables. Finally, reflective facilities are mixed with the base-level API of objects and classes
                                                                         and reflective features are heavily used by the system tools.
                                                                             Getting an understanding of such API is, however, tedious when the API is large and evolved over
                                                                         a decade. There is a need for a deep analysis of current reflective APIs to understand their underlying
                                                                         use, potential dependencies, and whether some reflective features can be scoped and optional.
                                                                             In this article, we analyze the reflective operations used in Pharo 11. We classify the current reflective
                                                                         operations in different families. Also, we identify a set of issues raised by the use of reflective operations.
                                                                         Such an analysis of reflective operations in Pharo is important to support the revision of the reflective
                                                                         layer and its potential redesign.

                                                                         Keywords
                                                                         Reflection, Meta-object protocols




                                1. Introduction
                                Reflective operations are powerful APIs that let developers build advanced tools or architecture
                                that otherwise would have to be implemented in language implementation engines, require
                                complex infrastructure (such as code representation), or may simply not be possible. These
                                reflective features support the implementation of tools (e.g., compiler, debugger, inspectors),
                                frameworks and libraries (e.g., serialization, persistence, logging), and language infrastruc-
                                ture (e.g., exceptions, distributed systems, continuations, green threads). Such a set of tools
                                and frameworks are both used during the development and deployment of applications (See
                                Section 2).
                                   Giving too much power to developers can, however, also be a burden. Reflective features
                                defeat static analysis [1]. Reflective features may be used to violate encapsulation or execute
                                methods that should not be executed [2, 3, 4, 5].

                                IWST 2023: International Workshop on Smalltalk Technologies. Lyon, France; August 29th-31st, 2023
                                    iona.thomas@inria.fr (I. Thomas); stephane.ducasse@inria.fr (S. Ducasse); pablo.tesones@inria.fr
                                (P. Tesone); guillermo.polito@inria.fr (G. Polito)
                                                                       © 2023 Copyright for this paper by its authors. Use permitted under Creative Commons License Attribution 4.0 International (CC BY 4.0).
                                    CEUR
                                    Workshop
                                    Proceedings
                                                  http://ceur-ws.org
                                                  ISSN 1613-0073
                                                                       CEUR Workshop Proceedings (CEUR-WS.org)




CEUR
                  ceur-ws.org
Workshop      ISSN 1613-0073
Proceedings
   Pharo, for example, as a descendant of Smalltalk is the essence of a reflective language with
advanced reflective operations such as bulk pointer swapping [6], on-demand stack reification,
first-class resumable exceptions. In addition, in Smalltalk-80 and many of its derivative, reflective
facilities are mixed with the base-level API of objects and classes [7, 8, 9]. They are a key part
of the kernel of the language and libraries. Finally, since 2008 Pharo evolved as a language:
new concepts were added (slots, packages, pragmas...). There is a need for a deep analysis of
reflective features.
   In this paper, we present an analysis of existing reflective features in Pharo 11. We scope the
analysis to runtime reflection to focus on the core reflective features of the language and its
associated virtual machine. Pharo inherited Squeak and Smalltalk-80 reflective operations and
facilities and extended them over the years. Some reflective methods like Object»instVarAt: are
still present and used, some names changed and new reflective facilities appeared.
   The contributions of this article are:

    • an up-to-date and deep catalog of the reflective features and their home metaobjects in
      Pharo,
    • a classification and an analysis of such operations, and
    • a discussion of such reflective APIs and points to be considered to improve or design a
      new reflective runtime MOP for Pharo.

   These contributions are of key importance since they set the foundation for a redesign of the
reflective capabilities of Pharo for example to offer optional reflective capabilities and more
controlled ones in the context of a more secure and modular version of the language [10].

   The outline of the paper is as follows: first, we explain the need for reflective features in
Section 2. In Section 3 we highlight why we need a classification. Section 4 presents an overview
of the reflective APIs based on the classes supporting them and their interactions. In Section 5
we present with a high-level perspective the analysis of the runtime reflective APIs in Pharo
11. The Appendix A lists the detailed selectors. For each of the categories, we analyze the
capabilities it provides and how they are used in Pharo. Section 6 presents a high-level discussion
of considerations to be taken into account to improve such APIs. It also sketches some points
for the design of a future MOP for Pharo.


2. Reflective behavior: A need
      Reflection is the ability of a program to manipulate as data something representing
      the state of the program during its own execution. There are two aspects of such
      manipulation: introspection and intercession [...] [11]

   Reflective features in object-oriented languages are central to the development of advanced
behavior ranging from enhanced development tools to new paradigm implementation such as
Aspect-Oriented Programming [12]. In the middle of the 90s, reflection was heavily explored:
structural [13, 14], computational [15, 16], message-based [15, 17], compile-time [18] and partial
reflection [19, 20].
  Reflection is an important tool that enables many important features of modern languages [21].
For example, message-passing control is one of the cornerstones of a broad range of applications
and an important feature of reflective systems. Applications that use message-passing control
can be roughly sorted into three main categories.

       • The first category is application analysis and introspection that are based on tools that
         display interaction diagrams, class affinity graphs, and graphic traces [22, 23, 24, 25].
       • The second category is language extension. In such a case, message passing control allows
         one to define new features from within the language itself: Garf [26], Distributed Smalltalk
         [27], or [28] introduce object distribution in a transparent manner. Language features such
         as multiple inheritance [29], backtracking facilities [30], and instance-based programming
         [31, 32] have been introduced. Futures [33, 34] or atomic messages [35, 36] are also based
         on message-passing control capabilities.
       • The third category is the definition of new object models, introducing concurrent aspects
         such as active objects (Actalk [13]) and synchronization between asynchronous messages
         (Concurrent Smalltalk 1 [37]). Other work proposes new object reflective models such
         CodA that is a meta-object protocol that controls all the activities of distributed objects
         [36], meta helix [38] or submethod reflection using AST annotation [39, 21].

   More elaborate schemes have been proposed (e.g., partial behavioral reflection [19, 20]) that
provide a more flexible and fine-grained way to specify both the location being reflected and the
metaobject invoked. Context-oriented [40] or aspect-oriented programming implementations
are often based on reflection [41], AspectBoxes [42]. Contexts and context history on the level
of the pointcuts [43, 44]. Tanter [45] provides a good overview and discussion on the many
mechanisms for dynamically scoping crosscutting aspects.
   The importance and need for reflective features are also illustrated by the effort to offer them
in more static languages such as C++ [18], Ada [46], and Java [47, 48, 49, 19].
   Often virtual machine implementations impose restrictions on the changes that are possible
[50]. For example, even if Pharo is one of the most advanced reflective languages due to its
large spectrum of capabilities, some changes are not possible due to their inherent runtime cost.
Indeed, virtual machines often define the way the objects are represented in memory, and how
messages are handled.


3. The need for an up-to-date reflective feature classification
More than 25 years of evolution. Between 1996 and 2008, Squeak evolved from the original
Smalltalk reflective API with many contributions. In 2008 Pharo was born from Squeak. Pharo
on its own turn saw many different contributions. To give an idea of the activity in Pharo, since
2019 and the versioning of Pharo on Git Hub, Pharo has around 100 contributors (with up to 30
regular ones). As of the writing of this article, its commit history counting only since 2019 is
more 20 000 commits.

1
    Concurrent Smalltalk is based on the extension of the virtual machine and new byte-code definition. However, the
    synchronization of asynchronous messages uses the doesNotUnderstand: technique.
For an up-to-date analysis. Back in 1996, Rivard [8] proposed the first-classification of
Smalltalk reflective features. Such classification is, however, old, and includes aspects such as
the compiler which are orthogonal to runtime reflective features. In addition, it is based on
VisualWorks a proprietary Smalltalk that is not easily accessible nowadays. Finally, it does not
take into account traits [51, 52, 53, 54], first-class instance variables, and the introduction of new
tools using reflection such as the new inspector framework [55], reflectivity [21], object-centric
debugging [25], error handling infrastructure [56], and on the fly deprecated message rewritings
[57] to name a few. Callau et al., [58] studied the use of dynamic features of programming
language and use Pharo as a case study. Their study is limited and focuses on the use of a limited
set of elements. They do not embrace the full reflective APIs. Demers and Malenfant proposed
to compare reflective capabilities in logic, functional and object-oriented programming [59],
but it is not related to a concrete Pharo implementation.

Importance of the analysis. Deploying an application with unneeded reflective facilities
produces, however, potential safety issues: as reflective operations might be used to bypass
security measures or affect the stability of the executing application [10].
   Removing unneeded reflective operations requires, however, a complete understanding of
their usage and analysis to see if they can be separated from the language kernel and core
libraries. The challenge is how to improve the modularity and security of the language core,
without affecting the features used by tools, frameworks, and libraries. For example, serialization
libraries such as STON highly use reflective operations to serialize and deserialize objects;
removing those operations to improve the security of the application impedes the use of such a
library. This is why in future work, we will analyze more precisely the potential issues that
reflective operations may generate in productive applications and their impact on the safety
and security of the application. As a first step in that direction, there is a need for a deep and
up-to-date analysis that embraces the full spectrum of reflective features. This is what we
develop from Section 4 and this is why we list the complete API in Appendix A.


4. Metaobjects, implementing classes and their related APIs
Before giving an overview of the API, we briefly present the structural metamodel of Pharo.

4.1. Pharo structural meta model
A class is a central entity in the structural meta-model [9]. We briefly describe it, since a large
part of the API is currently associated with classes.

    • A class defines instance variables or slots. Since several versions of Pharo, slots (first-class
      instance variables) have been introduced and the fusion between instance variables and
      slots is under development. A class also defines class variables (a.k.a static variables) and
      it can also use shared pools which are a kind of collection of constants.
    • A class inherits from another class and can have multiple subclasses. Since a couple of
      versions, a class can be composed out of traits (kind of class fragments having their own
      methods and state).
                                                               inherits from

   ClassVariable
                                            has
                                                                                                                                          Pragma
                                                                                  has
  InstanceVariable                                      Class                                   CompiledMethod             has
                                                                                                                                          Selector
         Slot
                                            refers to                         composed of


                                          SharedPools                         Trait

Figure 1: The structural Pharo metamodel: Class aggregates variables, methods, constant manage-
ment (SharedPools) and method annotation (Pragma) and exposes related APIs.


    • A class contains methods. Methods have a selector and can be annotated using Pragma
      [60].


4.2. Overview of the APIs
Figure 2 shows the classes and the reflective APIs they offer that are available in Pharo 11.

                            arbitrary method/                                                   state acess
                                                                 identity
                           primitive execution
                                                                                                   memory iteration               Memory
       Slot                           contains                  Object
                                                                                                   editing pointers
                                                                                                    to an object
                               instance variable
                                     query                                                                                             Reference
                                defines              object adoption                            accessing instances
  Class Variable          class variable
                              query                                                              reflective message send
                                                      Class
                               contains
                                                                                                                                       reference to
   MethodDict            selector/methods
                              access                                                     lookup (messages/variables)
                                                                                                                                 Legend
                           and iteration
      contains                                                                   message not understood
                                                                                                                                     Metaobject
                                                   selectors             class creation                                              Implementation object
    Compiled
                                  method query                                                                                       Missing object
     Method
                                                        hierarchy navigation                                                         Group of reflective
                                                                                                                                     features related to ….
      contains                                                                          ClassBuilder/                                Reflective features’
                                                                                           Installer                                 relations with objects
                                                                                                                                     Relations between
    Compiled                                                                                                                         objects
     Block                                Runtime


                 becomes at runtime
                                                  Block              knows
                                                                                        Context         Environment        Message        MessageSend
                                                 Closure            its own



                                                                      has

                                                 Thread                       sender/receiver       context hierarchy
                                                                                   current method/arguments



Figure 2: metaobjects controlling the reflective APIs of Pharo.
MetaObjects. Grey boxes represent first-class objects. Object, Slot, Class, ClassVariable,
and CompiledMethod are structural metaobjects (see Section 6). CompiledMethod and Com-
piledBlock are potentially the way to access AST nodes and submethod reflective APIs. We
decided not to add such a dimension since submethod reflection is optional and can be seen as
compiled-time reflection [56].

Implementation objects. We put the MethodDict, CompiledBlock, and BlockClosure in a
white box because it is unclear whether we need or not a metaobject for them. Indeed in Pharo,
the method dictionary is rather simple and does not offer a reflective entry point per se. It is
more of an implementation object. Similarly, which BlockClosure can be introspected as an
object it is unclear that it represents a metaobject.

Perspective. The dashed package-like packages represent two aspects of the system: on
the one hand Memory which represents the fact that memory can be iterated with methods
such as nextInstance and on the other hand Runtime which represents execution aspect of the
system with Context (stack reification), Messages, Thread, and Environment (keeping class and
variable binding).
  Note that some APIs are not controlled by metaobjects per se. For example, the Reference
API is an API defined on Object as such every object could override it.

                      Object inspection                                                      Object modification
                      Acessing object        Acessing object                  State            Manipulating          Object’s class
 State inspection
                         identity                class                      modification       object identity          change


                  Class structural inspection                                            Class structural modification
      Class /            Selectors and                                                         Selectors /methods
                       methods inspection     Variable lookup              Class creation         modification
   Metaclass shift

                         SharedPools          Instance variable                Slot              SharedPools         Instance variable
   Slot inspection
                          inspection             inspection                 modification         modification          modification

                         Iterating and         Class variable                                     Hierarchy           Class variable
      Pragma           querying hierarchy       inspection                                       modification          modification

           Message sending and code execution                                   Memory scanning                     Method creation
    Reflective         Arbitrary method/                                    Memory           Instances of             Compiled
                                              Method lookup
   message send        primitive execution                                  scanning            a class             method creation

   Message send        Control message
    reification            passing


     Structural queries on Method                                 Stack                        Chasing and atomic pointer swapping
    Method slot        Method element                                       Stack                                      Bulk pointer
                                                    Context                                     Find pointers to
       uses              references                                       manipulation                                  swapping


Figure 3: Overview of the reflective APIs.
5. A classification and analysis of runtime reflective operations
Rivard classified reflective operations in the following categories: Meta-Operation (objects),
Structure (class), Semantics (compiler), Message Sending, and Control State (thread). The Seman-
tics part is just a description of the compilation process and involved classes - as such it is not
relevant for our analysis since it boils down to the fact that we can add a new compiled method
to a method dictionary. We complement and revisit this classification by adding References, and
Memory Scanning.
   We propose a detailed and systematic description of the APIs and runtime reflective behavior.
Our classification subsumes the one of Rivard. In addition, we distinguish APIs supporting
introspection from modification since the modification is more impacting in terms of state
encapsulation. We are aware that presenting lists in a systematic manner may be tedious for
the reader, this is why Appendix A describes systematically all the APIs. For each of the APIs
we briefly describe it, list its key methods (we often group similar ones), and comment on it
when appropriate. This is our future work to identify layers within such method lists. Finally,
note that the existence of an API is more important than the fact that we classify it under a
given heading. For example, an object can be asked to reflectively execute a method, this API is
a list with the other execution-oriented APIs and not directly in the object-centered API.

5.1. Object inspection
The first family of reflective operations is centered around object inspection. Rivard [8] de-
scribes these operations in the Meta-Operations category, but he groups together inspection
and modification. Our category is composed of three subcategories:

    • State inspection to support inspecting the values of the variables of an object.
    • Accessing object identity to support identification of an object.
    • Accessing object class to access the class of an object.

   In Pharo, all instance variables are private, meaning there are not readable and writable by
any other object. They are only being accessible through getter or setter methods. Developers
decide which instance variables are accessible by implementing or not methods to access them.
Pharo also includes class instance variables and shared variables, these work in the same fashion
as instance variables, and the analysis for instance variables is directly extensible to them. Using
the State inspection operations is breaking the encapsulation and bypasses the decisions of the
developer.
   Several methods exist on the class Object allowing access to the state of internal variables.
The main examples of this category are Object»instVarAt: and Object»instVarNamed:, which
read an instance variable of an object from respectively its index or name. These operations can
be combined with those that can be called on the class of the object (accessible with self class
which is part of Accessing object class subcategory) to better understand its internal structure
like Behavior»allInstVarNames.
Possibilities offered: The State inspection operations give a uniform API to inspect all the
instance variables of any object, including classes. They are particularly useful for designing
tools addressing crosscutting needs, like debugging, inspecting an object, serializing it...

Examples of uses:

    • Copying objects.
    • Serializing objects.
    • Printing objects.
    • Inspecting objects.
    • Checking references, for example, if an object points to another object.
    • Testing, including for some fields without getter methods.

Possibilities offered: The Accessing object identity supports checking the identify of an
object. basicIdentityHash is used for implementing identityHash variants, scanning for an
object in a method dictionary, and testing.

Examples of uses:

    • Scanning for objects in a collection
    • Implementing hash methods
    • Testing
    • Printing unique id for some objects (Process, Workers, AdditionalMethodState)

  This use raises the question of whether accessing object identity is a reflective operation and
not just part of the base-level object API in a language where references are ubiquitous.

Areas of improvements.

    • In Pharo base image, there is currently no provided solution for intercession on state read
      or write on a class or even on a specific object. This requires using additional libraries or
      implementing ad hoc solutions [61]. Such a tool relies heavily on reflection, and loading
      several tools at the same time might lead to bugs and instability as each may modify some
      parts of the Pharo language, its compilation and/or its execution.

5.2. Object modification
The second family of reflective operations is centered around object modification. It is the
counterpart of the first one and it is composed of State modification, Manipulating object identity,
and Object’s class change.

    • State modification to support modifying the values of the variables of an object.
    • Manipulating object identity to manipulate the identity of an object.
    • Object’s class change to change the class of an object.
Possibilities offered: The State modification operations allows one to bypass the encapsu-
lation for modifying variables, which allows one to set variables that cannot be changed via
base-level message passing. This is for example useful for deserialization. They allow one
to build tools that will modify objects. The Object’s class change operations allow one object
to transform in an instance of another class, which is particularly important in Pharo’s live
environment when a class has to be rebuilt following changes.

Examples of uses:

    • Copying objects.
    • Deserializing objects.
    • Modifying object on the fly in the debugger
    • Testing, including for some fields without setter.
    • To make proxy harder to detect
    • Updating instances of classes to migrate them to the new version of a class

  The Manipulating object identity category is mostly empty: One can only copy the hash of
an existing object as a side effect of reference swapping with #becomeForward:copyHash.

Areas of improvements. The API on object class change is weak and limited. The object
state can be lost in the process and some constraints (the two classes should have the same
format) make it difficult to change the actual class [62]. Access and modification methods can
potentially be overridden. Overriding could provide a way for a class to limit reflection on its
instances but at the cost of limiting the API.

5.3. Class structural inspection
This category groups reflective APIs on the query over the class structure and its constituents:
methods, variables (instance/class/slots). It is composed of the following APIs:

    • Class/metaclass shift to support the navigation from a class to its metaclass and the inverse,
    • Iterating and querying hierarchy to support hierarchy analysis with, in particular, testing
      for belonging to a specific class or class hierarchy (e.g., isKindOf:),
    • Instance variable inspection, Class variable inspection, Shared pool inspection, Slot inspec-
      tion all deal about variables. Slot inspection provides a higher level view compared to
      instance variables. Some slots can come from traits. Therefore there is a difference
      between localSlots (not coming from traits) and slots (taking into account that they may
      come from traits),
    • Selectors and method inspection supports if a class has (abstract) methods, an object re-
      sponds to a specific selector, and all the classes implementing a set of selectors.
    • Variable lookup supports the access to the binding of a variable.
    • Pragmas supports the query and iteration of class annotations (named pragmas in Pharo).
    • Class kind testing supports the testing of the state of a class from a system perspective
      (obsolete, anonymous...).
Possibilities offered: The structural class introspection is large. It is mainly used by tools. It
supports the interpretation of object inspection. Methods related to the class hierarchy support
navigation of the graph with messages such as superclass and allSubclasses. Methods related to
the method dictionary allow one to check all existing selectors and methods, as well as adding
and removing them. Methods related to instance variables allow one to list their names, remove
some of them and add new ones.
  Some methods such as isKindOf: or respondsTo: tend to be used at the domain level and
produce a suboptimal design.

Examples of uses:

    • Looking up selectors.
    • Accessing environment, class side information, check for slot/instance variable.
    • Querying about memory format (isImmediate object / isVariable / isFixed) or how much
      is used.
    • Querying if an object is an instance of an anonymous class, a specific class, or part of a
      specific class hierarchy.
    • Copying/Converting to create new instances.
    • For the Code Browser, the change recorder, and the code coverage calculation.
    • Printing objects and error messages.
    • Asserting that an object is of a given class in testing.
    • Checking for types in arithmetic operations/comparisons for collections.
    • Type checking to determine the visibility of graphical elements.
    • Safeguards raising errors if the type does not match what is expected.
    • Equality implementations.

   An example of the use of environment information is for the doOnlyOnce checking for a
value stored in the environment. We also would like to point out the existence of species and
respondsTo:. The first is meant to be overridden if necessary and allow classes to specify as
instances of which class their instances should be perceived. respondsTo: allows one to query if
an object understands a given selector. These two messages can be used to not put as much of a
burden on polymorphism.

Areas of improvements.        The following improvements would benefit the system.

    • There is spurious redundancy between isClassSide and isMeta. Such double methods
      should be corrected.
    • As a general remark, the question of the systematic application of the Law of Demeter
      should be discussed because it bloats the API. For example, messages such as selectSuper-
      classes: / selectSubclasses: do not seem to be necessary. In addition, withAllSuperAnd-
      Subclasses and includesBehavior: look superfluous.
    • We see the old protocol with cryptic names such as instSize to mean instanceVariableSize.
    • The duality of instance variables and slots is an artifact of the current evolution of Pharo.
      Nevertheless, this is important that in the future, instance variables get fully replaced by
      slots and that the corresponding reflective APIs get merged.
    • The duality of selectors versus methods should be evaluated. Since a method dictionary
      always has the selector of the method as a key, the API could favor selectors for most
      of the queries and only favor one access to compiled methods (via a method such as
      methodNamed: and one iterator).

5.4. Class structural modification
This category is the counterpart of the previous one. It is composed of the following APIs whose
objectives are clear: Hierarchy modification, Instance variable modification, Shared pool modi-
fication, Slot modification, Selector/Method modification, Old class creation, Fluid class creation,
and Anonymous class creation. It focuses on the modification of the structural relation a class
has with its constituents.

Possibilities offered: Structural modification operations allow the user to modify the current
structure/shape of classes. They include operations to add/remove subclasses, instance variables,
and class variables. We distinguish introspection and modification APIs because we want to
stress that modification is destructively modifying the executed system and that as such they
represent more powerful operations.
   In addition to the traditional class creation API (kept for backward compatibility) and the fluid
API, Pharo introduced the notion of anonymous classes (message newAnonymousSubclass) [2].
It helps to define instance-specific methods.
   We do not want to give too much importance to such classification. Appendixes present the
details.

One use case: Fluid class creation. The presented APIs are the basis for the dynamic
recompilation and runtime mutation of the system. There is one point that we want to stress:
the class creation.
  For a couple of years, Pharo is in the process of revisiting fundamentally the way classes are
created.

    • First, a new implementation of a class builder supports better instance migration logic.
    • Second, the creation of a class is separated from its effective installation in the system.
      This supports the creation of class definitions without side effects on the system. The
      messages classBuilder and classInstaller correspond to these two different actions.
    • Third, since Pharo 10 a fluid API has been introduced to control and limit the
      combinatorial an explosion of arguments in the traditional class creation API
      (subclass:instanceVariableNames:classVariableNames:poolDictionaries:category:)           as
      shown in the Appendix. Pharo limited the exposure to the users of infrequent parameters
      such as pool dictionaries. Still, the API was extremely large with the introduction of new
      kinds of subclasses such as ephemerons. Fluid class creation API has been designed to
      reduce drastically such large API and to not expose directly the API via a class object:
      indeed the definition of the class is done via messages configuring a class builder. The
      message « is creating a class builder object as shown in the following example.


Object << #Point
 slots: { #x . #y };
 tag: ’BasicObjects’;
 package: ’Kernel’
  Finally, in addition to the traditional class creation API (kept for backward compatibility) and
the fluid API, the API Anonymous class creation supports the creation of anonymous classes
(message newAnonymousSubclass) [2]. It helps to define instance-specific methods.

Areas of improvements.

    • The unification of Slots and variables should be continued to avoid duplication at the
      reflective APIs level.
    • About Selector/Method modification. The ’silently’ prefix raises the question of the man-
      agement of the notification of modification. Indeed, some tools need to get notified to
      react to new elements. Nevertheless, this duality suggests a layered API where low-level
      API elements are clearly identified.
    • The API Anonymous class creation can be packaged separately from the Fluid class creation.

5.5. Method creation
The API Compiled method creation is a low-level API that supports the definition of compiled
methods. Such an API is often ignored but it is central because it is responsible for the creation
of new compiled methods that can then be further installed and executed.

Possibilities offered: Compiled method creation offers the possibility to create a compiled
method and this even without the need for the compiler.

Examples of uses: This API supports the modularization of the system core such as making
the compiler optional in the system bootstrap. It is used by Hermes a binary binary code loader.
It is an important asset that supports the bootstrap of Pharo [63] and ensures that the compiler
can be loaded in a system not having a compiler to compile and install code.

Areas of improvements. Since the code for creating compiled methods is just the code of
the CompiledMethod class. It has not been explicitly designed to be a MOP API. Revisiting this
central API in the context of the Selector/Method modification and the interplay between the
two could lead to a stronger MOP.
5.6. Structural queries on methods
This category supports the cross-referencing between methods, instance variables, and classes.
It is composed of two APIs: Method slot uses (which supports the access to a variable and
modification of a variable) and Method element references (which is a low-level API querying
the internal implementation of methods).

Possibilities offered: These two APIs are central for all the cross-referencing and navigation
such as senders and which methods use a given variable. As such these APIs are really important
for the IDE and the tools.

Areas of improvements. The duality of selectors and methods (exemplified by Behav-
ior»whichMethodsReferTo: and Behavior»whichSelectorsReferTo:) could be again better han-
dled. We suggest not exposing the compiled method, since it is always possible to get the
selector of a method. It would lead to a more compact API.
   In addition Method slot uses looks like an optional API that can be packaged with the tools. A
unification between the two APIs would produce a more coherent API.

5.7. Message sending and code execution
This category of operations allows us to explicitly send messages, handle lookup failures or
execute compiled methods. It is composed of different APIs: Reflective message send (which
supports the lookup and execution of a method), Arbitrary method/primitive execution (which
supports the execution of methods without lookup), Method lookup (which simulate the method
lookup), Control message passing (which supports the possibility to control message sent), and
Message send reification (which provides ways to access message information).
   In Pharo, when sending a message to an object, the first step is to search the message selector
in the class hierarchy of the message’s receiver. This is the lookup. Once a compiled method is
found in the receiver’s class or one of its superclasses, the method is applied to the receiver.
When the lookup does not find any corresponding method, doesNotUnderstand: is sent to the
receiver with the message reified as an instance of MessageSend. This gives the opportunity
to the receiver to specialize message error. The APIs are central to bringing flexibility to
applications. In particular Reflective message send with its perform: methods is important for
pluggable UI logic.
   While the methods of the APIs Reflective message send do a method lookup, methods of the
Arbitrary method/primitive execution API allow us to execute directly a compiled method or a
primitive. The main methods in this category are ProtoObject»(withArgs:) executeMethod:,
CompiledMethod»valueWithReceiver:arguments: and ProtoObject»tryPrimitive:withArgs:

Possibilities offered: These operations allow us to explicitly send a message and handle
failure cases. The selector sent can be determined dynamically from an input, a string, or a
symbol. Run a specific primitive or version of a compiled method without needing to install a
method in the class hierarchy.
Examples of uses for perform: message.
    • Iterating over a list of messages and sending them. Sometimes coming from a list of
      pragmas, using methodSelector.
    • Sending a message received as a String or Symbol parameter.
    • In testing, including when compiling the method corresponding to the selector in the test.
    • Sometimes used when a non-reflective message-send could be used

   Many uses are related to user input and are found especially in user interfaces (e.g., executing
the result of a selection). They are also used for methods on reified messages, system settings,
class parser, and the Finder tool. One more example, not included in the Pharo 11 base image, is
the TeaPot library and how it handles HTTP requests.

Examples of uses for ’message not understood’. The method doesNotUnderstand: has
23 senders and 27 implementors in the base Pharo image. Actually, from these senders:
    • 2 come from the lookup implementation,
    • 13 from doesNotUnderstand: reimplementations,
    • 1 from the implementation of debugging to test if the current context is a DNU,
    • 1 corresponds to the inclusion of the selector in the specialObjectsArray,
    • and the 4 remaining from tests and mocks.

  Among doesNotUnderstand: implementors, many try to delegate using the message sentTo:
answering the message to another object before raising the exception. This has been used for
example to implement proxies [33].

Examples of uses for Arbitrary method/primitive execution.                Many uses are key to
supporting debugging and advanced tool facilities.
    • In Context class for Debugging and primitive simulation
    • UnifiedFFI/Fuel/OpalCompiler/Decompiler Tests and test coverage
    • Debugging support.
    • Evaluating (e.g., for RBNode, OpalCompiler)
    • Profiling
    • FFI methods

Areas of improvements.
    • Pharo offers two ways of representing a message via the class MessageSend and Mes-
      sage. This situation shows that the addition of concepts was not done carefully to avoid
      duplication. Pharo defines also a class Message (selector and arguments). This class is
      used to represent a message when an error occurs (doesNotUnderstand:). It supports
      the possibility to perform a lookup via the message sendTo: which is the counterpart
      of doesNotUnderstand:. The class MessageSend represents the concept of sending a
      message. It holds a receiver, a selector, and arguments. As such the class MessageSend
      offers corresponding getters and setters. Such a class is not used by the runtime and it
      is used only to represent and execute a message. For its execution, the class offers an
      API compatible with block closures: The messages value: and its variants allow one to
      execute a message. In addition, cull: and variants provide more flexibility in the number
      of arguments. We suggest merging MessageSend into Message since this last one is used
      to reify messages on error.
    • Having several ways to express the same behavior can be improved. Compiled-
      Method»valueWithReceiver:arguments:, ProtoObject»executeMethod:, and ProtoOb-
      ject»withArgs:executeMethod: are similar. We suggest that only methods on Compiled-
      Method s should be kept. The definition on ProtoObject would have the pernicious side
      effect to make domain developers that it is safe to use such messages.
    • The direct execution of a compiled method as offered by the Arbitrary method/primitive
      execution API is really dangerous because the system does not check that the executed
      method can be executed on the receiver. This is usually ensured by the lookup. Therefore
      while it makes sense to use methods of the Reflective message send API, we believe
      domain developers should not be exposed to the Arbitrary method/primitive execution
      API. In addition, this API should be packaged separately to clearly expose its nature.

   While the previous category allowed one to query the identity and type of an object, this one
is related to modifying those.

5.8. Chasing and atomic pointer swapping
The APIs in this category are Find pointers to and Bulk pointer swapping (supports the atomic
swapping to references). The first one is rarely mentioned but Pharo supports the possibility to
identify pointers to a given object (e.g., ProtoObject»pointersTo and ProtoObject»pointsTo:).

Possibilities offered: Find pointers to is really useful to build tools to identify a memory leak;
it is optional and its use is well-scoped.
    The second one Bulk pointer swapping is one of the hallmarks of Smalltalk reflective APIs.
Indeed in the original Smalltalk implementation, the use of an object table made the imple-
mentation of swapping references very cheap and used for example for growing collections.
However, such an old implementation did not scale for the modern amount of objects a runtime
contains. For modern implementations, become: conceptually requires scanning the complete
memory and is a costly operation. Modern implementations lowered the cost of this operation
by using forwarders at the VM level [6]. It should be noted that Pharo offers two semantics
for swapping: become: which symmetrically swaps the pointers and becomeForward: which is
one way. In addition, one cannot be used to express the other at the language level.

Examples of uses:

    • Memory leak analyzers.
    • Dynamically updating existing instances to new class shapes.
Areas of improvements. Such API while useful during development sessions should be
limited during deployment. A precise analysis of the use of Bulk pointer swapping should be
done to differentiate the places where it is mandatory from the places where it is a convenient
optimized solution. It should be noted that Find pointers to could be implemented on top of
a full memory scan APIs such as the ones presented in the next section. Similarly, a slower
version of Bulk pointer swapping could be possible.

5.9. Memory scanning
This category contains two API Memory scanning that support the traversal of the complete
heap and Instances of a class that gives access to all the instances of a class.

Possibilities offered: This API is usually not mentioned in the literature but it is at the core
of live programming [64]. The method nextObject and nextInstance are key to building other
functionalities such as allInstances.

Examples of uses: The main use is the class build that needs to access all the instances of a
given class to reflect potential class shape changes. Other uses such as collecting all instances
of a class are more anecdotal and reflect the lack of an explicit registration mechanism in the
domain.

Areas of improvements. Understanding whether such a reflective API can be optional and
only be loaded on demand would be a step to build a more compact, tidier, and secure reflective
MetaObject protocol.

5.10. Stack Manipulation
This category groups together all APIs that support traversing and modifying the execution
stack. These APIs are accessible from two main entry points: the Process class that provides
access to the existing processes and their suspended execution stack, and the thisContext
pseudo-variable that provides access to the current method execution. Both these entry points
provide instances of Context that represent a method execution and that represent the execution
stack as a linked list.

Possibilities offered: The Stack Manipulation APIs provide on the one hand low-level access
to the call stack (e.g., sender, programCounter), context meta-data (e.g., method), and context
operand stack (e.g., push:, pop and at:), and on the other hand support for continuations built
on top of the previous APIs (e.g., return:, resume:).

Examples of uses: These APIs make possible essential features in the programming language
and environment such as exceptions, bytecode simulation, and debugging.
Areas of improvements. Stack manipulation support for stack modification and intercession
is, at the moment of this writing, limited. A single class Context is allowed, and its instances are
reified on-demand by the execution engine by the Virtual Machine implementation [65]. This
means that the APIs described above cannot be refined in subclasses to modify the behavior of
method execution. Currently, such fine-grained intercession is achieved by bytecode rewriting
using frameworks such as reflectivity [21].
    Additionally, the fact that essential language features such as exceptions are built on top of
stack manipulation support turns this support mandatory. Optional stack manipulation requires
a major redesign such as a re-implementation of such essential features on the Virtual Machine,
or at the extreme considering exceptions as optional reflective features too.


6. Discussions
As we have seen in the previous sections, if reflective operations are extremely powerful and
useful to implement tools to navigate Pharo’s live environment [66], they are also impeding
application safety in multiple ways. Analyzing and designing a new modular MOP is a clear
challenge. In this section we discuss various aspects ranging from the analysis we presented to
the consideration to be taken into account.

6.1. General concerns
About dual entities. On several occasions, the MOP proposes a kind of duplicated APIs: one
for selectors and the other for compiled methods, or one for a variable and its name. Having
only one API based on the object is not good because it would force the developer to have an
object while it may not be possible. It means that using a name is a good approach. In particular,
since when one has an object (compiled method, slot) we can get its name. We suggest reducing
the API spectrum by not proposing two APIs but favoring one based on the name for query or
access, and for the modification, the developer can query first based on name to access an object
and then perform the corresponding operation. In that regards the question of the application
of the Law of Demeter should be evaluated since it tends to produce larger APIs.

Absence of layers. On several occasions we see the need to clearly identify the level of
API. Indeed some methods require mere index (instVarAt:) while some others require names
(instVarName:). While the first one is needed, we suggest (1) a clear naming convention that
helps understand the level of the functionality, (2) a better naming (methods named instSize
that returns the number of instance variable feels outdated in a modern language. Finally, some
APIs are large due to the fact that basic functionality is augmented with helper behavior built
on top for such basic functionality. While this is a good practice to promote code reuse and
offer developers stronger APIs, we suggest to layer such APIs and making sure that high-level
APIs are optional with clearly identified users.

About metaobject Protocol and piecemeal growth. In Smalltalk, reflection is exposed as
methods of objects that can modify the internals of the system and the causal connection makes
sure that the modifications get in effect. We can see this approach as an organic one and from
this perspective we can say that the metaobject Protocol of Smalltalk has been less designed
than the one of CLOS [67].
   We suggest that the design of a new MOP should consider how certain objects represent
customization points and avoid piecemeal and accidental MOP growth. For example, in CLOS it
is possible to specify at the metaclass level, the class of the executed method. The Method class
is then a natural metaobject exposing a method that can be specialized to for example count
the number of execution of the methods. In Pharo, the hook to specify the class of a method
is not clear. More important, when a method is executed there is no identified method that is
called prior to the method execution. Frameworks such as Method Proxy, MethodWrappers [24]
build such functionality using VM hooks such the possibility to place any object in a system
dictionary and that such an object receives the message run:with:in:.
   A MOP may decide to expose customization points as dedicated objects and not necessarily
objects that are currently been executed [36]. For example in CodA, different lifetime aspects
of objects (message send, message received, state access, execution,...) are reified via specific
metaobjects.

Execution-Time Reflection. In our analysis, we have centered on the reflective API during
the execution time. We analyzed the operations that are able to be done during the execution
of our code. In this sense, we have left outside operations performed outside the execution of
the code. Operations such as static code analysis and rewriting, memory dump inspection and
modification, refactoring, and on-load code rewriting or instrumentation are not performed
during execution time. Those operations are outside our definition of reflective operations.

Compiler. In contrast to Rivard [8] who considers the compiler as part of the reflective API
of the system, in our analysis we keep it out. We have taken this decision as the reflective API
provides ways of creating and installing methods. In Pharo reflective API a method is created
from its bytecode, literals, and header. The complexity of generating such a set of bytecode,
literals, and header for the method is outside the reflective API. The compiler has as input
the source code of the method. Through a series of complex transformations (such as parsing,
AST building, AST rewriting, AST optimizations, Intermediate Representation Building, and
bytecode generation) the compiler generates the bytecode, literals, and headers. A compiler
is just one possible source of these elements. For example, in Pharo, we have a binary code
loader that generates and install methods. This binary code loader is used without the compiler
to load code during the bootstrap process of the image. The compiler and the binary code
loader both use the same reflective API, that allows them to create and install new methods in
the running environment. Moreover, it is possible to have more alternative tools to generate
methods profiting Pharo reflective API.

Package Loading / Unloading Missing. The existing reflective API does not present a clear
metamodel to handle the concept of Packages. Even though this concept is used outside the
execution of code. It is a key element in the metamodel of Pharo. It is used to load, unload and
version classes, methods, and extensions existing in Pharo. Moreover, it is the key element to
support method extensions.
   A clear reflective API is required to handle the loading, unloading, versioning, and modifica-
tion of packages in Pharo. Also, clear modeling of the package allows for additional points of
extension to the metamodel and the ability to improve existing tools (e.g., scoping extensions,
dependencies).
   We have left outside of this paper the analysis of the features and a possible design of such
Package API, but we recognize the importance of such reflective API.

Architecture for notification. In our analysis, we have found that there is no clear API for
handling the notifications of changes. Tools working on the metamodel of Pharo require a
good integration to be notified of changes. For example, a Code Browser requires a clear way
of getting notifications when a new method or class is added to the system. Also, there are
scenarios where the tools modify the system but this modification should not be notified. For
example, when instrumenting a method, if the original method is replaced there is no need that
the Code Browser to be notified.
   A clear notification API should guarantee that the tools and libraries are able to scope the
notifications they want to produce and consume.
   An extensive analysis of this notification architecture is outside the scope of this paper,
however, we realize that such a notification architecture is required.

About definition and method reification. In early versions of Squeak, a compiled method
did not know its class or its selector. It was then expensive to ask a compiled for its selector
since it required scanning all the methods installed in a class. Over the years compiled methods
saw their API and representation improved. At the same time, there is a need to be able to
represent methods that are not installed in a class, for example, to browse multiple versions of a
method or perform branch analysis [68]. In this scenario, there is a need to represent a method
with a source code that is not the one of the currently installed compiled method. Similarly,
several meta-models such as Ring and Ring2 have been designed to support the analysis of code
not loaded in an image (browsing, crossreferencing, remote browser...). There is a need to have
method definitions as well as compiled methods. This raises the question of whether the tools
should not manipulate method definitions and not compiled methods. Such method definitions
could be connected to a compiled method when the compiled method is actually installed in the
system. From a reflective API, compiled methods could be more executable objects and expose
only information related to their execution and for all the other needs the tools could request
the associated method definition. By making sure that the tools and reflective API always go
from a method definition to the compiled method, we could restrain the compiled method API.
Such architecture, however, should be built and validated because in an image for development,
it would double the number of objects representing methods or special caches should be done
to support method cross-referencing.
6.2. Mirror architecture
At the language level, Mirrors [69, 70] aims for stratification of meta-level facilities and gives
access to reflective capability based on a reference to a mirror factory. Mirrors were implemented
in several languages, for example, Self [70], StrongTalk [71] and Newspeak [72]. MirrorPrimi-
tives offer a mirror implementation in Pharo. However, given that MirrorPrimitives is a class, it
is registered in the global environment, making access to this facility possible from anywhere.
This defeats the idea of restricting access to reflection through the use of references to mirror
factories. In [73] the authors advocate that mirrors should also address structural decomposition.
Mirrors should not only be the entry points of reflective behavior but also be the storage entities
of meta-information. Pharo offers a first implementation of Mirrors (with APIs to read/write
fields, check the class and the identity of an object, and execution of a method with another
receiver) but it is not systematically used and adds another mechanism.

6.3. Controlling reflection
Optional reflective features. Our analysis identified some APIs of reflective behavior that
are optional. This is important and we suggest continuing this effort with the objective to
obtain a minimal core with modular and optional extensions. This is particularly interesting
because the expectations of a development session should be automatically the same as the one
of a deployed application. Of course, this is handy to be able to do fancy reflective actions on
deployed applications to debug them, but this is important that MOP designers consider other
scenarios such as more constrained application deployment setup.

Controlling reflection. N. Papoulias et al., [74] proposes a model for the reification of the
control of reflection. Indeed controlling the run-time behavior of reflective facilities introduces
several challenges, such as computational overhead, the possibility of meta-recursion, and
an unclean separation of concerns between the base and the meta-levels. They present five
dimensions of meta-level control from related literature that try to remedy these problems.
These dimensions are namely: temporal and spatial control, placement control, level control,
and identity control. Making a reflective feature optional and identifying its dependencies is
one way to control it.

External reflection. Another approach is to separate completely the implementation of the
language from the reflective API. Lorenz proposes a pluggable reflection [75], in which the
reflective API should be external to the language. This solution allows tools using reflectivity
to process information coming from different sources (source code, live environment) as long
as the same external API is available. This solution aims at flexibility and interoperability.
While this might seem to not fit the model of the Smalltalk/Pharo live environment with all its
embedded tools, having such an external reflective API could remote debugging while removing
the reflectivity inside the image.
7. Conclusion
This article acknowledged that the runtime reflection offered by Pharo was in need of a deep and
systematic analysis after the evolution of Squeak and the subsequent evolution of Pharo since
2008. The analysis of Rivard [8] while interesting is simply dated. Indeed Pharo metaobjects
evolved and got [51, 52, 53, 54], first-class instance variables and the introduction of new tools
using reflection such as the new inspector framework [55], reflectivity [21], object-centric
debugging [25], error handling infrastructure [56] and on the fly deprecated message rewritings
[57]. This is not counting the full rewrite of the compiler.
   In this article, we present a new systematic analysis of the reflective APIs unrevealing some
often undocumented aspects such as memory scanning or method installation. In addition, the
analysis proposes some potential improvements to the existing MOP. The discussion raises the
bar of the analysis because MOP designers should challenge the monolithic perception that a
MOP should be omnipotent and cover all the aspects all the time. We believe that a faceted
MOP where on-demand reflective operations can be made available is the way to create a more
versatile system that has different varieties of flavors depending on the kind of applications
that one wants to deploy and their companion security properties.


References
 [1] B. Livshits, J. Whaley, M. S. Lam, Reflection analysis for java, in: Proceedings of Asian
     Symposium on Programming Languages and Systems, 2005.
 [2] S. Ducasse, Evaluating message passing control techniques in Smalltalk, Journal of
     Object-Oriented Programming (JOOP) 12 (1999) 39–44.
 [3] G. Richards, C. Hammer, B. Burg, J. Vitek, The eval that men do: A large-scale study of
     the use of eval in javascript applications, in: Proceedings of Ecoop 2011, 2011.
 [4] M. S. Miller, M. Samuel, B. Laurie, I. Awad, M. Stay, Caja Safe active content in sanitized
     JavaScript, Technical Report, Google Inc., 2008. URL: http://google-caja.googlecode.com/files/
     caja-spec-2008-06-07.pdf .
 [5] G. C. Hunt, J. R. Larus, Singularity: rethinking the software stack, SIGOPS Oper. Syst. Rev.
     41 (2007) 37–49. doi:10.1145/1243418.1243424.
 [6] E. Miranda, C. Béra, A partial read barrier for efficient support of live object-oriented
     programming, in: International Symposium on Memory Management (ISMM ’15), Port-
     land, United States, 2015, pp. 93–104. URL: https://hal.inria.fr/hal-01152610. doi:10.1145/
     2754169.2754186.
 [7] A. Goldberg, D. Robson, Smalltalk-80: The Language, Addison Wesley, 1989.
 [8] F. Rivard, Smalltalk: a reflective language, in: Proceedings of REFLECTION’96, 1996, pp.
     21–38.
 [9] A. P. Black, S. Ducasse, O. Nierstrasz, D. Pollet, D. Cassou, M. Denker, Pharo by Example,
     Square Bracket Associates, Kehrsatz, Switzerland, 2009. URL: http://books.pharo.org.
[10] C. Teruel, S. Ducasse, D. Cassou, M. Denker, Access control to reflection with object
     ownership, in: Dynamic Languages Symposium (DLS’2015), 2015. URL: https://hal.inria.fr/
     hal-01217041. doi:10.1145/2816707.2816721.
[11] D. G. Bobrow, R. P. Gabriel, J. White, CLOS in context — the shape of the design, in:
     A. Paepcke (Ed.), Object-Oriented Programming: the CLOS perspective, MIT Press, 1993,
     pp. 29–61.
[12] G. Kiczales, J. Lamping, A. Mendhekar, C. Maeda, C. Lopes, J.-M. Loingtier, J. Irwin,
     Aspect-Oriented Programming, in: M. Aksit, S. Matsuoka (Eds.), European Conference on
     Object-Oriented Programming (ECOOP’97), Springer-Verlag, 1997, pp. 220–242. doi:10.
     1007/BFb0053381.
[13] J.-P. Briot, P. Cointe, Programming with explicit metaclasses in Smalltalk-80, in: Proceed-
     ings OOPSLA ’89, ACM SIGPLAN Notices, volume 24, 1989, pp. 419–432.
[14] N. Bouraqadi, T. Ledoux, F. Rivard, Safe metaclass programming, in: Proceedings OOPSLA
     ’98, 1998, pp. 84–96.
[15] J. Ferber, Computational reflection in class-based object-oriented languages, in: Proceed-
     ings OOPSLA ’89, ACM SIGPLAN Notices, volume 24, 1989, pp. 317–326.
[16] J. McAffer, Meta-level programming with coda, in: W. Olthoff (Ed.), Proceedings ECOOP
     ’95, volume 952 of LNCS, Springer-Verlag, Aarhus, Denmark, 1995, pp. 190–214.
[17] W. Cazzola, Evaluation of object-oriented reflective models, in: In Proceedings of ECOOP
     Workshop on Reflective Object-Oriented Programming and Systems (EWROOPS 98),
     in 12th European Conference on Object-Oriented Programming (ECOOP 98), Brussels,
     Belgium, on 20th-24th, 1998, pp. 3–540.
[18] S. Chiba, A metaobject protocol for C++, in: Proceedings of OOPSLA ’95, volume 30 of
     ACM SIGPLAN Notices, 1995, pp. 285–299.
[19] É. Tanter, J. Noyé, D. Caromel, P. Cointe, Partial behavioral reflection: Spatial and temporal
     selection of reification, in: Proceedings of OOPSLA ’03, ACM SIGPLAN Notices, 2003, pp.
     27–46. URL: http://www.dcc.uchile.cl/~etanter/research/publi/2003/tanter-oopsla03.pdf . doi:10.
     1145/949305.949309.
[20] D. Röthlisberger, M. Denker, É. Tanter, Unanticipated partial behavioral reflection: Adapt-
     ing applications at runtime, Journal of Computer Languages, Systems and Structures 34
     (2008) 46–65. doi:10.1016/j.cl.2007.05.001.
[21] S. Costiou, V. Aranega, M. Denker, Sub-method, partial behavioral reflection with reflectiv-
     ity: Looking back on 10 years of use, The Art, Science, and Engineering of Programming 4
     (2020). doi:10.22152/programming-journal.org/2020/4/5.
[22] J. H. Heinz-Dieter Bocker, What tracers are made of, in: Proceedings of OOPSLA/ECOOP
     ’90, 1990, pp. 89–99.
[23] F. Pachet, F. Wolinski, S. Giroux, Spying as an Object-Oriented Programming Paradigm,
     in: Proceedings of TOOLS EUROPE ’93, 1993, pp. 109–118.
[24] J. Brant, B. Foote, R. Johnson, D. Roberts, Wrappers to the rescue, in: Proceedings
     European Conference on Object Oriented Programming (ECOOP’98), volume 1445 of
     LNCS, Springer-Verlag, 1998, pp. 396–417.
[25] S. Costiou, M. Kerboeuf, C. Toullec, A. Plantec, S. Ducasse, Object miners: Acquire, capture
     and replay objects to track elusive bugs, Journal of Object Technology 19 (2020) 1:1–32.
     URL: http://www.jot.fm/contents/issue_2020_01/article1.html. doi:10.5381/jot.2020.19.
     1.a1.
[26] J. Garbus, D. Salomon, B. Tretter, SYBASE DBA: Survival Guide, Sams Publishing, 1995.
[27] J. K. Bennett, The design and implementation of distributed Smalltalk, in: Conference pro-
     ceedings on Object-oriented programming systems, languages and applications, OOPSLA
     ’87, ACM, New York, NY, USA, 1987, pp. 318–330. URL: http://doi.acm.org/10.1145/38765.
     38836. doi:10.1145/38765.38836.
[28] P. L. McCullough, Transparent forwarding: First steps, in: Proceedings OOPSLA ’87, ACM
     SIGPLAN Notices, volume 22, 1987, pp. 331–341.
[29] A. H. Borning, D. H. Ingalls, Multiple inheritance in Smalltalk-80, in: Proceedings at the
     National Conference on AI, Pittsburgh, PA, 1982, pp. 234–237.
[30] W. R. LaLonde, M. V. Gulik, Building a backtracking facility in Smalltalk without kernel
     support, in: Proceedings OOPSLA ’88, ACM SIGPLAN Notices, volume 23, 1988, pp.
     105–122. doi:10.1145/62083.62094.
[31] K. Beck, Instance specific behavior: How and Why, Smalltalk Report 2(7) (1993).
[32] K. Beck, Instance specific behavior: Digitalk implementation and the deep meaning of it
     all, Smalltalk Report 2(7) (1993).
[33] G. A. Pascoe, Encapsulators: A new software paradigm in Smalltalk-80, in: Proceedings
     OOPSLA ’86, ACM SIGPLAN Notices, volume 21, 1986, pp. 341–346.
[34] W. LaLonde, J. Pugh, Inside Smalltalk: Volume 1, Prentice Hall, 1990.
[35] B. Foote, R. E. Johnson, Reflective facilities in Smalltalk-80, in: Proceedings OOPSLA ’89,
     ACM SIGPLAN Notices, volume 24, 1989, pp. 327–336.
[36] J. McAffer, A Meta-level Architecture for Prototyping Object Systems, Ph.D. thesis, Uni-
     versity of Tokyo, 1995. URL: http://www.laputan.org/pub/mcaffer/mcaffer-phd.pdf .
[37] Y. Yokote, M. Tokoro, Experience and evolution of ConcurrentSmalltalk, in: Proceedings
     OOPSLA ’87, volume 22, 1987, pp. 406–415.
[38] S. Chiba, G. Kiczales, J. Lamping, Avoiding confusion in metacircularity: The meta-helix, in:
     K. Futatsugi, S. Matsuoka (Eds.), Proceedings of ISOTAS ’96, volume 1049, Springer, 1996,
     pp. 157–172. URL: http://www2.parc.com/csl/groups/sda/publications/papers/Chiba-ISOTAS96/
     for-web.pdf . doi:10.1007/3-540-60954-7_49.
[39] M. Denker, S. Ducasse, A. Lienhard, P. Marschall, Sub-method reflection, in: Journal of
     Object Technology, Special Issue. Proceedings of TOOLS Europe 2007, volume 6/9, ETH,
     2007, pp. 231–251. doi:10.5381/jot.2007.6.9.a14.
[40] P. Costanza, R. Hirschfeld, Language constructs for context-oriented programming: An
     overview of ContextL, in: Proceedings of the Dynamic Languages Symposium (DLS’05),
     ACM, New York, NY, USA, 2005, pp. 1–10. URL: http://p-cos.net/documents/contextl-overview.
     pdf . doi:10.1145/1146841.1146842.
[41] N. Bouraqadi, A. Seriai, G. Leblanc, Towards unified aspect-oriented programming, in:
     Proceedings of 13th International Smalltalk Conference (ISC’05), 2005.
[42] A. Bergel, R. Hirschfeld, S. Clarke, P. Costanza, Aspectboxes — controlling the visibility of
     aspects, in: M. H. Joaquim Filipe, Boris Shiskov (Ed.), In Proceedings of the International
     Conference on Software and Data Technologies (ICSOFT 2006), 2006, pp. 29–38. URL:
     http://www.cs.tcd.ie/Alexandre.Bergel/download/papers/Berg06c-Aspectboxes.pdf .
[43] C. Herzeel, K. Gybels, P. Costanza, A temporal logic language for context awareness in
     pointcuts, in: Proceeding of the Workshop on Revival of Dynamic Languages, 2006.
[44] C. Herzeel, K. Gybels, P. Costanza, T. D’Hondt, Modularizing crosscuts in an e-commerce
     application in lisp using halo, in: Proceeding of the International Lisp Conference (ILC)
     2007, 2007.
[45] É. Tanter, On dynamically-scoped crosscutting mechanisms, in: G. Kniesel (Ed.), Proceed-
     ings of the European Workshop on Aspects in Software (EWAS 2006), Technical Report
     IAI-TR-2006-6, University of Bonn, Germany, Twente, The Netherlands, 2006, pp. 18–22.
[46] P. Rogers, A. Wellings, Openada: Compile-time reflection for ada 95, in: Reliable Software
     Technologies - Ada Europe, volume 3063 of LNCS, Springer, 2004.
[47] I. Welch, R. J. Stroud, Kava — using bytecode rewriting to add behavioural reflection
     to Java, in: Proceedings of the 6th USENIX Conference on Object-Oriented Technology
     (COOTS’2001), San Antonio, Texas, USA, 2001, pp. 119–130.
[48] B. Redmond, V. Cahill, Iguana/J: Towards a dynamic and efficient reflective architecture
     for java, in: Proceedings of European Conference on Object-Oriented Programming,
     workshop on Reflection and Meta-Level Architectures, 2000.
[49] B. Redmond, V. Cahill, Supporting unanticipated dynamic adaptation of application
     behaviour, in: Proceedings of European Conference on Object-Oriented Programming,
     volume 2374, Springer-Verlag, 2002, pp. 205–230.
[50] G. Chari, D. Garbervetsky, S. Marr, S. Ducasse, Fully reflective execution environments:
     Virtual machines for more flexible software, Transaction on Software Engineering 45
     (2018) 858–876. doi:10.1109/TSE.2018.2812715.
[51] S. Ducasse, N. Schärli, R. Wuyts, Uniform and safe metaclass composition, Journal of
     Computer Languages, Systems and Structures 31 (2005) 143–164. doi:10.1016/j.cl.
     2004.11.003.
[52] S. Ducasse, O. Nierstrasz, N. Schärli, R. Wuyts, A. P. Black, Traits: A mechanism for
     fine-grained reuse, ACM Transactions on Programming Languages and Systems (TOPLAS)
     28 (2006) 331–388. doi:10.1145/1119479.1119483.
[53] P. Tesone, S. Ducasse, G. Polito, L. Fabresse, N. Bouraqadi, A new modular implementation
     for stateful traits, Science of Computer Programming 195 (2020) 1–37. doi:10.1016/j.
     scico.2020.102470.
[54] P. Tesone, G. Polito, L. Fabresse, N. Bouraqadi, S. Ducasse, Preserving instance state during
     refactorings in live environments, Future Generation Computer Systems 110 (2020) 1–17.
     doi:10.1016/j.future.2020.04.010.
[55] A. Chiş, O. Nierstrasz, A. Syrel, T. Gîrba, The moldable inspector, in: 2015 ACM Inter-
     national Symposium on New Ideas, New Paradigms, and Reflections on Programming
     and Software (Onward!), Onward! 2015, ACM, New York, NY, USA, 2015, pp. 44–60. URL:
     http://doi.acm.org/10.1145/2814228.2814234. doi:10.1145/2814228.2814234.
[56] S. Costiou, T. Dupriez, D. Pollet, Handling Error-Handling Errors: dealing with debugger
     bugs in Pharo, in: International Workshop on Smalltalk Technologies - IWST 2020, 2020.
     URL: https://hal.inria.fr/hal-02992644.
[57] S. Ducasse, G. Polito, O. Zaitsev, M. Denker, P. Tesone, Deprewriter: On the fly rewriting
     method deprecations, Journal of Object Technologies (JOT) 21 (2022). doi:10.5381/jot.
     2022.21.1.a1.
[58] O. Callau, R. Robbes, D. Rothlisberger, E. Tanter, How developers use the dynamic features
     of programming languages: the case of smalltalk, in: Mining Software Repositories
     International Conference (MSR’11), 2011.
[59] F.-N. Demers, J. Malenfant, Reflection in logic, functional and object-oriented program-
     ming: a short comparative study, in: IJCAI’95 Workshop on Reflection and Metalevel
     Architectures and their Applications in AI, 1995.
[60] S. Ducasse, E. Miranda, A. Plantec, Pragmas: Literal messages as powerful method
     annotations, in: International Workshop on Smalltalk Technologies IWST’16, Prague,
     Czech Republic, 2016. doi:10.1145/2991041.2991050.
[61] S. Costiou, V. Aranega, M. Denker, Reflection as a tool to debug objects, in: International
     Conference on Software Language Engineering (SLE), 2022, pp. 55–60.
[62] F. Rivard, Évolution du comportement des objets dans les langages à classes réflexifs, Ph.D.
     thesis, Ecole des Mines de Nantes, Université de Nantes, France, 1997.
[63] G. Polito, Virtualization Support for Application Runtime Specialization and Extension,
     Ph.D. thesis, University Lille 1 - Sciences et Technologies - France, 2015.
[64] P. Tesone, Dynamic Software Update for Production and Live Programming Environments,
     Ph.D. thesis, Université de Lille - IMT Lille Douai, 2018. URL: https://hal.inria.fr/view/index/
     docid/2025442.
[65] E. Miranda, Context management in visualworks 5i, 1999.
[66] J. Kubelka, R. Robbes, A. Bergel, The road to live programming: Insights from the practice,
     in: Proceedings of the 40th International Conference on Software Engineering, ICSE ’18,
     ACM, New York, NY, USA, 2018, pp. 1090–1101. URL: http://doi.acm.org/10.1145/3180155.
     3180200. doi:10.1145/3180155.3180200.
[67] G. Kiczales, L. Rodriguez, Efficient method dispatch in PCL, in: Proceedings of ACM
     conference on Lisp and Functional Programming, Nice, 1990, pp. 99–105.
[68] V. Uquillas Gómez, S. Ducasse, T. D’Hondt, Meta-models and infrastructure for smalltalk
     omnipresent history, in: Smalltalks’2010, 2010.
[69] G. Bracha, D. Ungar, Mirrors: design principles for meta-level facilities of object-
     oriented programming languages, in: Proceedings of the International Conference
     on Object-Oriented Programming, Systems, Languages, and Applications (OOPSLA’04),
     ACM SIGPLAN Notices, ACM Press, New York, NY, USA, 2004, pp. 331–344. URL:
     http://bracha.org/mirrors.pdf .
[70] D. Ungar, R. B. Smith, Self: The Power of Simplicity, in: Proceedings OOPSLA ’87, ACM
     SIGPLAN Notices, volume 22, 1987, pp. 227–242. doi:10.1145/38765.38828.
[71] L. Bak, G. Bracha, S. Grarup, R. Griesemer, D. Griswold, U. Hölzle, Mixins in Strongtalk,
     in: ECOOP ’02 Workshop on Inheritance, 2002.
[72] P. Tesone, G. Polito, L. Fabresse, N. Bouraqadi, S. Ducasse, Instance migration in dynamic
     software update, in: Meta’16, Amsterdam, Netherlands, 2016. URL: https://hal.inria.fr/
     hal-01611600.
[73] N. Papoulias, N. Bouraqadi, M. Denker, S. Ducasse, L. Fabresse, Towards structural
     decomposition of reflection with mirrors, in: Proceedings of International Workshop on
     Smalltalk Technologies (IWST’11), Edingburgh, United Kingdom, 2011.
[74] N. Papoulias, M. Denker, S. Ducasse, L. Fabresse, Reifying the reflectogram, in: 30th
     ACM/SIGAPP Symposium On Applied Computing, Salamanca, Spain, 2015. doi:10.1145/
     2695664.2695883.
[75] D. H. Lorenz, J. Vlissides, Pluggable reflection: decoupling meta-interface and imple-
     mentation, in: ICSE ’03: Proceedings of the 25th International Conference on Software
     Engineering, IEEE Computer Society, Washington, DC, USA, 2003, pp. 3–13.
A. Details of the systematic classification of reflective
   operations
We propose a detailed and systematic description of the APIs and reflective behavior. Our
classification subsumes the one of Rivard.
   We are aware that presenting lists in a systematic manner may be tedious for the reader. We
consciously decided to do so to give a full view of the current situation in this appendix. For
each API, we briefly describe it, list its methods (we often group similar ones together), and
provide when adequate a little comment. This is our future work to identify layers within such
method lists.


B. Object Inspection
State inspection. These operations allow one to access the number of indexable variables,
and the values of instance variables, if they include a specific object

    • Context»objectSize:
    • Object»instVarAt:
    • Object>instVarNamed:
    • ProtoObject»instVarsInclude:

Accessing object identity. These operations allow one to identify one object

    • ProtoObject»basicIdentityHash
    • ProtoObject»identityHash

Accessing object class.    This operation allows one to access the class of an object :

    • ProtoObject»class
    • Context»objectClass:


C. Object Modification
State modification. These operations allow one to set the value of an instance variable.

    • Object»instVarAt:put: Write an instance variable using its index
    • Object»instVarNamed:put: Write an instance variable using its name.

Manipulating object identity. As a side effect of reference swapping, the reflective opera-
tion ProtoObject»becomeForward:copyHash: manipulates the hash of an object.
Object’s class change. These operations allow one to change the class of an object to another
one:

    • Behavior»adoptInstance:
    • Metaclass»adoptInstance:from:
    • Object»primitiveChangeClassTo:


D. Class structural inspection
Structural inspection operations allow the user to get information about the structure of the
current Pharo world. This includes information about the classes, their variables names and
hierarchy, as well as object, their variables names, and if they are capable of answering some
messages.

Class/metaclass shift. Those operations deal with testing and navigating between the class
and instance side of classes.

    • ClassDescription»classSide / Class»classSide / Metaclass»classSide
    • ClassDescription»instanceSide / Class»instanceSide / Metaclass»instanceSide
    • ClassDescription»isClassSide / CompiledMethod»isClassSide
    • ClassDescription»isInstanceSide
    • Metaclass»isMetaclassOfClassOrNil
    • ClassDescription»hasClassSide / Class»hasClassSide / Metaclass»hasClassSide
    • Object»isClass / Class»isClass / Trait»isClass / Metaclass»isClass
    • Behavior»isMeta / ClassDescription»isMeta / Metaclass»isMeta

Iterating and querying hierarchy. These operations allow one to query the hierarchy of a
class and iterate over those. They allow one to access superclasses and subclasses, testing for
common ancestry in the class hierarchy, and testing that an object is an instance or subinstance
of a class.

    • Class»subclasses / MetaClass»subclasses / UndefinedObject»subclasses
    • Behavior»allSubclasses
    • Behavior»withAllSubclasses
    • Behavior»obsoleteSubclasses / Metaclass»obsoleteSubclasses
    • Class»hasSubclasses
    • Behavior»superclass
    • Behavior»allSuperclasses
    • Behavior»withAllSuperclasses
    • Behavior»allSuperclassesIncluding:
    • Behavior»allSubclassesWithLevelDo:startingLevel:
    • Class»subclassesDo: / Metaclass»subclassesDo: / UndefinedObject»subclassesDo:
    • Behavior»allSubclassesDo:
    • Behavior»withAllSubclassesDo:
    • Behavior»allSuperclassesDo: / UndefinedObject»allSuperclassesDo:
    • Behavior»withAllSuperclassesDo:
    • Behavior»withAllSuperAndSubclasses
    • Behavior»withAllSubAndSuperclassesDo:
    • Object»isKindOf:
    • Object»isMemberOf:
    • Behavior»kindOfSubclass
    • Class»commonSuperclassWith: / UndefinedObject»commonSuperclassWith:
    • Behavior»whichSuperclassSatisfies:
    • Behavior»inheritsFrom:
    • Behavior»includesBehavior:
    • Behavior»isRootInEnvironment
    • Behavior»selectSuperclasses:
    • Behavior»selectSubclasses:

Instance variable inspection. These operations allow one to query and get instance variable
names, iterate over those, and get their index and the class defining a specific instance variable.

    • Behavior»instVarNames / ClassDescription»instVarNames
    • Behavior»allInstVarNames / ClassDescription»allInstVarNames
    • ClassDescription»instanceVariableNamesDo:
    • ClassDescription»hasInstVarNamed:
    • Behavior»definedVariables / Class»definedVariables
    • ClassDescription»allInstVarNamesEverywhere
    • ClassDescription»classThatDefinesInstVarNamed:
    • Behavior»whichClassDefinesInstVar:
    • Behavior»instSize
    • Object»basicSize / Context»basicSize
    • Behavior»instVarNames

Class variable inspection. These operations allow one to query and test class variables,
get class variable names, get their values, iterate over those, class defining a specific instance
variable and who is using them.
    • Class»classVariables / Metaclass»classVariables
    • Behavior»allClassVarNames
    • Behavior»classVarNames / Class»classVarNames / Metaclass»classVarNames
    • Class»hasClassVariable:
    • Class»hasClassVarNamed: / Metaclass»hasClassVarNamed:
    • Class»classVariableNamed:ifAbsent:
    • Class»definesClassVariable:
    • Class»definesClassVariableNamed:
    • Class»readClassVariableNamed:
    • ClassDescription»classThatDefinesClassVariable:
    • Behavior»whichClassDefinesClassVar:
    • Class»usesClassVarNamed:
   The     methods  ClassDescription»classThatDefinesClassVariable:  and    Behav-
ior»whichClassDefinesClassVar: looks the same and the mix between variable and var
is prejudicial.

Shared pool inspection. These operations allow one to query and test on sharedPools and
where there are used. They are important to navigate with the IDE.

    • ClassDescription»sharedPools / Class»sharedPools
    • Behavior»allSharedPools / ctClassDescription»allSharedPools / ctClass»allSharedPools
    • Class»sharedPoolNames / Metaclass»sharedPoolNames
    • ClassDescription»hasSharedPools / Class»hasSharedPools
    • ClassDescription»sharedPoolOfVarNamed / Class»sharedPoolOfVarNamed
    • Class»sharedPoolsDo:
    • Class»classPool / Metaclass»classPool
    • ClassDescription»usesLocalPoolVarNamed: / Class»usesLocalPoolVarNamed:
    • ClassDescription»usesPoolVarNamed: / Class»usesPoolVarNamed:
    • ClassDescription»includesSharedPoolNamed:

Slot inspection. These operations allow one to query and test on slots in a class, or read
those in an object. This is a higher-level view compared to instance variables. Some slots can
come from traits. Therefore there is a difference between localSlots (without traits) and slots
(with).
    • Behavior»instanceVariables (returns a collection of slots)
    • Behavior»slots / ClassDescription»slots / TraitedMetaclass»slots
    • ClassDescription»localSlots
    • Behavior»allSlots / ClassDescription»allSlots
    • ClassDescription»slotNames
    • ClassDescription»hasSlotNamed:
    • ClassDescription»slotNamed:
    • ClassDescription»slotNamed:ifFound:
    • ClassDescription»slotNamed:ifFound:ifNone:
    • Object»readSlot:
    • Object»readSlotNamed:
    • ClassDescription»definesSlot:
    • ClassDescription»definesSlotNamed:
Selectors and method inspection. These operations allow one to test if a class has (abstract)
methods, an object responds to a specific selector, and all the classes that implement a set of
selectors.

    • Behavior»hasMethods / Class»hasMethods
    • Behavior»hasAbstractMethods / Class»hasAbstractMethods
    • Object»respondsTo:
    • ClassDescription»classesThatImplementAllOf:

  Getting the selectors and local selectors, iterating over them, and querying them :

    • Behavior»includesSelector:
    • Behavior»includesLocalSelector: / TraitedClass»includesLocalSelector: / TraitedMeta-
      class»includesLocalSelector:
    • Behavior»isDisabledSelector:
    • Behavior»isLocalSelector:    / TraitedClass»isLocalSelector:       / TraitedMeta-
      class»isLocalSelector:
    • Behavior»selectors
    • Behavior»selectorsDo:
    • Behavior»selectorsWithArgs:
    • Behavior»whichClassIncludesSelector:

Getting the methods, iterating over them, and querying them :

    • Behavior»methods
    • Behavior»methodNamed:
    • Behavior»includesMethod:
    • Behavior»methodsDo:
    • Behavior»selectorsAndMethodsDo:

Variable lookup. These operations allow one to lookup a variable in the scope of the receiver.

    • Behavior»classBindingOf: / SharedPool class»classBindingOf:
    • Object»bindingOf: / Behavior»bindingOf: / Class»bindingOf: / MetaClass»bindingOf:
    • Behavior»lookupVar: / ctContext»lookupVar: / ctSystemDictionnary»lookupVar:
    • Behavior»lookupVar:declare: / ctContext»lookupVar:declare: / ctSystemDiction-
      nary»lookupVar:declare:
    • Behvior»lookupVarForDeclaration:

Pragmas. Pragmas are method annotations that got introduced both in VisualWorks and
Pharo over the year [60]. These operations (Class»pragmasClass»pragmasDo:)allow one to get
all the pragmas of a class and iterate over them.
Class kind testing. Test various properties of classes: usage, anonymity, obsolescence.
    • Behvior»isAnonymous / Class»isAnonymous /MetaClass»isAnonymous
    • Object»isClassOrTrait / Class»isClassOrTrait
    • Behavior»isUsed / Class»isUsed / Trait»isUsed / Metaclass»isUsed
    • Behavior»isObsolete / Class»isObsolete / Metaclass»isObsolete


E. Class structural modification
Structural modification operations allow the user to modify the current structure/shape of
classes. They include operations to add/remove subclasses, instance variables, class variables, ...

Hierarchy modification. These operations allow one to edit the class hierarchy either by
adding/removing/changing subclasses, or changing the superclass.
    • Class»subclasses:
    • Behavior»superclass:
    • Behavior»basicSuperclass:
    • Class»addSubclass: / Metaclass»addSubclass: / UndefinedObject»addSubclass:
    • Class»removeSubclass:       / Metaclass»removeSubclass:         / UndefinedOb-
      ject»removeSubclass:
    • Behavior»removeAllObsoleteSubclasses
    • Behavior»addObsoleteSubclass: / Metaclass»addObsoleteSubclass:

Instance variable modification.        It allows one to add or remove an instance variable (by
name).
    • ClassDescription»addInstVarNamed:    /           Class»addInstVarNamed:           /   Meta-
      class»addInstVarNamed:
    • ClassDescription»removeInstVarNamed:

Class variable modification. These operations allow one to add or remove a class variable.
    • Class»addClassVariable:
    • Class»addClassVarNamed:
    • Class»removeClassVariable:
    • Class»removeClassVarNamed:

Shared pool modification. These operations allow one to add, change, or remove shared
pools.
    • Class»sharedPools:
    • Class»addSharedPool:
    • Class»addSharedPoolNamed:
    • Class»removeSharedPool:
    • Class»classPool:
Slot modification.

    • ClassDescription»addSlot: / Class»addSlot: / Metaclass»addSlot:
    • ClassDescription»removeSlot: / Class»removeSlot: / Metaclass»removeSlot:
    • Class»addClassSlot:
    • Class»removeClassSlot:
    • Object»writeSlot:value:
    • Object»writeSlotNamed:value
    • Class»writeClassVariableNamed:value:

Selector/Method modification. These operations allow one to add or remove selectors, or
query the class including one or more selectors.

    • Behavior»removeSelector:      / ClassDescription»removeSelector:   / TraitedMeta-
      class»removeSelector: / TraitedClass»removeSelector:
    • Behavior»removeSelectorSilently:
    • Behavior»addSelectorSilently:withMethod:                   /         ClassDescrip-
      tion»addSelectorSilently:withMethod:
    • Behavior»addSelector:withMethod: / ClassDescription»addSelector:withMethod: /
      TraitedMetaclass»addSelector:withMethod:
    • addSelector:withMethod: / TraitedClass»>addSelector:withMethod: / TraitedClass
      class»>addSelector:withMethod:
    • Behavior»addSelector:withRecompiledMethod:                       /        Traited-
      Metaclass»addSelector:withRecompiledMethod:                      /        Traited-
      Class»addSelector:withRecompiledMethod:

Old class creation. The following lists present the partial old API of Class for class creations.
It ignores the message supporting optional arguments. It shows clearly why it is about to be
deprecated.

    • subclass:instanceVariableNames:classVariableNames:category:
    • subclass:instanceVariableNames:classVariableNames:package:
    • subclass:instanceVariableNames:classVariableNames:poolDictionaries:category:
    • subclass:instanceVariableNames:classVariableNames:poolDictionaries:package:
    • subclass:layout:slots:classVariables:package:
    • subclass:layout:slots:classVariables:poolDictionaries:package:
    • subclass:slots:classVariables:package:
    • subclass:slots:classVariables:poolDictionaries:package:
    • variableByteSubclass:instanceVariableNames:classVariableNames:category:
    • variableByteSubclass:instanceVariableNames:classVariableNames:package:
    • variableByteSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category:
    • variableByteSubclass:instanceVariableNames:classVariableNames:poolDictionaries:package:
   • variableDoubleByteSubclass:instanceVariableNames:classVariableNames:package:
   • variableDoubleWordSubclass:instanceVariableNames:classVariableNames:package:
   • variableSubclass:instanceVariableNames:classVariableNames:category:
   • variableSubclass:instanceVariableNames:classVariableNames:package:
   • variableSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category:
   • variableSubclass:instanceVariableNames:classVariableNames:poolDictionaries:package:
   • variableWordSubclass:instanceVariableNames:classVariableNames:category:
   • variableWordSubclass:instanceVariableNames:classVariableNames:package:
   • variableWordSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category:
   • variableWordSubclass:instanceVariableNames:classVariableNames:poolDictionaries:package:
   • weakSubclass:instanceVariableNames:classVariableNames:category:
   • weakSubclass:instanceVariableNames:classVariableNames:package:
   • weakSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category:
   • weakSubclass:instanceVariableNames:classVariableNames:poolDictionaries:package:
   • ephemeronSubclass:instanceVariableNames:classVariableNames:package:
   • ephemeronSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category:
   • ephemeronSubclass:instanceVariableNames:classVariableNames:poolDictionaries:package:
   • immediateSubclass:instanceVariableNames:classVariableNames:package:
   • immediateSubclass:instanceVariableNames:classVariableNames:poolDictionaries:category:
   • immediateSubclass:instanceVariableNames:classVariableNames:poolDictionaries:package:

Fluid class creation. The following list presents the equivalent of the previous API in the
new fluid class creation API:

   • Beharior»« / Metaclass»« / Trait class»«
   • FluidClassBuilder»layout:
   • FluidBuilder»traits:
   • FluidClassBuilder»sharedVariables:
   • FluidClassBuilder»superclass:
   • FluidClassBuilder»sharedPools:
   • FluidBuilder»slots:
   • FluidBuilder»package:
   • FluidBuilder»tag:

Anonymous class creation.      Pharo introduced the notion of anonymous classes that support
instance-specific behavior.

   • Class»newAnonymousSubclass / Metaclass»newAnonymousSubclass
F. Compiled method creation
Compiled method creation      These operations support the creation of compile methods.
   • CompiledMethod class»newMethod:header:
   • CompileMethod»literalAt:put:
   • CompiledMethod»classBinding:
   • CompiledMethod»at:put:


G. Structural queries on methods
Method slot uses.   Query on which method is using some specific slot and how.
   • Behavior»allMethodsAccessingSlot:
   • Behavior»allMethodsReadingSlot:
   • Behavior»allMethodsWritingSlot:
   • Behavior»methodsAccessingSlot:
   • Behavior»methodsReadingSlot:
   • Behavior»methodsWritingSlot:
   • Behavior»hasMethodAccessingVariable:

Method element references.     Query which method/selector is using a given literal.
   • Behavior»whichMethodsReferTo:
   • Behavior»whichSelectorsReferTo:
   • Behavior»thoroughHasSelectorReferringTo:
   • Behavior»thoroughWhichMethodsReferTo:
   • Behavior»thoroughWhichMethodsReferTo:specialIndex:
   • Behavior»thoroughWhichSelectorsReferTo:
   • Behavior»hasSelectorReferringTo:

Class references. Behavior»usingMethods returns methods is referencing a given class.


H. Message Sending and code execution
H.1. Reflective message send
   • Object»perform:
   • Object»perform:orSendTo:
   • Object»perform:with:
   • Object»perform:with:with:
   • Object»perform:with:with:with:
   • Object»perform:with:with:with:with:
   • Object»perform:withArguments:
   • Object»perform:withArguments:inSuperclass:
   • Object»perform:withEnoughArguments:
Arbitrary method/primitive execution. While the message perform: supports message
sending, the following messages bypass the method lookup and execute a given compiler
method.
   • ProtoObject»withArgs:executeMethod:
   • ProtoObject»tryPrimitive:withArgs:
   • CompiledMethod»valueWithReceiver:arguments:
   • ProtoObject»executeMethod:
   • CompiledMethod»receiver:withArguments:executeMethod:

Method lookup.     These operations look up for selectors, and query about this lookup.
   • Behavior»lookupSelector:
   • Behavior»canPerform:
   • Behavior»canUnderstand:

Control message passing.
   • ProtoObject»cannotInterpret: Is sent to the receiver if the lookup finds a nil method
     dictionary. Use a special lookup starting above the class with the nil method dictionary.
     Has been implemented for proxy implementation.
   • ProtoObject»doesNotUnderstand: / Object»doesNotUnderstand: Is sent to the receiver
     of the message if the lookup reaches the root of the class hierarchy without finding the
     receiver.
   • ReflectiveMethod»run:with:in:

Message send reification. These operations allow one to query a message send to know if
it is its arguments, receiver and selectors, and to get a corresponding message.
   • MessageSend»isValid
   • MessageSend»arguments / Message»arguments
   • MessageSend»numArgs / Message»numArgs
   • MessageSend»collectArguments:
   • MessageSend»receiver
   • MessageSend»selector / Message»selector
   • MessageSend»message
   • Message»lookupClass
  These operations allow one to modify a message.
   • MessageSend»arguments:
   • Message»argument:
   • MessageSend»receiver:
   • MessageSend»selector:
   • Message»setSelector:
   • Message»lookupClass:
   • Message»setSelector:arguments:
Runtime and Evaluation     These operations allow one to evaluate a messageSend or convert
it to a messageSend.

   • Message»asSendTo:
   • Message»sends:
   • Message»sentTo:
   • MessageSend»value BlockClosure»value
   • MessageSend»value: BlockClosure»value:
   • MessageSend»value:value: BlockClosure»value:value:
   • MessageSend»value:value:value: BlockClosure»value:value:value:
   • MessageSend»valueWithArguments: BlockClosure»valueWithArguments:
   • MessageSend»valueWithEnoughArguments:                                      BlockClo-
     sure»valueWithEnoughArguments:
   • MessageSend»cull: BlockClosure»cull:
   • MessageSend»cull:cull: BlockClosure»cull:cull:
   • MessageSend»cull:cull:cull: BlockClosure»cull:cull:cull:

  The following methods perform explicit message sending (do the lookup and then apply a
compiled method if any is found):

   • Object»perform:(with: with: with: with:)
   • Object»perform: orSendTo:
   • Object»perform:withArguments:
   • Object»perform:withArguments: inSuperclass:
   • Object»perform:withEnoughArguments:


I. Chasing and swapping pointers
Find pointers to.

   • ProtoObject»pointersTo
   • ProtoObject»pointersToAmong:
   • ProtoObject»pointersToExcept:
   • ProtoObject»pointersToExcept:among:
   • Object»pointsOnlyWeaklyTo:
   • ProtoObject»pointsTo:

Bulk pointer swapping.

   • ProtoObject»become: swaps the references in both ways,
   • ProtoObject»becomeForward: swaps only towards a given object.
   • ProtoObject»becomeForward:copyHash:
J. Memory Scanning
Bulk pointer swapping.       The operations allow one to traverse the heap.

    • Object»someObject
    • ProtoObject»nextObject

Instances of a class. These operations allow one to get or iterate over the instances and
subinstances of a class.

    • Behavior»someInstance
    • ProtoObject»nextInstance
    • Behavior»allInstances
    • Behavior»allInstancesOrNil
    • Behavior»allInstancesDo:
    • Behavior»allSubInstancesDo:
    • Behavior»allSubInstances


K. Stack manipulation
K.1. Context
These operations allow one to get information on the execution context (stack, sender, receiver,
...). The thisContext pseudo-variable supports access to the current execution context. This
supports the creation of continuations and co-routines.

    • Context»selector
    • Context»sender
    • Context»activeOuterContext
    • Context»arguments
    • Context»at:
    • Context»at:put:
    • Context»method
    • Context»methodNode
    • Context»outerContext
    • Context»outerMostContext
    • Context»receiver
    • Context»tempAt:
    • Context»tempAt:put:
K.2. Controlling the stack
These operations allow one to control the execution of the current program.

    • Context»top
    • Context»stepUntilSomethingOnStack
    • Context»runUntilErrorOrReturnFrom:
    • Context»resume:through:
    • Context»activateMethod:withArgs:receiver:class:
    • Context»terminate
    • Context»send:to:with:lookupIn:
    • Context»resumeEvaluating:
    • Context»jump
    • Context»terminateTo:
    • Context»send:to:with:super:
    • Context»return
    • Context»pop
    • Context»shortDebugStack
    • Context»return:
    • Context»push:
    • Context»step
    • Context»return:from:
    • Context»resume
    • Context»stepToCallee
    • Context»return:through:
    • Context»resume: