// Find a way to improve this mess package flow import ( "errors" "reflect" ) type operation interface { fref() ref Process(params ...Data) Data } // Ref and cacher? // common operation type ref struct { flow *Flow // Type? serializable ID int `json:"id"` } // ref ref ref func (r ref) fref() ref { return r } func typeName(o operation) string { switch o.(type) { case OpIn: return "in" case OpVar: return "data" case OpConst: return "const" case OpFunc: return "func" } return "" } type OpIn struct{ ref } type OpVar struct{ ref } type OpConst struct{ ref } type OpFunc struct{ ref } func (o OpIn) Process(p ...Data) Data { if o.ID >= len(p) || o.ID < 0 { o.flow.err = errors.New("Invalid input") return nil } return p[o.ID] } func (o OpVar) Process(...Data) Data { return o.flow.data[o.ID] } // Get // Set variable set func (o OpVar) Set(value Data) { o.flow.data[o.ID] = value } // OpConst const operator func (o OpConst) Process(...Data) Data { return o.flow.consts[o.ID] } // Get // Make this else where? func (o OpFunc) Process(params ...Data) Data { op := o.flow.operations[o.ID] // Grab operation inputs from flow callParam := make([]reflect.Value, len(op.inputs)) for i, in := range op.inputs { switch v := in.(type) { case operation: callParam[i] = reflect.ValueOf(v.Process(params...)) default: // {lpf} Analyse this panic(errors.New("Is not operation")) } } return reflect.ValueOf(op.executor).Call(callParam)[0].Interface() }