perf: use native builtin for foldl and foldr

benchmark                                 old ns/op      new ns/op      delta
Benchmark_Builtin_substr-8                17914126       16328579       -8.85%
Benchmark_Builtin_reverse-8               360776847      346691957      -3.90%
Benchmark_Builtin_parseInt-8              8686867        8314151        -4.29%
Benchmark_Builtin_base64Decode-8          22157223       21749268       -1.84%
Benchmark_Builtin_base64DecodeBytes-8     281975629      281841745      -0.05%
Benchmark_Builtin_base64-8                23824149       23716470       -0.45%
Benchmark_Builtin_base64_byte_array-8     141846327      141377054      -0.33%
Benchmark_Builtin_manifestJsonEx-8        9317781        9279067        -0.42%
Benchmark_Builtin_comparison-8            128783954      128362069      -0.33%
Benchmark_Builtin_comparison2-8           2082396660     2029123362     -2.56%
Benchmark_Builtin_foldl-8                 159908963      31278937       -80.44%
This commit is contained in:
Jesse-Cameron 2022-09-20 16:09:11 +10:00 committed by Stanisław Barzowski
parent 953327b03c
commit e9a59202cf

View File

@ -396,6 +396,68 @@ func builtinJoin(i *interpreter, sep, arrv value) (value, error) {
}
}
func builtinFoldl(i *interpreter, funcv, arrv, initv value) (value, error) {
fun, err := i.getFunction(funcv)
if err != nil {
return nil, err
}
var len int
var elements []*cachedThunk
switch arrType := arrv.(type) {
case valueString:
len = arrType.length()
for _, item := range arrType.getRunes() {
elements = append(elements, readyThunk(makeStringFromRunes([]rune{item})))
}
case *valueArray:
len = arrType.length()
elements = arrType.elements
default:
return nil, i.Error("foldl second parameter should be string or array, got " + arrType.getType().name)
}
accValue := initv
for counter := 0; counter < len; counter++ {
accValue, err = fun.call(i, args([]*cachedThunk{readyThunk(accValue), elements[counter]}...))
if err != nil {
return nil, err
}
}
return accValue, nil
}
func builtinFoldr(i *interpreter, funcv, arrv, initv value) (value, error) {
fun, err := i.getFunction(funcv)
if err != nil {
return nil, err
}
var len int
var elements []*cachedThunk
switch arrType := arrv.(type) {
case valueString:
len = arrType.length()
for _, item := range arrType.getRunes() {
elements = append(elements, readyThunk(makeStringFromRunes([]rune{item})))
}
case *valueArray:
len = arrType.length()
elements = arrType.elements
default:
return nil, i.Error("foldr second parameter should be string or array, got " + arrType.getType().name)
}
accValue := initv
for counter := len - 1; counter >= 0; counter-- {
accValue, err = fun.call(i, args([]*cachedThunk{elements[counter], readyThunk(accValue)}...))
if err != nil {
return nil, err
}
}
return accValue, nil
}
func builtinReverse(i *interpreter, arrv value) (value, error) {
arr, err := i.getArray(arrv)
if err != nil {
@ -1636,6 +1698,8 @@ var funcBuiltins = buildBuiltinMap([]builtin{
&binaryBuiltin{name: "join", function: builtinJoin, params: ast.Identifiers{"sep", "arr"}},
&unaryBuiltin{name: "reverse", function: builtinReverse, params: ast.Identifiers{"arr"}},
&binaryBuiltin{name: "filter", function: builtinFilter, params: ast.Identifiers{"func", "arr"}},
&ternaryBuiltin{name: "foldl", function: builtinFoldl, params: ast.Identifiers{"func", "arr", "init"}},
&ternaryBuiltin{name: "foldr", function: builtinFoldr, params: ast.Identifiers{"func", "arr", "init"}},
&binaryBuiltin{name: "range", function: builtinRange, params: ast.Identifiers{"from", "to"}},
&binaryBuiltin{name: "primitiveEquals", function: primitiveEquals, params: ast.Identifiers{"x", "y"}},
&binaryBuiltin{name: "equals", function: builtinEquals, params: ast.Identifiers{"x", "y"}},