justinmeza/lci — pull request #22 by ord-nas (2014-11-27 03:40:29+00:00)
Title: Fixed problem with ME when using alternate method calling syntax

I found what I think is a bug in how lci handles the "obj IZ function" way of calling functions.

I created this object:

O HAI IM CAT
HOW IZ I EATIN YR FOOD
VISIBLE SMOOSH "i eated " AN FOOD MKAY
IF U SAY SO
KTHX

I can call `CAT'Z EATIN` in two ways, and both work.

I IZ CAT'Z EATIN YR "cheeseburger" MKAY
CAT IZ EATIN YR "cheeseburger" MKAY

But now, suppose that I make `CAT'Z EATIN` use the ME identifier to try to access the caller's slots, like so:

O HAI IM CAT
I HAS A COUNT ITZ 0
HOW IZ I EATIN YR FOOD
ME'Z COUNT R SUM OF ME'Z COUNT AN 1
VISIBLE SMOOSH "i eated " AN FOOD MKAY
VISIBLE SMOOSH "yum yum, me haz " AN ME'Z COUNT AN " stuffz in stomach!" MKAY
IF U SAY SO
KTHX

Now, the `I IZ CAT'Z EATIN` syntax still works, but the `CAT IZ EATIN` syntax fails ... the system hums for a while, and then I get a segfault ...

I looked through the code, and the problem appears to be in the `getScopeObjectLocalCaller` function. In the case of `CAT IZ EATIN`, the "caller" will be set to the EATIN function (there's a warning that this is a hack). Presumably, when I tried to look up `ME'Z COUNT`, the interpreter tried to use the function as a scope, and everything exploded.

I think the right behaviour is that if `getScopeObjectLocalCaller` ends up finding a function, it should just return the dest scope. In the call `OBJ IZ FUNCTION`, we'll see that FUNCTION is a function, and the caller scope will be OBJ instead, which I believe is the correct behaviour.

The only potential downside that I can see is that this means that when a function is called *without* a calling object, ME will just refer to the outer scope. i.e.

HOW IZ I FUNCTIONIN
VISIBLE ME'Z FOO
IF U SAY SO

I HAS A FOO ITZ "foo!"

I IZ FUNCTIONIN MKAY

will print "foo!", because the caller scope will be set to the global scope (since that's what the `I` in `I IZ FUNCTIONIN` refers to). The spec says this is supposed to "raise an exception" or something. For reference, lci's current behaviour in this case is to segfault ;)