This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
MindenCucc's profile picture

coroutine.resume returns unexpected results

Started by MindenCucc, 14 May 2015 - 08:34 PM
MindenCucc #1
Posted 14 May 2015 - 10:34 PM
I'm having technical difficulties with coroutines. Somehow ddm ends without errors (the while-true broke somehow, or idk)

Le' code:
ddm - http://pastebin.com/BLnEZa8J
sand(box) - http://pastebin.com/KFLmtidq

test
Spoiler


os.loadAPI("sand")

local sandenv = {}
sandenv.env = sandenv
sandenv.k = function(t) for k,v in pairs(t) do write(k..", ") print(v) end end

local deskman, err = loadfile("ddm")
if not deskman then error(err) end

local sandbox = sand.new(deskman, sandenv)
sandenv.box = sandbox

sandbox.run()

local ok, ejj

while sandbox.running() do
  ok, ejj = sandbox.unyield()
  if not ok then error(ejj) end
end
if not ok then error(ejj) end
print(tostring(ok) .. ", " .. tostring(ejj))
error(ejj)

Usage:
Spoilerrun test, click the bottom-right corner of the gray bar until the cursor pops up (hart to notice), type in "rom/programs/lua" (without quotes of course), and see the weirdness happen.

Also, running "test" in a pcall returns "false, nil" :blink:/>
Edited on 14 May 2015 - 08:44 PM
Lupus590 #2
Posted 14 May 2015 - 10:59 PM
Liking this tutorial is the best I can do: https://docs.google.com/document/d/1UU-bSCgLqwAQixldXmDzvEFPACaieph3qs08WreQlZs/edit
My only other suggestion is to dig into the parallel API's code.

Mentioning the parallel API, in most cases it can do what people need when using multiple coroutines, have a look if it will do what you want to do.
KingofGamesYami #3
Posted 14 May 2015 - 11:11 PM
You're not passing anything to sandbox.unyield(), which in turn passes nothing to coroutine.yield, dropping any filters the code you're running gives you.

For example,


os.pullEvent( "char" )

Will not only pull char events (running in your coroutine), but anything else (such as mouse_click).

I'm not sure this is the cause, but you may want to check it out.
Bomb Bloke #4
Posted 15 May 2015 - 02:03 AM
A while back I scribbled out an example of the process KoGY describes; here's an attempt to make it more clear:

local function myFunc(myArg)
	for i = 1, myArg do
                print(i)
                sleep(1)
        end
end

-- From bios.lua, we have the source of sleep:
-- function sleep( nTime )
--     local timer = os.startTimer( nTime or 0 )
--     repeat
--         local sEvent, param = os.pullEvent( "timer" )
--     until param == timer
-- end

-- ... and the source of os.pullEvent():
-- function os.pullEvent( sFilter )
--     local eventData = { os.pullEventRaw( sFilter ) }
--     if eventData[1] == "terminate" then
--         error( "Terminated", 0 )
--     end
--     return table.unpack( eventData )
-- end

-- ... and the source of os.pullEventRaw():
-- function os.pullEventRaw( sFilter )
--     return coroutine.yield( sFilter )
-- end

-- So, os.pullEvent( "timer" ) == coroutine.yield( "timer" ), but errors if a terminate event is returned instead.
-- Now let's run myFunc as a coroutine:

-- Initialise coroutine:
print("Starting coroutine!")

local myCoroutine = coroutine.create(myFunc)
local ok, requestedEvent = coroutine.resume(myCoroutine, 10)  -- Being the first resume, 10 gets pushed to myArg.

-- Run coroutine to completion:
while coroutine.status(myCoroutine) ~= "dead" do
        print("Coroutine seems ok, and is asking for a \"" .. requestedEvent .. "\" event.")  -- With the example myFunc, "requestedEvent" will always be "timer".

        local myEvent = {os.pullEvent(requestedEvent)}
        ok, requestedEvent = coroutine.resume(myCoroutine, unpack(myEvent))  -- Parameters of later resumes are returned by coroutine.yield() (and hence os.pullEvent()) within the coroutine itself.
end

-- Coroutine has finished execution.
if ok then
        print("Coroutine has completed in a natural manner.")
else
        print("Coroutine errored!: " .. requestedEvent)
end