123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- package seq
- import (
- "reflect"
- "dev.hexasoftware.com/hxs/prettylog"
- )
- var (
- log = prettylog.New("Seq")
- )
- type Entry struct {
- desc string
- fn reflect.Value
- seqFn func(sc *Context) error
- param []Param
- grab []reflect.Value
- }
- // Helper
- type Seq struct {
- seq []*Entry
- last *Entry
- }
- func NewSeq() *Seq {
- return &Seq{[]*Entry{}, nil}
- }
- func (s *Seq) Add(params ...interface{}) *Seq {
- entry := &Entry{}
- fni := 0
- if v, ok := params[0].(string); ok {
- entry.desc = v
- fni = 1
- }
- fn := params[fni]
- if v, ok := fn.(func(s *Context) error); ok {
- log.Println("Special func")
- entry.seqFn = v
- } else {
- entry.fn = reflect.ValueOf(fn)
- fnTyp := reflect.TypeOf(fn)
- if fnTyp.Kind() != reflect.Func {
- log.Fatal("First param must be a function")
- }
- vparam := []Param{}
- for _, p := range params[fni+1:] {
- sp := Param{}
- switch v := p.(type) {
- case Param:
- sp = v
- default:
- sp.typ = 0
- sp.param = reflect.ValueOf(p)
- }
- vparam = append(vparam, sp)
- }
- entry.param = vparam
- }
- s.seq = append(s.seq, entry)
- s.last = entry
- return s
- }
- func (s *Seq) Grab(grab ...interface{}) {
- if s.last == nil {
- return
- }
- for _, g := range grab {
- gv := reflect.ValueOf(g)
- if gv.Kind() != reflect.Ptr {
- panic("Grab should be pointer")
- }
- s.last.grab = append(s.last.grab, gv)
- }
- }
- func (s *Seq) Exec(eparam ...interface{}) error {
- sCon := NewContext()
- sCon.params = eparam
- for _, e := range s.seq {
- if e.seqFn != nil {
- err := e.seqFn(sCon)
- sCon.Log("E:", e.desc, "=>", err)
- if err != nil {
- return err
- }
- continue
- }
- param := []reflect.Value{}
- for _, p := range e.param {
- var val reflect.Value
- switch p.typ {
- case 0:
- val = p.param
- case 1:
- val = reflect.ValueOf(sCon.Ret(p.nres, p.ires))
- case 2:
- val = reflect.Indirect(reflect.ValueOf(eparam[p.nres]))
- }
- param = append(param, val)
- }
- retVal := e.fn.Call(param)
- iretList := []interface{}{}
- for i, r := range retVal { // Populate grabs
- if i < len(e.grab) {
- e.grab[i].Elem().Set(r)
- }
- iret := r.Interface()
- if err, ok := iret.(error); ok {
- return err
- }
- iretList = append(iretList, iret)
- }
- sCon.ret = append(sCon.ret, iretList)
- if e.desc != "" { // Only if we have a description
- sCon.Log("E:", e.desc, "=>", iretList)
- }
- }
- sCon.LogRep()
- return nil
- }
|