Execution Model
From RubySpec
Note: where there are questions asked on this page, please feel free to put your suggested answers here (or just to change the text). I have no ego :-)
Contents |
Processing
A Ruby processor executes a program in two separate phases.
- During the translation phase, the processor converts the program into an internal form.
- During the run phase, the processor performs the actions as specified by the output from translation.
Note: the internal form is not prescribed, and can be anything from essentially the original source program (augmented with scope information for local variables) to executable code for a conventional processor.
Variables and values
Ruby uses dynamic typing, in which variables are not typed, but the value bound to a variable has a type.
Values
The fundamental objects on which a Ruby program operates are known as objects: each is comprised of three components.
- The class of which the object is an instance (immutable).
- A mutability flag, which indicates whether the object's state may be changed during execution.
- The actual data that the object contains.
Since there are no values that are not instances of classes, the concepts of type and class are the same in Ruby (unlike, for example, C++).
TODO: say more about object mutation.
In most cases, the data an object contains will consist of references to other objects (see the discussion of identity and equality later). In a few cases, e.g., numbers, the data will be direct binary data. NOTE: an implementation may optimize the storage of certain classes, e.g., numbers and booleans. However, the observed behavior must be the same as in an unoptimized implementation.
Methods and messages
The fundamental operation in Ruby is sending a message to an object. This operation requires:
- A target object to which the message is sent
- A message consisting of a Symbol
- Zero or more arguments, objects to be included with the message.
The sending of a message triggers the execution of a corresponding method, a procedure that is invoked as a result of the message sent. Invoking the method results in the execution of the code it contains, and returns zero or more result objects.
Classes and inheritance
NOTE: I know that there are errors in the following. I hope you will join me in correcting them.
Each object is an instance of precisely one class.
A class is an object that comprises
- a set of flags
- a reference to a superclass
- a set of names of instance variables
- a method dictionary whose keys are symbols representing messages, and whose values are the corresponding method objects
TODO: Should class variables and class methods be included here as well?
TODO: Should class constants be added here as well?
An instance variable is a variable used to store state data for an object. The scope of an instance variable is the associated object. All instance variables are private to the object (unlike some other languages) and thus cannot be accessed directly from outside the containing object. It is the class's responsibility to provide whatever methods are necessary to perform operations on an object's instance variables. Instance variables do not have to be declared, they simple are added to an object when they are first assigned a value. An attempt to access an instance variable that does not exist will return nil.
TODO: explain metaclasses
The superclass links of all classes form a singly-rooted tree whose root is the class *Object*.
A message m is sent to an object o as follows.
- let k be the class object referred to by the object
- if there is an entry in k's method dictionary for m, then invoke the corresponding value (which must be a method) and terminate
- if k is an Object and there is no corresponding method, repeat from Step 1 with m = method_missing
- otherwise, follow k's superclass pointer and repeat from Step 2 with k = superclass.
NOTE: Since the Kernel module (which the Object class mixes in) defines a default method_missing which raises a NoMethodError exception, we're guaranteed to terminate in Step 2 when m = method_missing.
TODO: In Step 2, should there be a set of sub-steps to explain calls to super inside the method invocation?
TODO: Same as above, should this also cover the virtual class pointer in each class object along with an explanation as to how class methods work?
TODO: this doesn't cover modules
Methods, blocks, and closures
TODO: define each and explain their interrelationship TODO: do we want to expose Binding? I'd say yes

