123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- package seq
- import (
- "fmt"
- "log"
- "reflect"
- )
- type SeqFunc func(s *Seq) error
- type Entry struct {
- desc string
- fn reflect.Value
- seqFn SeqFunc
- param []SeqParam
- ret []reflect.Value
- grab []reflect.Value
- }
- type SeqParam struct {
- typ byte
- nres int
- ires int
- // Or
- param reflect.Value
- }
- func P(n, i int) SeqParam {
- return SeqParam{1, n, i, reflect.Value{}}
- }
- func EP(n int) SeqParam {
- return SeqParam{2, n, 0, reflect.Value{}}
- }
- type Seq struct {
- seq []*Entry
- last *Entry
- vars map[string]interface{}
- rep []string
- }
- func New() *Seq {
- return &Seq{[]*Entry{}, nil, map[string]interface{}{}, 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.(SeqFunc); ok {
- 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 := []SeqParam{}
- for _, p := range params[fni+1:] {
- sp := SeqParam{}
- switch v := p.(type) {
- case SeqParam:
- 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) Log(param...interface{){
- }
- func (s *Seq) Exec(eparam ...interface{}) error {
- s.rep = []string{}
- for _, e := range s.seq {
- if e.seqFn != nil {
- err := e.seqFn(s)
- if err != nil {
- return err
- }
- }
- param := []reflect.Value{}
- for _, p := range e.param {
- var val reflect.Value
- switch p.typ {
- case 0:
- val = p.param
- case 1:
- val = s.seq[p.nres].ret[p.ires]
- case 2:
- val = reflect.Indirect(reflect.ValueOf(eparam[p.nres]))
- }
- param = append(param, val)
- }
- e.ret = e.fn.Call(param)
- for i, r := range e.ret { // Populate grabs
- if i < len(e.grab) {
- e.grab[i].Elem().Set(r)
- }
- if err, ok := r.Interface().(error); ok {
- return err
- }
- }
- if e.desc != "" { // Only if we have a description
- iret := []interface{}{}
- for _, r := range e.ret {
- iret = append(iret, reflect.Indirect(r).Interface())
- }
- s.rep = append(s.rep, fmt.Sprintf("E: %s => %s", e.desc, iret))
- }
- }
- log.Println("Report:")
- for _, r := range s.rep {
- log.Println(r)
- }
- return nil
- }
|