squirrel icon indicating copy to clipboard operation
squirrel copied to clipboard

base is null in a method called with bindenv via a corountine?

Open MrSapps opened this issue 7 years ago • 2 comments

The smallest script I could make to repro the issue is this one:

class TestBase
{
   function PlaySoundEffect(sfx)
   {
     print("PlaySoundEffect:" + sfx);
   }
}

class Test extends TestBase
{
    mData = {};
    mThread = "";
    mFirst = true;

    function constructor()
    {
       mThread = ::newthread(CoRoutineProc);
       print("Base is: " + base); // BASE IS OK Base is: (class : 0x0x50eb48)
       base.PlaySoundEffect("Test1");
    }

    function Update()
    {
        if (mFirst)
        {
            mThread.call(this);
            mFirst = false;
        }
        else
        {
            mThread.wakeup(this);
        }
    }

    function CoRoutineProc(thisPtr)
    {
        thisPtr.Exec.bindenv(thisPtr)();
    }

    function Exec()
    {
        mData = { mFunc = Test.TestFunction};
        while (true)
        {
            mData.mFunc.bindenv(this)();
            ::suspend();
        }
    }

    function TestFunction()
    {
        DoACallBack("test",
        { 
            onFrame = function()
            {
                print("Base is: " + base); // WHY IS BASE NULL HERE?? Base is: (null : 0x(nil))
                base.PlaySoundEffect("Test2");
            }
        });
    }

    function DoACallBack(name, params = null)
    {
        if ("onFrame" in params)
        {
            print("Calling nested call back");
            if (params.onFrame.bindenv(this)())
            {

            }
        }
        ::suspend();
    }
}

local t = Test();
t.Update();

In TestFunction when onFrame is called base is null, is this an issue with my script or could it be a bug?

MrSapps avatar Mar 14 '17 23:03 MrSapps

"base" is only set to a closure when the closure is added to a class, either by declaring it in the body or by adding it with the <- operator( as in Myclass.funcname <- function() {}). It is not a free variable.

albertodemichelis avatar Mar 15 '17 04:03 albertodemichelis

Hmm this seems a little quirky - if I add mBase = base; to the class and replace all use of base. with mBase. then I get to access "base". Your suggestion won't work in my example because it seems that <- can't be used after the class is constructed or on an instance of a class?

I would have thought the pattern of

someclass::function()
{
   this.callMeWhenSomethingHappens(function() { print("It happened"); });
}

Would be quite common in scripting. Or is something like mBase = base the usual workaround for this situation?

MrSapps avatar Mar 15 '17 07:03 MrSapps