Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Coroutine support * Bug fixing & specs * Coroutine#resume return results * Add sample
- Loading branch information
Showing
9 changed files
with
214 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
require "../src/lua" | ||
|
||
lua = Lua.load | ||
co = lua.run(%q{ | ||
function foo (a) | ||
print("foo", a) | ||
return coroutine.yield(2*a) | ||
end | ||
return coroutine.create(function (a,b) | ||
print("co-body", a, b) | ||
local r = foo(a+1) | ||
print("co-body", r) | ||
local r, s = coroutine.yield(a+b, a-b) | ||
print("co-body", r, s) | ||
return b, "end" | ||
end) | ||
}).as(Lua::Coroutine) | ||
|
||
res = co.resume 1, 10 | ||
puts "main #{res}" | ||
|
||
res = co.resume "r" | ||
puts "main #{res}" | ||
|
||
res = co.resume "x", "y" | ||
puts "main #{res}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
require "../../spec_helper" | ||
|
||
module Lua | ||
describe Coroutine do | ||
describe "#resume" do | ||
it "starts and resumes coroutine" do | ||
lua = Lua.load | ||
f = lua.run %q{ | ||
return function() | ||
coroutine.yield() | ||
end | ||
} | ||
co = lua.newthread(f.as Lua::Function) | ||
co.status.should eq CALL::OK | ||
co.resume | ||
co.status.should eq CALL::YIELD | ||
co.resume | ||
co.status.should eq CALL::OK | ||
lua.close | ||
end | ||
|
||
it "can yield arguments" do | ||
lua = Lua.load | ||
f = lua.run %q{ | ||
return function(x) | ||
return coroutine.yield() | ||
end | ||
} | ||
co = lua.newthread(f.as Lua::Function) | ||
co.resume.should eq nil | ||
co.resume(42).should eq 42.0 | ||
lua.close | ||
end | ||
|
||
it "resumes coroutine created with coroutine.create" do | ||
lua = Lua.load | ||
t = lua.run %q{ | ||
function s(x) | ||
return coroutine.yield(x) | ||
end | ||
return coroutine.create(s) | ||
} | ||
|
||
co = t.as(Lua::Coroutine) | ||
co.resume.should eq nil | ||
co.status.should eq CALL::YIELD | ||
co.resume("test").should eq "test" | ||
co.status.should eq CALL::OK | ||
lua.close | ||
end | ||
|
||
it "can return an error" do | ||
lua = Lua.load | ||
t = lua.run %q{ | ||
function s(x) | ||
return x * 20 | ||
end | ||
return coroutine.create(s) | ||
} | ||
|
||
co = t.as(Lua::Coroutine) | ||
expect_raises RuntimeError do | ||
co.resume("hello") | ||
end | ||
co.status.should eq CALL::ERRRUN | ||
lua.close | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
module Lua | ||
class Coroutine < Object | ||
# Creates new Coroutine with it's own stack | ||
# and a function to execute. | ||
# | ||
# ``` | ||
# lua = Lua.load | ||
# | ||
# f = lua.run %q{ | ||
# return function() | ||
# print("before yield") | ||
# | ||
# coroutine.yield() | ||
# | ||
# print("after yield") | ||
# end | ||
# } | ||
# | ||
# co = lua.newthread(f.as Lua::Function) | ||
# co.resume # before yield | ||
# co.status # => YIELD | ||
# co.resume # after yield | ||
# co.status # => OK | ||
# ``` | ||
# | ||
# Stack may return coroutine. In this case we do not need to | ||
# pass a function 'cause coroutine should already have it: | ||
# | ||
# ``` | ||
# t = lua.run %q { | ||
# function s(x) | ||
# return coroutine.yield(x) * 10 | ||
# end | ||
# | ||
# return coroutine.create(s) | ||
# } | ||
# | ||
# co = t.as(Lua::Coroutine) | ||
# co.resume # => nil | ||
# co.resume(4.2) # => 42.0 | ||
# ``` | ||
def initialize(stack, @function : Function? = nil) | ||
super(stack, nil) | ||
end | ||
|
||
def resume(*args) | ||
if function = @function | ||
function.preload(@stack) { @stack.resume *args } | ||
else | ||
@stack.resume *args | ||
end | ||
end | ||
|
||
def status | ||
@stack.status | ||
end | ||
|
||
protected def function=(f : Function) | ||
@function = f | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
module Lua::StackMixin | ||
module CoroutineSupport | ||
# Creates new thread and returns a coroutine that wraps | ||
# that state and function `f` | ||
def newthread(f : Function) | ||
LibLua.newthread(@state) | ||
pop.as(Coroutine).tap { |c| c.function = f } | ||
end | ||
|
||
# Starts and resumes a coroutine in the given thread | ||
protected def resume(*args) | ||
thread_pos = size | ||
args.each { |a| self.<< a } | ||
|
||
res = CALL.new LibLua.resume(@state, nil, args.size) | ||
raise error(res, pop) if res > CALL::YIELD | ||
|
||
pick_results thread_pos | ||
end | ||
|
||
# Returns the status of the current thread. | ||
def status | ||
CALL.new LibLua.status(@state) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters