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  }