github.com/hirochachacha/plua@v0.0.0-20170217012138-c82f520cc725/stdlib/coroutine/coroutine.go (about) 1 package coroutine 2 3 import ( 4 "github.com/hirochachacha/plua/object" 5 "github.com/hirochachacha/plua/object/fnutil" 6 ) 7 8 func create(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 9 ap := fnutil.NewArgParser(th, args) 10 11 cl, err := ap.ToFunction(0) 12 if err != nil { 13 return nil, err 14 } 15 16 th1 := th.NewThread() 17 18 th1.LoadFunc(cl) 19 20 return []object.Value{th1}, nil 21 } 22 23 func isyieldable(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 24 return []object.Value{object.Boolean(th.IsYieldable())}, nil 25 } 26 27 func resume(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 28 ap := fnutil.NewArgParser(th, args) 29 30 th1, err := ap.ToThread(0) 31 if err != nil { 32 return nil, err 33 } 34 35 rets, err := th1.Resume(args[1:]...) 36 if err != nil { 37 return []object.Value{object.False, err.Value()}, nil 38 } 39 40 return append([]object.Value{object.True}, rets...), nil 41 } 42 43 func running(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 44 return []object.Value{th, object.Boolean(th.IsMainThread())}, nil 45 } 46 47 func status(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 48 ap := fnutil.NewArgParser(th, args) 49 50 th1, err := ap.ToThread(0) 51 if err != nil { 52 return nil, err 53 } 54 55 switch th1.Status() { 56 case object.THREAD_INIT: 57 return []object.Value{object.String("suspended")}, nil 58 case object.THREAD_SUSPENDED: 59 return []object.Value{object.String("suspended")}, nil 60 case object.THREAD_ERROR: 61 return []object.Value{object.String("dead")}, nil 62 case object.THREAD_RETURN: 63 return []object.Value{object.String("dead")}, nil 64 case object.THREAD_RUNNING: 65 if th == th1 { 66 return []object.Value{object.String("running")}, nil 67 } 68 69 return []object.Value{object.String("normal")}, nil 70 default: 71 panic("unreachable") 72 } 73 } 74 75 func wrap(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 76 ap := fnutil.NewArgParser(th, args) 77 78 cl, err := ap.ToFunction(0) 79 if err != nil { 80 return nil, err 81 } 82 83 th1 := th.NewThread() 84 85 th1.LoadFunc(cl) 86 87 fn := func(_ object.Thread, args1 ...object.Value) ([]object.Value, *object.RuntimeError) { 88 return th1.Resume(args1...) 89 } 90 91 return []object.Value{object.GoFunction(fn)}, nil 92 } 93 94 func yield(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 95 return th.Yield(args...) 96 } 97 98 func Open(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 99 m := th.NewTableSize(0, 7) 100 101 m.Set(object.String("create"), object.GoFunction(create)) 102 m.Set(object.String("isyieldable"), object.GoFunction(isyieldable)) 103 m.Set(object.String("resume"), object.GoFunction(resume)) 104 m.Set(object.String("running"), object.GoFunction(running)) 105 m.Set(object.String("status"), object.GoFunction(status)) 106 m.Set(object.String("wrap"), object.GoFunction(wrap)) 107 m.Set(object.String("yield"), object.GoFunction(yield)) 108 109 return []object.Value{m}, nil 110 }