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  }