遠藤です。

長文失礼します。Lua と Modula-2 をちょっとだけ試してみたので報告します。
はじめての Lua と Modula-2 なので間違いがあったらごめんなさい。
検証したコードは末尾に載せます。


Lua の coroutine は semi-coroutine で、coroutine 間に親子関係がありました。
実行を移すコマンドが二種類 (resume と yield) あります。
resume で他の coroutine を駆動し、その coroutine が yield するのを待ちます。
resume は親から子を、yield は子から親を駆動する感じです (親は子を選べますが、
子は親を選べません) 。
coroutine が終了すると、その coroutine が yield したのと同じ動作をしました。
親子関係を壊すような遷移 (子から親を resume する) はエラーになりました。
終了した coroutine を resume してもエラーでした。

Modula-2 の coroutine は純粋 (?) な coroutine で、coroutine 同士は対等です。
従って実行を移すコマンドは一種類 (TRANSFER) だけです。
TRANSFER で他の coroutine を駆動します。TRANSFER した coroutine は他の
coroutine から TRANSFER されるまで絶対に動きません。
coroutine が終了するとプログラムごと終了しました。

Lua 式と Modula-2 式のどちらがいいかは一長一短だと思います。



1.9 の Fiber は Lua と Modula-2 の中間 (やや Modula-2 寄り) にいる感じ
でしょうか。coroutine 終了時に yield するのは Lua っぽいですが、
実行を移すのが 1 種類だけのは Modula-2 っぽいです。

Lua は resume と yield の区別によって coroutine の親子関係が保証されており、
coroutine の終了時の挙動 (親に戻る) が関数呼び出しっぽくてわかりやすいです。
Modula-2 は親も子もなく実行はただ一本で、それが途切れたら全部終わり、という、
乱暴な挙動ではありますが、これはこれで筋が通っていると思います。
1.9 の現状の Fiber はこのあたりが中途半端なので prev が変なところを
指している感じがします。


あと噂では、Simula は Lua 式と Modula-2 式の両方の機能を提供しているらしい
(しかしそのせいで非常に複雑な実装になっているらしい) です。



非常にわかりにくいメールですみません。
以下、検証したコードです。※の数字の順に実行されます。


[[test.lua ここから]]
c1 = coroutine.create(function ()
    print("1")                     -- ※ 3 ※
    coroutine.yield()              -- ※ 4 ※
    print("2")                     -- ※ 到達しない ※
end)
c2 = coroutine.create(function ()
    coroutine.resume(c1)           -- ※ 2 ※
                                   -- ※ 5 ※
end)
coroutine.resume(c2)               -- ※ 1 ※
                                   -- ※ 6 ※
                                   -- ※ ここで実行終了 ※
[[test.lua ここまで]]

> $ lua test.lua
> 1


[[test.mi ここから]]
MODULE test;
  FROM SYSTEM IMPORT WORD, ADR, ADDRESS, TRANSFER, NEWPROCESS;
  FROM InOut IMPORT WriteInt, WriteLn;
VAR main, co1, co2 : ADDRESS;
    Workspace1 : ARRAY [0..1023] OF WORD;
    Workspace2 : ARRAY [0..1023] OF WORD;

PROCEDURE CO1;
BEGIN
 WriteInt (1, 1); WriteLn;                    (* ※ 4 ※ *)
 TRANSFER (co1, co2); (* co2.yield 相当 *)    (* ※ 5 ※ *)
 WriteInt (2, 1); WriteLn;                    (* 到達しない *)
END CO1;

PROCEDURE CO2;
BEGIN
 TRANSFER (co2, co1); (* co1.yield 相当 *)    (* ※ 3 ※ *)
                                              (* ※ 6 ※ *)
                                              (* ここで実行終了 *)
END CO2;

BEGIN
                                              (* ※ 1 ※ *)
 (* co1 = Fiber.new { CO1() }; co2 = Fiber.new { CO2() } *)
 NEWPROCESS (CO1, ADR (Workspace1), SIZE (Workspace1), co1);
 NEWPROCESS (CO2, ADR (Workspace2), SIZE (Workspace2), co2);

 TRANSFER (main, co2); (* co2.yield 相当 *)   (* ※ 2 ※ *)
                                              (* 到達しない *)
END test.
[[test.mi ここまで]]

> $ mocka -c test && mocka -p test && ./test
> 1

Modula-2 は mocka という実装で試してみました。
http://www.info.uni-karlsruhe.de/~modula/index.php


Lua のエラーのテスト:
[[test2.lua ここから]]
c1 = coroutine.create(function ()
    print(coroutine.resume(c2)) -- 親を resume しようとする
end)
c2 = coroutine.create(function ()
    coroutine.resume(c1)
end)
coroutine.resume(c2)
print(coroutine.resume(c2))     -- 死んだ coroutine を resume しようとする
[[test2.lua ここまで]]

> $ lua test2.lua
> false   cannot resume non-suspended coroutine
> false   cannot resume dead coroutine


Lua は coroutine の終了で親に帰っていく:
[[test3.lua]]
f1 = coroutine.create(function ()
    print("f1 before")
    coroutine.resume(f2)
    print("f1 after")
end)
f2 = coroutine.create(function ()
    print("f2 before")
    coroutine.resume(f3)
    print("f2 after")
end)
f3 = coroutine.create(function ()
    print("f3 before")
    coroutine.yield()
    print("f3 after")
end)
coroutine.resume(f1)
[[test3.lua ここまで]]

> $ lua test3.lua
> f1 before
> f2 before
> f3 before
> f2 after
> f1 after


上と似ている Ruby のコード
[[test.rb ここから]]
f2 = f3 = nil
f1 = Fiber.new do
    puts "f1 before"
    f2.yield
    puts "f1 after"
end
f2 = Fiber.new do
    puts "f2 before"
    f3.yield
    puts "f2 after"
end
f3 = Fiber.new do
    puts "f3 before"
    f2.yield
    puts "f3 after"
end

f1.yield
[[test.rb ここまで]]

> $ ./ruby test.rb
> f1 before
> f2 before
> f3 before
> f2 after
> f3 after

-- 
Yusuke ENDOH <mame / tsg.ne.jp>