Handler in a handler

In an attempt to track down a larger problem, I made these three scripts in a suite I called handlerConfusion:

====================
driveTest.script:
put new parentObject into po
send “someMessage” to po

====================
ParentObject.script:
function makeNewObject
put “------------------------------------”
put “I’m a parent constructor”
put “I make a child”
put new childObject into co2 // succeeds
put “and it’s no problem!”
put “------------------------------------”
return me
end makeNewObject

on someMessage
put “------------------------------------”
put “I’m a parent message”
put “I make a child”
put new childObject into co // fails
put “------------------------------------”
end someMessage

on put
pass message
end put
on
put “I’m the parent, I don’t want the child’s message!”
end

====================
ChildObject.script:
function makeNewObject
put “I’m the child and I’m gonna call my function”
childFunction
return me
end makeNewObject

to childFunction
put “I am in the childFunction”
end childFunction

on put
pass message
end put

on
put “I’m the child, and I didn’t get the message!”
end

====================
I expect the same behavior when I create a childobject in the parentobject constructor as I see when I create a childobject in the parentobject message handler, but I don’t. I get this error:

Tue, 12/6/05 5:09:32 PM START Running /Documents/source/qa/eggplant_tests/test/handlerConfusion.suite/Scripts/driveTest.script

I’m a parent constructor
I make a child
I’m the child and I’m gonna call my function
I am in the childFunction
and it’s no problem!


I’m a parent message
I make a child
I’m the child and I’m gonna call my function
Tue, 12/6/05 5:09:33 PM FAILURE Screen_Error.tiff SRUN_UnknownCommand ERROR: No Handler Found for Command message: ‘childfunction’

Please tell me why I cannot get the childobject handler to be called when the childobject was created in the course of handling a parentobject message.

Also, please show me how to do this essential operation or point me to some documentation I may have overlooked.

Thank you.
-edj

An update:
I noticed that if I change the call to the childFunction from function syntax to message syntax, the expected behavior happens. That is:

put “I’m the child and I’m gonna call my function”
childFunction // or childFunction()

does not call the ‘to childFunction’, which I think it should. This may be an eggplant bug?

but when I change it to:

put “I’m the child and I’m gonna call my function”
send “childFunction” to me // or … to this object

it calls childFunction as I expect.

I guess I could do it this way, making everything a (send “someMessage”, to handle someMessage) pair, but I don’t understand why I should have to.

Also, please note that I must say ‘send “childFunction” TO ME’. By default, shouldn’t ‘send “childFunction”’ have an implicit ‘to me’? Maybe another bug?

-edj

Yes, there is clearly a bug here. What you’ve tried should all work as you expected. I haven’t had a chance yet to figure out exactly what the problem is, but during the creation of an object, the object is (at least under certain conditions) sending messages to the object that is creating it rather than to itself. This isn’t the correct behavior, but you’ve found at least one reasonable workaround for the time being, which is to send messages explicitly to ‘me’.

While on the subject of object creation, I thought I would point out that SenseTalk doesn’t really use “constructors” in the same way that other languages do. The makeNewObject function is generally not needed – your objects will be created just fine without such a handler. An initialize handler is more common, but in many cases you may find that assigning properties in the script that creates them is sufficient, like this:

set child to new childObject with (name:"Cory", eyes:"blue")

Without getting off track of the original problem, I just want to point out why I am doing things in the makeNewObject so that you don’t feel like there’s a better way. (Well, maybe the IS a better way. :slight_smile: )

Actually, I had already figured out that initialize seems to be Eggplant’s preferred way, so I am using initialize now instead of makeNewObject.

I have a script to run my software on some machine and it looks like this:

put new machine into m // object interface to a real machine
send “grabmachine” to m // vnc to the machine
put new login(m.OS) into session // login to the machine that I’m vnc’d to

That login object of the last line has to do quite a bit of work. One, of the things it may have to do (it’s a Windows machine) is logoff first. So I made ‘function logoff’ to do this. And function logoff is called from makeNewObject (now initialize) and it doesn’t work because of this odd SenseTalk behavior.

That’s why I am doing what I am doing.

-edj

Fair enough. I apologize for the inconvenience – we’ll try to get this remedied soon.

One other slight variation that occurs to me would be to make a session object (a noun, after all) , rather than a login object, and then call a login function on the session. This would also avoid the current problem, I believe. :wink:

Well, originally, login was a procedural script that logged in to the machine. It had helper functions that were exhibiting a problem (which I am guessing is this same bug) about no handler for logoff was found or some such. So I thought maybe I can’t mix a procedural script with an object-type script.

So, I decided, fine, I’ll just make login.script an object. I was lazy and didn’t change the name. :slight_smile:

At this point, I suppose I may as well do it right. :wink:

-edj

Look what I found on page 129 of the Eggplant Reference Manual:
“A function always has a return value and it must be part of a statement; it cannot appear on a line by itself that does not handle the return value:”

Sure enough, when I change my code from:
childFunction
-to-
set res = childFunction()

it works!

So, I still think it’s bad to have the inconsistent behavior that the program above displays, but otherwise, it seems like SenseTalk is happy was I use the correct function call syntax.
-edj

The bug identified above has now been fixed for the next release of Eggplant, so now that I understand the problem I thought I’d explain it briefly.

There was nothing wrong with your code. You were calling childFunction as a command, not as a function, which is fine since it’s implementation was written as a “to childFunction” handler (if it was written as “function childFunction” then you would have to call it as a function – using “to” it can be called either way). Changing your code to call it as a function worked because the bug turned out to be a problem only for command calls, not function calls.

This particular bug was also related to the “send” command, such that the incorrect behavior only occurred when something was called as a command within the context of a handler that was invoked by a send command. So another possible workaround (for anyone who runs into this before the next version of Eggplant is released) would be to avoid the use of “send”. It had nothing to do with object creation, as I incorrectly supposed earlier. I hope that clarifies the situation, and I apologize once again for the inconvenience of having to work around this issue for now.