func (e *State) walkFunc(node *parse.FuncNode, T miniprofiler.Timer) *Results { var res *Results T.Step("func: "+node.Name, func(T miniprofiler.Timer) { var in []reflect.Value for i, a := range node.Args { var v interface{} switch t := a.(type) { case *parse.StringNode: v = t.Text case *parse.NumberNode: v = t.Float64 case *parse.FuncNode: v = extract(e.walkFunc(t, T)) case *parse.UnaryNode: v = extract(e.walkUnary(t, T)) case *parse.BinaryNode: v = extract(e.walkBinary(t, T)) case *parse.ExprNode: v = e.walkExpr(t, T) default: panic(fmt.Errorf("expr: unknown func arg type")) } var argType models.FuncType if i >= len(node.F.Args) { if !node.F.VArgs { panic("expr: shouldn't be here, more args then expected and not variable argument type func") } argType = node.F.Args[node.F.VArgsPos] } else { argType = node.F.Args[i] } if f, ok := v.(float64); ok && argType == models.TypeNumberSet { v = fromScalar(f) } in = append(in, reflect.ValueOf(v)) } f := reflect.ValueOf(node.F.F) fr := f.Call(append([]reflect.Value{reflect.ValueOf(e), reflect.ValueOf(T)}, in...)) res = fr[0].Interface().(*Results) if len(fr) > 1 && !fr[1].IsNil() { err := fr[1].Interface().(error) if err != nil { panic(err) } } if node.Return() == models.TypeNumberSet { for _, r := range res.Results { e.AddComputation(r, node.String(), r.Value.(Number)) } } }) return res }
func (e *State) walkFunc(node *parse.FuncNode, T miniprofiler.Timer) *Results { var res *Results T.Step("func: "+node.Name, func(T miniprofiler.Timer) { var in []reflect.Value for i, a := range node.Args { var v interface{} switch t := a.(type) { case *parse.StringNode: v = t.Text case *parse.NumberNode: v = t.Float64 case *parse.FuncNode: v = extract(e.walkFunc(t, T)) case *parse.UnaryNode: v = extract(e.walkUnary(t, T)) case *parse.BinaryNode: v = extract(e.walkBinary(t, T)) default: panic(fmt.Errorf("expr: unknown func arg type")) } if f, ok := v.(float64); ok && node.F.Args[i] == parse.TypeNumberSet { v = fromScalar(f) } in = append(in, reflect.ValueOf(v)) } f := reflect.ValueOf(node.F.F) fr := f.Call(append([]reflect.Value{reflect.ValueOf(e), reflect.ValueOf(T)}, in...)) res = fr[0].Interface().(*Results) if len(fr) > 1 && !fr[1].IsNil() { err := fr[1].Interface().(error) if err != nil { panic(err) } } if node.Return() == parse.TypeNumberSet { for _, r := range res.Results { e.AddComputation(r, node.String(), r.Value.(Number)) } } }) return res }