github.com/hirochachacha/plua@v0.0.0-20170217012138-c82f520cc725/stdlib/goroutine/goroutine.go (about) 1 package goroutine 2 3 import ( 4 goreflect "reflect" 5 6 "github.com/hirochachacha/plua/object" 7 "github.com/hirochachacha/plua/object/fnutil" 8 "github.com/hirochachacha/plua/object/reflect" 9 ) 10 11 func newchannel(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 12 ap := fnutil.NewArgParser(th, args) 13 14 cap, err := ap.OptGoInt(0, 0) 15 if err != nil { 16 return nil, err 17 } 18 19 if cap < 0 { 20 return nil, ap.ArgError(0, "capacity should not be negative") 21 } 22 23 return []object.Value{reflect.ValueOf(make(chan object.Value, cap))}, nil 24 } 25 26 func _select(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 27 ap := fnutil.NewArgParser(th, args) 28 29 cases := make([]goreflect.SelectCase, len(args)) 30 for i := range args { 31 ud, err := ap.ToFullUserdata(i) 32 if err != nil { 33 return nil, ap.TypeError(i, "SELECT_CASE*") 34 } 35 36 c, ok := ud.Value.(goreflect.SelectCase) 37 if !ok { 38 return nil, ap.TypeError(i, "SELECT_CASE*") 39 } 40 41 cases[i] = c 42 } 43 44 chosen, recv, recvOK := goreflect.Select(cases) 45 46 return []object.Value{object.Integer(chosen + 1), reflect.ValueOf(recv), object.Boolean(recvOK)}, nil 47 } 48 49 func _case(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 50 ap := fnutil.NewArgParser(th, args) 51 52 dir, err := ap.ToGoString(0) 53 if err != nil { 54 return nil, err 55 } 56 57 var rdir goreflect.SelectDir 58 59 switch dir { 60 case "send": 61 rdir = goreflect.SelectSend 62 case "recv": 63 rdir = goreflect.SelectRecv 64 case "default": 65 rdir = goreflect.SelectDefault 66 } 67 68 ud, err := ap.ToFullUserdata(1) 69 if err != nil { 70 return nil, ap.TypeError(1, "CHAN*") 71 } 72 73 if ud.Metatable == nil || ud.Metatable.Get(object.TM_NAME) != object.String("CHAN*") { 74 return nil, ap.TypeError(1, "CHAN*") 75 } 76 77 rch, ok := ud.Value.(goreflect.Value) 78 if !ok { 79 return nil, ap.TypeError(1, "CHAN*") 80 } 81 82 var rsend goreflect.Value 83 if send, ok := ap.Get(2); ok { 84 rsend = goreflect.ValueOf(send) 85 } 86 87 c := goreflect.SelectCase{ 88 Dir: rdir, 89 Chan: rch, 90 Send: rsend, 91 } 92 93 ud = &object.Userdata{ 94 Value: c, 95 } 96 97 return []object.Value{ud}, nil 98 } 99 100 func wrap(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 101 ap := fnutil.NewArgParser(th, args) 102 103 fn, err := ap.ToFunction(0) 104 if err != nil { 105 return nil, err 106 } 107 108 th1 := th.NewGoThread() 109 110 th1.LoadFunc(fn) 111 112 retfn := func(_ object.Thread, args1 ...object.Value) ([]object.Value, *object.RuntimeError) { 113 rets, err := th1.Resume(args1...) 114 if err != nil { 115 return nil, err 116 } 117 118 return rets, nil 119 } 120 121 return []object.Value{object.GoFunction(retfn)}, nil 122 } 123 124 func Open(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 125 m := th.NewTableSize(0, 4) 126 127 m.Set(object.String("newchannel"), object.GoFunction(newchannel)) 128 m.Set(object.String("select"), object.GoFunction(_select)) 129 m.Set(object.String("case"), object.GoFunction(_case)) 130 m.Set(object.String("wrap"), object.GoFunction(wrap)) 131 132 return []object.Value{m}, nil 133 }