Skip to content

Commit

Permalink
adding better message passing section in lookup chapter
Browse files Browse the repository at this point in the history
  • Loading branch information
Ducasse committed Jan 10, 2025
1 parent 2846a1a commit c895183
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 7 deletions.
9 changes: 4 additions & 5 deletions Chapters/08-EvaluatorMessageError.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
## Handling Unknown Messages
@cha:dnu

In the previous chapter we presented method lookup and show the precise semantics of message sent to `super`. We did not take into the case where the method we are looking up actually exists.
In the previous chapter, we presented method lookup and showed the precise semantics of the messages sent to `super`. We only took into account the case where the method we are looking up actually exists.
In this chapter, we show how to handle this case. We extend the interpreter with support for the
support error and the famous `doesNotUnderstand:`.



We start by revisiting the current method lookup implementation. Doing so, we will be ready to handle the case of unknown messages.


### Correct Semantics Verification

To ensure that the method lookup is correctly implemented, especially in the presence of `super` messages, we need to verify an extra condition. Several books wrongly define that `super` messages lookup methods starting from the superclass of the class of the receiver. This is plain wrong.
To ensure that the method lookup is correctly implemented, especially in the presence of `super` messages, we need to stress our implementation with an extra scenario. Several books wrongly define that `super` messages lookup methods starting from the superclass of the class of the receiver. This is plain wrong.

This definition, illustrated in the code snippet below, is incorrect: it only works when the inheritance depth is limited to two classes, a class, and its superclass.
In other cases, this definition creates an infinite loop.
Expand All @@ -35,7 +34,7 @@ In this scenario, our inheritance depth is of three classes and we create two me
In the highest class, the method returns a value.
In the middle class, the first method is overridden doing a super send.

![A simple situation making wrongly defined super semantics loop endlessly: sending the message `redefinedMethod` to an instance of the class `CInterpretable` loops forever. %width=60&anchor=fighierarchyFullWrong](figures/WrongSuperLoopsHierarchy.pdf)
![A simple situation that breaks wrongly defined super semantics: sending the message `redefinedMethod` to an instance of the class `CInterpretable` loops forever. %width=60&anchor=fighierarchyFullWrong](figures/WrongSuperLoopsHierarchy.pdf)

Let us define the situation that will loop with the wrong semantics.

Expand Down
47 changes: 45 additions & 2 deletions Chapters/08-EvaluatorMessageLookup.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,55 @@ In this chapter, we will implement method lookup for messages sent to an object.
Then we will present how we handle the case of messages sent to `super`.


### Method Lookup Introduction

So far we have concentrated on method evaluation and put aside method lookup.
Our current solution fetches methods from the class of the receiver, without supporting inheritance.
In this section, we address this problem and implement a proper method lookup algorithm.

### Method Lookup Introduction

![Sending a message is a two-step process: method lookup and execution. % width=48&label=fig:ToSteps](figures/InheritanceDiagram-sendingMessage.pdf)

Sending a message is a two-step process as shown by Figure *@fig:ToSteps@*:
1. Method lookup: the method corresponding to the selector is looked up in the class of the receiver and its superclasses.
1. Method execution: the method is applied to the receiver. This means that `self` or `this` in the method will be bound to the receiver.

Conceptually, sending a message can be described by the following function composition:

```
sending a message (receiver argument)
return apply (lookup (selector classof(receiver) receiver) receiver arguments)
```


#### Method lookup

Now the lookup process is conceptually defined as follows:
1. The lookup starts in the **class** of the **receiver**.
1. If the method is defined in that class (i.e., if the method is defined in the method dictionary), it is returned.
1. Otherwise the search continues in the superclass of the currently explored class.
1. If no method is found and there is no superclass to explore (if we are in the class `Object`), this is an error (i.e., the method is not defined).


![Looking for a method is a two-step process: first, go to the class of receiver then follow inheritance. % width=58&label=fig:LookupNoError](figures/Ref-LookupNoError.pdf)

The method lookup walks through the inheritance graph one class at a time using the superclass relationship. Here is a possible description of the lookup algorithm that will be used for both instance and class methods.

```
lookup (selector class receiver):
if the method is found in class
then return it
else if class == Object
then Error
else lookup (selector superclass(class) receiver)
```

Let us implement method lookup.


### Method Lookup Scenario



To implement and test the method lookup, we should extend our scenario classes with a class hierarchy.
We introduce two superclasses above `CInterpretable`: `CInterpretableRoot` and its subclass `CInterpretableSuperclass`.
With this setup, we can test all interesting situations, even the ones leading to infinite loops
Expand Down
Binary file modified Chapters/figures/InheritanceDiagram-sendingMessage.graffle
Binary file not shown.
Binary file modified Chapters/figures/InheritanceDiagram-sendingMessage.pdf
100755 → 100644
Binary file not shown.
Binary file added Chapters/figures/Ref-LookupNoError.graffle
Binary file not shown.
Binary file added Chapters/figures/Ref-LookupNoError.pdf
Binary file not shown.

0 comments on commit c895183

Please sign in to comment.