@@ -2280,6 +2280,7 @@ func builtinExtVar(i *interpreter, name value) (value, error) {
2280
2280
func builtinMinArray (i * interpreter , arguments []value ) (value , error ) {
2281
2281
arrv := arguments [0 ]
2282
2282
keyFv := arguments [1 ]
2283
+ onEmpty := arguments [2 ]
2283
2284
2284
2285
arr , err := i .getArray (arrv )
2285
2286
if err != nil {
@@ -2291,7 +2292,11 @@ func builtinMinArray(i *interpreter, arguments []value) (value, error) {
2291
2292
}
2292
2293
num := arr .length ()
2293
2294
if num == 0 {
2294
- return nil , i .Error ("Expected at least one element in array. Got none" )
2295
+ if onEmpty == nil {
2296
+ return nil , i .Error ("Expected at least one element in array. Got none" )
2297
+ } else {
2298
+ return onEmpty , nil
2299
+ }
2295
2300
}
2296
2301
minVal , err := arr .elements [0 ].getValue (i )
2297
2302
if err != nil {
@@ -2325,6 +2330,7 @@ func builtinMinArray(i *interpreter, arguments []value) (value, error) {
2325
2330
func builtinMaxArray (i * interpreter , arguments []value ) (value , error ) {
2326
2331
arrv := arguments [0 ]
2327
2332
keyFv := arguments [1 ]
2333
+ onEmpty := arguments [2 ]
2328
2334
2329
2335
arr , err := i .getArray (arrv )
2330
2336
if err != nil {
@@ -2336,7 +2342,11 @@ func builtinMaxArray(i *interpreter, arguments []value) (value, error) {
2336
2342
}
2337
2343
num := arr .length ()
2338
2344
if num == 0 {
2339
- return nil , i .Error ("Expected at least one element in array. Got none" )
2345
+ if onEmpty == nil {
2346
+ return nil , i .Error ("Expected at least one element in array. Got none" )
2347
+ } else {
2348
+ return onEmpty , nil
2349
+ }
2340
2350
}
2341
2351
maxVal , err := arr .elements [0 ].getValue (i )
2342
2352
if err != nil {
@@ -2533,7 +2543,7 @@ func flattenArgs(args callArguments, params []namedParameter, defaults []value)
2533
2543
}
2534
2544
// Bind defaults for unsatisfied named parameters
2535
2545
for i := range params {
2536
- if flatArgs [i ] == nil {
2546
+ if flatArgs [i ] == nil && defaults [ i ] != nil {
2537
2547
flatArgs [i ] = readyThunk (defaults [i ])
2538
2548
}
2539
2549
}
@@ -2551,9 +2561,13 @@ type unaryBuiltin struct {
2551
2561
func (b * unaryBuiltin ) evalCall (args callArguments , i * interpreter ) (value , error ) {
2552
2562
flatArgs := flattenArgs (args , b .parameters (), []value {})
2553
2563
2554
- x , err := flatArgs [0 ].getValue (i )
2555
- if err != nil {
2556
- return nil , err
2564
+ var x value
2565
+ var err error
2566
+ if flatArgs [0 ] != nil {
2567
+ x , err = flatArgs [0 ].getValue (i )
2568
+ if err != nil {
2569
+ return nil , err
2570
+ }
2557
2571
}
2558
2572
return b .function (i , x )
2559
2573
}
@@ -2581,13 +2595,19 @@ type binaryBuiltin struct {
2581
2595
func (b * binaryBuiltin ) evalCall (args callArguments , i * interpreter ) (value , error ) {
2582
2596
flatArgs := flattenArgs (args , b .parameters (), []value {})
2583
2597
2584
- x , err := flatArgs [0 ].getValue (i )
2585
- if err != nil {
2586
- return nil , err
2598
+ var err error
2599
+ var x , y value
2600
+ if flatArgs [0 ] != nil {
2601
+ x , err = flatArgs [0 ].getValue (i )
2602
+ if err != nil {
2603
+ return nil , err
2604
+ }
2587
2605
}
2588
- y , err := flatArgs [1 ].getValue (i )
2589
- if err != nil {
2590
- return nil , err
2606
+ if flatArgs [1 ] != nil {
2607
+ y , err = flatArgs [1 ].getValue (i )
2608
+ if err != nil {
2609
+ return nil , err
2610
+ }
2591
2611
}
2592
2612
return b .function (i , x , y )
2593
2613
}
@@ -2615,17 +2635,25 @@ type ternaryBuiltin struct {
2615
2635
func (b * ternaryBuiltin ) evalCall (args callArguments , i * interpreter ) (value , error ) {
2616
2636
flatArgs := flattenArgs (args , b .parameters (), []value {})
2617
2637
2618
- x , err := flatArgs [0 ].getValue (i )
2619
- if err != nil {
2620
- return nil , err
2638
+ var err error
2639
+ var x , y , z value
2640
+ if flatArgs [0 ] != nil {
2641
+ x , err = flatArgs [0 ].getValue (i )
2642
+ if err != nil {
2643
+ return nil , err
2644
+ }
2621
2645
}
2622
- y , err := flatArgs [1 ].getValue (i )
2623
- if err != nil {
2624
- return nil , err
2646
+ if flatArgs [1 ] != nil {
2647
+ y , err = flatArgs [1 ].getValue (i )
2648
+ if err != nil {
2649
+ return nil , err
2650
+ }
2625
2651
}
2626
- z , err := flatArgs [2 ].getValue (i )
2627
- if err != nil {
2628
- return nil , err
2652
+ if flatArgs [2 ] != nil {
2653
+ z , err = flatArgs [2 ].getValue (i )
2654
+ if err != nil {
2655
+ return nil , err
2656
+ }
2629
2657
}
2630
2658
return b .function (i , x , y , z )
2631
2659
}
@@ -2647,8 +2675,9 @@ type generalBuiltinFunc func(*interpreter, []value) (value, error)
2647
2675
type generalBuiltinParameter struct {
2648
2676
// Note that the defaults are passed as values rather than AST nodes like in Parameters.
2649
2677
// This spares us unnecessary evaluation.
2650
- defaultValue value
2651
- name ast.Identifier
2678
+ defaultValue value
2679
+ name ast.Identifier
2680
+ nonValueDefault bool
2652
2681
}
2653
2682
2654
2683
// generalBuiltin covers cases that other builtin structures do not,
@@ -2665,7 +2694,7 @@ func (b *generalBuiltin) parameters() []namedParameter {
2665
2694
ret := make ([]namedParameter , len (b .params ))
2666
2695
for i := range ret {
2667
2696
ret [i ].name = b .params [i ].name
2668
- if b .params [i ].defaultValue != nil {
2697
+ if b .params [i ].defaultValue != nil || b . params [ i ]. nonValueDefault {
2669
2698
// This is not actually used because the defaultValue is used instead.
2670
2699
// The only reason we don't leave it nil is because the checkArguments
2671
2700
// function uses the non-nil status to indicate that the parameter
@@ -2693,9 +2722,11 @@ func (b *generalBuiltin) evalCall(args callArguments, i *interpreter) (value, er
2693
2722
values := make ([]value , len (flatArgs ))
2694
2723
for j := 0 ; j < len (values ); j ++ {
2695
2724
var err error
2696
- values [j ], err = flatArgs [j ].getValue (i )
2697
- if err != nil {
2698
- return nil , err
2725
+ if flatArgs [j ] != nil {
2726
+ values [j ], err = flatArgs [j ].getValue (i )
2727
+ if err != nil {
2728
+ return nil , err
2729
+ }
2699
2730
}
2700
2731
}
2701
2732
return b .function (i , values )
@@ -2840,8 +2871,8 @@ var funcBuiltins = buildBuiltinMap([]builtin{
2840
2871
& unaryBuiltin {name : "encodeUTF8" , function : builtinEncodeUTF8 , params : ast.Identifiers {"str" }},
2841
2872
& unaryBuiltin {name : "decodeUTF8" , function : builtinDecodeUTF8 , params : ast.Identifiers {"arr" }},
2842
2873
& generalBuiltin {name : "sort" , function : builtinSort , params : []generalBuiltinParameter {{name : "arr" }, {name : "keyF" , defaultValue : functionID }}},
2843
- & generalBuiltin {name : "minArray" , function : builtinMinArray , params : []generalBuiltinParameter {{name : "arr" }, {name : "keyF" , defaultValue : functionID }}},
2844
- & generalBuiltin {name : "maxArray" , function : builtinMaxArray , params : []generalBuiltinParameter {{name : "arr" }, {name : "keyF" , defaultValue : functionID }}},
2874
+ & generalBuiltin {name : "minArray" , function : builtinMinArray , params : []generalBuiltinParameter {{name : "arr" }, {name : "keyF" , defaultValue : functionID }, { name : "onEmpty" , nonValueDefault : true } }},
2875
+ & generalBuiltin {name : "maxArray" , function : builtinMaxArray , params : []generalBuiltinParameter {{name : "arr" }, {name : "keyF" , defaultValue : functionID }, { name : "onEmpty" , nonValueDefault : true } }},
2845
2876
& unaryBuiltin {name : "native" , function : builtinNative , params : ast.Identifiers {"x" }},
2846
2877
& unaryBuiltin {name : "sum" , function : builtinSum , params : ast.Identifiers {"arr" }},
2847
2878
& unaryBuiltin {name : "avg" , function : builtinAvg , params : ast.Identifiers {"arr" }},
0 commit comments