Hi
I'm rethinking about my objvlisp lecture. In this lecture I'm talking about
building the objVlisp kernel in Smalltalk.
Now everything is working well except the error handling when a method is not
found with different arguments
than the original. Methods are represented with blocks having different number
of arguments.
I have several send messages (I should simplify this in the future)
------------------------------------------
binarySend: selector with: argument
"send the message whose selector is <selector> to the receiver. The
arguments of the messages
are an <argument>. The method is lookep up in the class of the
receiver.
self is an objObject or a objClass."
| ans |
ans := (self objClass lookup: selector for: self) value: self value:
argument.
^ ans
send: selector withArguments: arguments
"send the message whose selector is <selector> to the receiver. The
arguments of the messages
are an array <arguments>. The method is lookep up in the class of the
receiver.
self is an objObject or a objClass."
| ans |
ans := (self objClass lookup: selector for: self)
valueWithArguments: (Array with: self) ,
arguments.
^ ans
lookup is as simple as
------------------------------
lookup: selector for: anObjObject
"look for the method named <selector> starting in the receiver.
The lookup is done for a message sent to <anObjObject>. self is an
objClass"
^(self doesUnderstand: selector)
ifTrue: [ self bodyOfMethod: selector]
ifFalse: [self objName = #ObjObject
ifFalse: [ (Obj giveClassNamed: self
objSuperclassId) lookup: selector for: anObjObject.]
ifTrue: [ anObjObject objClass lookup: #error
for: anObjObject]]
Now the problem is that error redefinition only works if the same number of
arguments are used and this is not nice.
For example error redefinition works:
---------------------------------------------------
testErrorRedefinition
"(self run: #testErrorRedefinition)"
self should: [aPoint unarySend: #zork] raise: Error.
(pointClass at: pointClass offsetForMethodDict) at: #error
put: ([ :superClassOfClassDefiningTheMethod | [:objself | 33]]
value: objectClass).
self assert: (aPoint unarySend: #zork) = 33.
I could use cull: or something like that to be able to execute the block
representing the error message
But I have the impression that I need a way to say that the lookup failed and
that the arguments should be packed in a message object.
I looked in the StackVM to see how the arguments were handled: how do we go
some
lookupMethodInClass: class
| currentClass dictionary found |
...
currentClass := class.
[currentClass ~= objectMemory nilObject]
whileTrue:
[dictionary := objectMemory fetchPointer: MethodDictionaryIndex
ofObject: currentClass.
...
found := self lookupMethodInDictionary: dictionary.
found ifTrue: [^currentClass].
currentClass := self superclassOf: currentClass].
...
"Cound not find a normal message -- raise exception #doesNotUnderstand:"
self createActualMessageTo: class.
messageSelector := objectMemory splObj: SelectorDoesNotUnderstand.
^self lookupMethodInClass: class
Am I correct to believe that createActualMessageTo: eats up the call args and
does basically what I would like to do
Stef