func trim(f interface{}) (interface{}, error) { if reflect.TypeOf(f).Implements(varTyp) { return f, nil } if reflect.TypeOf(f).Implements(constTyp) { return f, nil } this := reflect.ValueOf(f).Elem() trimable := true for i := 0; i < this.NumField(); i++ { var trimmed interface{} var err error if this.Field(i).Type().Kind() == reflect.Slice { if _, ok := this.Field(i).Type().Elem().MethodByName("Eval"); ok { trimable = false } } if _, ok := this.Field(i).Type().MethodByName("Eval"); !ok { continue } if this.Field(i).Elem().Type().Implements(varTyp) { if funcs.IsConst(this.Field(i).Type()) { return nil, &errNotConst{f, this.Field(i)} } trimable = false continue } if this.Field(i).Elem().Type().Implements(listOfTyp) { trimmed, err = trimList(this.Field(i).Interface()) } else { trimmed, err = trim(this.Field(i).Interface()) } if err != nil { return nil, err } this.Field(i).Set(reflect.ValueOf(trimmed)) if !this.Field(i).Elem().Type().Implements(constTyp) { if funcs.IsConst(this.Field(i).Type()) { return nil, &errNotConst{f, this.Field(i)} } trimable = false } } if !trimable { return f, nil } if inits, ok := f.(funcs.Init); ok { err := inits.Init() if err != nil { return nil, err } } return funcs.NewConst(reflect.ValueOf(f).MethodByName("Eval").Call(nil)[0].Interface()), nil }
func trimList(f interface{}) (interface{}, error) { this := reflect.ValueOf(f).Elem() list := this.Field(0) newList := reflect.MakeSlice(list.Type(), list.Len(), list.Len()) trimable := true for i := 0; i < list.Len(); i++ { trimmed, err := trim(list.Index(i).Interface()) if err != nil { return nil, err } trimmedValue := reflect.ValueOf(trimmed) newList.Index(i).Set(trimmedValue) if !trimmedValue.Type().Implements(constTyp) { trimable = false } } this.Field(0).Set(newList) if !trimable { return f, nil } return funcs.NewConst(reflect.ValueOf(f).MethodByName("Eval").Call(nil)[0].Interface()), nil }