15 type jpFunction func(arguments []interface{}) (interface{}, error)
20 jpUnknown jpType = "unknown"
21 jpNumber jpType = "number"
22 jpString jpType = "string"
23 jpArray jpType = "array"
24 jpObject jpType = "object"
25 jpArrayNumber jpType = "array[number]"
26 jpArrayString jpType = "array[string]"
27 jpExpref jpType = "expref"
31 type functionEntry struct {
43 type byExprString struct {
50 func (a *byExprString) Len() int {
53 func (a *byExprString) Swap(i, j int) {
54 a.items[i], a.items[j] = a.items[j], a.items[i]
56 func (a *byExprString) Less(i, j int) bool {
57 first, err := a.intr.Execute(a.node, a.items[i])
60 // Return a dummy value.
63 ith, ok := first.(string)
68 second, err := a.intr.Execute(a.node, a.items[j])
71 // Return a dummy value.
74 jth, ok := second.(string)
82 type byExprFloat struct {
89 func (a *byExprFloat) Len() int {
92 func (a *byExprFloat) Swap(i, j int) {
93 a.items[i], a.items[j] = a.items[j], a.items[i]
95 func (a *byExprFloat) Less(i, j int) bool {
96 first, err := a.intr.Execute(a.node, a.items[i])
99 // Return a dummy value.
102 ith, ok := first.(float64)
107 second, err := a.intr.Execute(a.node, a.items[j])
110 // Return a dummy value.
113 jth, ok := second.(float64)
121 type functionCaller struct {
122 functionTable map[string]functionEntry
125 func newFunctionCaller() *functionCaller {
126 caller := &functionCaller{}
127 caller.functionTable = map[string]functionEntry{
130 arguments: []argSpec{
131 {types: []jpType{jpString, jpArray, jpObject}},
137 arguments: []argSpec{
138 {types: []jpType{jpString}},
139 {types: []jpType{jpString}},
141 handler: jpfStartsWith,
145 arguments: []argSpec{
146 {types: []jpType{jpNumber}},
152 arguments: []argSpec{
153 {types: []jpType{jpArrayNumber}},
159 arguments: []argSpec{
160 {types: []jpType{jpNumber}},
166 arguments: []argSpec{
167 {types: []jpType{jpArray, jpString}},
168 {types: []jpType{jpAny}},
170 handler: jpfContains,
174 arguments: []argSpec{
175 {types: []jpType{jpString}},
176 {types: []jpType{jpString}},
178 handler: jpfEndsWith,
182 arguments: []argSpec{
183 {types: []jpType{jpNumber}},
189 arguments: []argSpec{
190 {types: []jpType{jpExpref}},
191 {types: []jpType{jpArray}},
198 arguments: []argSpec{
199 {types: []jpType{jpArrayNumber, jpArrayString}},
205 arguments: []argSpec{
206 {types: []jpType{jpObject}, variadic: true},
212 arguments: []argSpec{
213 {types: []jpType{jpArray}},
214 {types: []jpType{jpExpref}},
221 arguments: []argSpec{
222 {types: []jpType{jpArrayNumber}},
228 arguments: []argSpec{
229 {types: []jpType{jpArrayNumber, jpArrayString}},
235 arguments: []argSpec{
236 {types: []jpType{jpArray}},
237 {types: []jpType{jpExpref}},
244 arguments: []argSpec{
245 {types: []jpType{jpAny}},
251 arguments: []argSpec{
252 {types: []jpType{jpObject}},
258 arguments: []argSpec{
259 {types: []jpType{jpObject}},
265 arguments: []argSpec{
266 {types: []jpType{jpArrayString, jpArrayNumber}},
272 arguments: []argSpec{
273 {types: []jpType{jpArray}},
274 {types: []jpType{jpExpref}},
281 arguments: []argSpec{
282 {types: []jpType{jpString}},
283 {types: []jpType{jpArrayString}},
289 arguments: []argSpec{
290 {types: []jpType{jpArray, jpString}},
296 arguments: []argSpec{
297 {types: []jpType{jpAny}},
303 arguments: []argSpec{
304 {types: []jpType{jpAny}},
306 handler: jpfToString,
310 arguments: []argSpec{
311 {types: []jpType{jpAny}},
313 handler: jpfToNumber,
317 arguments: []argSpec{
318 {types: []jpType{jpAny}, variadic: true},
326 func (e *functionEntry) resolveArgs(arguments []interface{}) ([]interface{}, error) {
327 if len(e.arguments) == 0 {
328 return arguments, nil
330 if !e.arguments[len(e.arguments)-1].variadic {
331 if len(e.arguments) != len(arguments) {
332 return nil, errors.New("incorrect number of args")
334 for i, spec := range e.arguments {
335 userArg := arguments[i]
336 err := spec.typeCheck(userArg)
341 return arguments, nil
343 if len(arguments) < len(e.arguments) {
344 return nil, errors.New("Invalid arity.")
346 return arguments, nil
349 func (a *argSpec) typeCheck(arg interface{}) error {
350 for _, t := range a.types {
353 if _, ok := arg.(float64); ok {
357 if _, ok := arg.(string); ok {
361 if isSliceType(arg) {
365 if _, ok := arg.(map[string]interface{}); ok {
369 if _, ok := toArrayNum(arg); ok {
373 if _, ok := toArrayStr(arg); ok {
379 if _, ok := arg.(expRef); ok {
384 return fmt.Errorf("Invalid type for: %v, expected: %#v", arg, a.types)
387 func (f *functionCaller) CallFunction(name string, arguments []interface{}, intr *treeInterpreter) (interface{}, error) {
388 entry, ok := f.functionTable[name]
390 return nil, errors.New("unknown function: " + name)
392 resolvedArgs, err := entry.resolveArgs(arguments)
397 var extra []interface{}
398 extra = append(extra, intr)
399 resolvedArgs = append(extra, resolvedArgs...)
401 return entry.handler(resolvedArgs)
404 func jpfAbs(arguments []interface{}) (interface{}, error) {
405 num := arguments[0].(float64)
406 return math.Abs(num), nil
409 func jpfLength(arguments []interface{}) (interface{}, error) {
411 if c, ok := arg.(string); ok {
412 return float64(utf8.RuneCountInString(c)), nil
413 } else if isSliceType(arg) {
414 v := reflect.ValueOf(arg)
415 return float64(v.Len()), nil
416 } else if c, ok := arg.(map[string]interface{}); ok {
417 return float64(len(c)), nil
419 return nil, errors.New("could not compute length()")
422 func jpfStartsWith(arguments []interface{}) (interface{}, error) {
423 search := arguments[0].(string)
424 prefix := arguments[1].(string)
425 return strings.HasPrefix(search, prefix), nil
428 func jpfAvg(arguments []interface{}) (interface{}, error) {
429 // We've already type checked the value so we can safely use
431 args := arguments[0].([]interface{})
432 length := float64(len(args))
434 for _, n := range args {
435 numerator += n.(float64)
437 return numerator / length, nil
439 func jpfCeil(arguments []interface{}) (interface{}, error) {
440 val := arguments[0].(float64)
441 return math.Ceil(val), nil
443 func jpfContains(arguments []interface{}) (interface{}, error) {
444 search := arguments[0]
446 if searchStr, ok := search.(string); ok {
447 if elStr, ok := el.(string); ok {
448 return strings.Index(searchStr, elStr) != -1, nil
452 // Otherwise this is a generic contains for []interface{}
453 general := search.([]interface{})
454 for _, item := range general {
461 func jpfEndsWith(arguments []interface{}) (interface{}, error) {
462 search := arguments[0].(string)
463 suffix := arguments[1].(string)
464 return strings.HasSuffix(search, suffix), nil
466 func jpfFloor(arguments []interface{}) (interface{}, error) {
467 val := arguments[0].(float64)
468 return math.Floor(val), nil
470 func jpfMap(arguments []interface{}) (interface{}, error) {
471 intr := arguments[0].(*treeInterpreter)
472 exp := arguments[1].(expRef)
474 arr := arguments[2].([]interface{})
475 mapped := make([]interface{}, 0, len(arr))
476 for _, value := range arr {
477 current, err := intr.Execute(node, value)
481 mapped = append(mapped, current)
485 func jpfMax(arguments []interface{}) (interface{}, error) {
486 if items, ok := toArrayNum(arguments[0]); ok {
494 for _, item := range items[1:] {
501 // Otherwise we're dealing with a max() of strings.
502 items, _ := toArrayStr(arguments[0])
510 for _, item := range items[1:] {
517 func jpfMerge(arguments []interface{}) (interface{}, error) {
518 final := make(map[string]interface{})
519 for _, m := range arguments {
520 mapped := m.(map[string]interface{})
521 for key, value := range mapped {
527 func jpfMaxBy(arguments []interface{}) (interface{}, error) {
528 intr := arguments[0].(*treeInterpreter)
529 arr := arguments[1].([]interface{})
530 exp := arguments[2].(expRef)
534 } else if len(arr) == 1 {
537 start, err := intr.Execute(node, arr[0])
541 switch t := start.(type) {
545 for _, item := range arr[1:] {
546 result, err := intr.Execute(node, item)
550 current, ok := result.(float64)
552 return nil, errors.New("invalid type, must be number")
554 if current > bestVal {
563 for _, item := range arr[1:] {
564 result, err := intr.Execute(node, item)
568 current, ok := result.(string)
570 return nil, errors.New("invalid type, must be string")
572 if current > bestVal {
579 return nil, errors.New("invalid type, must be number of string")
582 func jpfSum(arguments []interface{}) (interface{}, error) {
583 items, _ := toArrayNum(arguments[0])
585 for _, item := range items {
591 func jpfMin(arguments []interface{}) (interface{}, error) {
592 if items, ok := toArrayNum(arguments[0]); ok {
600 for _, item := range items[1:] {
607 items, _ := toArrayStr(arguments[0])
615 for _, item := range items[1:] {
623 func jpfMinBy(arguments []interface{}) (interface{}, error) {
624 intr := arguments[0].(*treeInterpreter)
625 arr := arguments[1].([]interface{})
626 exp := arguments[2].(expRef)
630 } else if len(arr) == 1 {
633 start, err := intr.Execute(node, arr[0])
637 if t, ok := start.(float64); ok {
640 for _, item := range arr[1:] {
641 result, err := intr.Execute(node, item)
645 current, ok := result.(float64)
647 return nil, errors.New("invalid type, must be number")
649 if current < bestVal {
655 } else if t, ok := start.(string); ok {
658 for _, item := range arr[1:] {
659 result, err := intr.Execute(node, item)
663 current, ok := result.(string)
665 return nil, errors.New("invalid type, must be string")
667 if current < bestVal {
674 return nil, errors.New("invalid type, must be number of string")
677 func jpfType(arguments []interface{}) (interface{}, error) {
679 if _, ok := arg.(float64); ok {
682 if _, ok := arg.(string); ok {
685 if _, ok := arg.([]interface{}); ok {
688 if _, ok := arg.(map[string]interface{}); ok {
694 if arg == true || arg == false {
695 return "boolean", nil
697 return nil, errors.New("unknown type")
699 func jpfKeys(arguments []interface{}) (interface{}, error) {
700 arg := arguments[0].(map[string]interface{})
701 collected := make([]interface{}, 0, len(arg))
702 for key := range arg {
703 collected = append(collected, key)
705 return collected, nil
707 func jpfValues(arguments []interface{}) (interface{}, error) {
708 arg := arguments[0].(map[string]interface{})
709 collected := make([]interface{}, 0, len(arg))
710 for _, value := range arg {
711 collected = append(collected, value)
713 return collected, nil
715 func jpfSort(arguments []interface{}) (interface{}, error) {
716 if items, ok := toArrayNum(arguments[0]); ok {
717 d := sort.Float64Slice(items)
719 final := make([]interface{}, len(d))
720 for i, val := range d {
725 // Otherwise we're dealing with sort()'ing strings.
726 items, _ := toArrayStr(arguments[0])
727 d := sort.StringSlice(items)
729 final := make([]interface{}, len(d))
730 for i, val := range d {
735 func jpfSortBy(arguments []interface{}) (interface{}, error) {
736 intr := arguments[0].(*treeInterpreter)
737 arr := arguments[1].([]interface{})
738 exp := arguments[2].(expRef)
742 } else if len(arr) == 1 {
745 start, err := intr.Execute(node, arr[0])
749 if _, ok := start.(float64); ok {
750 sortable := &byExprFloat{intr, node, arr, false}
751 sort.Stable(sortable)
752 if sortable.hasError {
753 return nil, errors.New("error in sort_by comparison")
756 } else if _, ok := start.(string); ok {
757 sortable := &byExprString{intr, node, arr, false}
758 sort.Stable(sortable)
759 if sortable.hasError {
760 return nil, errors.New("error in sort_by comparison")
764 return nil, errors.New("invalid type, must be number of string")
767 func jpfJoin(arguments []interface{}) (interface{}, error) {
768 sep := arguments[0].(string)
769 // We can't just do arguments[1].([]string), we have to
770 // manually convert each item to a string.
771 arrayStr := []string{}
772 for _, item := range arguments[1].([]interface{}) {
773 arrayStr = append(arrayStr, item.(string))
775 return strings.Join(arrayStr, sep), nil
777 func jpfReverse(arguments []interface{}) (interface{}, error) {
778 if s, ok := arguments[0].(string); ok {
780 for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
781 r[i], r[j] = r[j], r[i]
783 return string(r), nil
785 items := arguments[0].([]interface{})
787 reversed := make([]interface{}, length)
788 for i, item := range items {
789 reversed[length-(i+1)] = item
793 func jpfToArray(arguments []interface{}) (interface{}, error) {
794 if _, ok := arguments[0].([]interface{}); ok {
795 return arguments[0], nil
797 return arguments[:1:1], nil
799 func jpfToString(arguments []interface{}) (interface{}, error) {
800 if v, ok := arguments[0].(string); ok {
803 result, err := json.Marshal(arguments[0])
807 return string(result), nil
809 func jpfToNumber(arguments []interface{}) (interface{}, error) {
811 if v, ok := arg.(float64); ok {
814 if v, ok := arg.(string); ok {
815 conv, err := strconv.ParseFloat(v, 64)
821 if _, ok := arg.([]interface{}); ok {
824 if _, ok := arg.(map[string]interface{}); ok {
830 if arg == true || arg == false {
833 return nil, errors.New("unknown type")
835 func jpfNotNull(arguments []interface{}) (interface{}, error) {
836 for _, arg := range arguments {