From 29b1f0807fb1add1e1cd7fac56861b742e77ed63 Mon Sep 17 00:00:00 2001 From: xrstf Date: Sat, 2 Dec 2023 21:22:59 +0100 Subject: [PATCH] split Functions into smaller chunks, make it easier to merge Function sets --- aliases.go | 4 +- docs/embed.go | 2 +- pkg/eval/builtin/comparisons_test.go | 6 +- pkg/eval/builtin/core_test.go | 16 +- pkg/eval/builtin/encoding_test.go | 4 +- pkg/eval/builtin/funcs.go | 243 +++++++++++++++------------ pkg/eval/builtin/hashing_test.go | 6 +- pkg/eval/builtin/lists_test.go | 12 +- pkg/eval/builtin/logic_test.go | 6 +- pkg/eval/builtin/math_test.go | 8 +- pkg/eval/builtin/strings_test.go | 8 +- pkg/eval/builtin/types_test.go | 10 +- pkg/eval/types/context.go | 21 ++- 13 files changed, 198 insertions(+), 148 deletions(-) diff --git a/aliases.go b/aliases.go index 7bc8fa3..44d3af7 100644 --- a/aliases.go +++ b/aliases.go @@ -45,9 +45,9 @@ func NewFunctions() Functions { return types.NewFunctions() } -// NewBuiltInFunctions returns a copy of the built-in Rudi functions. +// NewBuiltInFunctions returns a copy of all the built-in Rudi functions. func NewBuiltInFunctions() Functions { - return builtin.Functions.DeepCopy() + return builtin.AllFunctions.DeepCopy() } // NewVariables returns an empty set of runtime variables. diff --git a/docs/embed.go b/docs/embed.go index 32a71b1..0c04176 100644 --- a/docs/embed.go +++ b/docs/embed.go @@ -50,7 +50,7 @@ func Topics() []Topic { "div": {}, } - for funcName, function := range builtin.Functions { + for funcName, function := range builtin.AllFunctions { if _, ok := ignoredFunctions[funcName]; ok { continue } diff --git a/pkg/eval/builtin/comparisons_test.go b/pkg/eval/builtin/comparisons_test.go index 33a503e..0a7f6e8 100644 --- a/pkg/eval/builtin/comparisons_test.go +++ b/pkg/eval/builtin/comparisons_test.go @@ -208,7 +208,7 @@ func TestEqFunction(t *testing.T) { }) for _, testcase := range append(syntax, flipped...) { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -356,7 +356,7 @@ func TestLikeFunction(t *testing.T) { }) for _, testcase := range append(syntax, testcases...) { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -442,7 +442,7 @@ func TestLtFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } diff --git a/pkg/eval/builtin/core_test.go b/pkg/eval/builtin/core_test.go index ff2c51f..fa47140 100644 --- a/pkg/eval/builtin/core_test.go +++ b/pkg/eval/builtin/core_test.go @@ -71,7 +71,7 @@ func TestIfFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -325,7 +325,7 @@ func TestSetFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -542,7 +542,7 @@ func TestDeleteFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -584,7 +584,7 @@ func TestDoFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -629,7 +629,7 @@ func TestDefaultFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -680,7 +680,7 @@ func TestTryFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -746,7 +746,7 @@ func TestIsEmptyFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -1049,7 +1049,7 @@ func TestHasFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } diff --git a/pkg/eval/builtin/encoding_test.go b/pkg/eval/builtin/encoding_test.go index c038263..355d0bf 100644 --- a/pkg/eval/builtin/encoding_test.go +++ b/pkg/eval/builtin/encoding_test.go @@ -51,7 +51,7 @@ func TestToBase64Function(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -107,7 +107,7 @@ func TestFromBase64Function(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } diff --git a/pkg/eval/builtin/funcs.go b/pkg/eval/builtin/funcs.go index d3a7695..3c5afca 100644 --- a/pkg/eval/builtin/funcs.go +++ b/pkg/eval/builtin/funcs.go @@ -8,108 +8,141 @@ import ( "go.xrstf.de/rudi/pkg/eval/types" ) -var Functions = types.Functions{ - // core - "default": types.BasicFunction(defaultFunction, "returns the default value if the first argument is empty"), - "delete": deleteFunction{}, - "do": types.BasicFunction(doFunction, "eval a sequence of statements where only one expression is valid"), - "empty?": types.BasicFunction(isEmptyFunction, "returns true when the given value is empty-ish (0, false, null, \"\", ...)"), - "has?": types.BasicFunction(hasFunction, "returns true if the given symbol's path expression points to an existing value"), - "if": types.BasicFunction(ifFunction, "evaluate one of two expressions based on a condition"), - "set": types.BasicFunction(setFunction, "set a value in a variable/document, only really useful with ! modifier (set!)"), - "try": types.BasicFunction(tryFunction, "returns the fallback if the first expression errors out"), - "strictly": types.BasicFunction(strictlyFunction, "evaluates the child expressions using strict coalescing"), - "pedantically": types.BasicFunction(pedanticallyFunction, "evaluates the child expressions using pedantic coalescing"), - "humanely": types.BasicFunction(humanelyFunction, "evaluates the child expressions using humane coalescing"), - - // math - "+": types.BasicFunction(sumFunction, "returns the sum of all of its arguments"), - "-": types.BasicFunction(subFunction, "returns arg1 - arg2 - .. - argN"), - "*": types.BasicFunction(multiplyFunction, "returns the product of all of its arguments"), - "/": types.BasicFunction(divideFunction, "returns arg1 / arg2 / .. / argN"), - - // math aliases to make bang functions nicer (sum! vs +!) - "sum": types.BasicFunction(sumFunction, "alias for +"), - "sub": types.BasicFunction(subFunction, "alias for -"), - "mult": types.BasicFunction(multiplyFunction, "alias for *"), - "div": types.BasicFunction(divideFunction, "alias for div"), - - // strings - // "len": lenFunction is defined for lists, but works for strings as well - // "reverse" also works for strings - "concat": types.BasicFunction(concatFunction, "concatenate items in a vector using a common glue string"), - "split": fromStringFunc(splitFunction, 2, "split a string into a vector"), - "has-prefix?": fromStringFunc(hasPrefixFunction, 2, "returns true if the given string has the prefix"), - "has-suffix?": fromStringFunc(hasSuffixFunction, 2, "returns true if the given string has the suffix"), - "trim-prefix": fromStringFunc(trimPrefixFunction, 2, "removes the prefix from the string, if it exists"), - "trim-suffix": fromStringFunc(trimSuffixFunction, 2, "removes the suffix from the string, if it exists"), - "to-lower": fromStringFunc(toLowerFunction, 1, "returns the lowercased version of the given string"), - "to-upper": fromStringFunc(toUpperFunction, 1, "returns the uppercased version of the given string"), - "trim": fromStringFunc(trimFunction, 1, "returns the given whitespace with leading/trailing whitespace removed"), - - // lists - "len": types.BasicFunction(lenFunction, "returns the length of a string, vector or object"), - "append": types.BasicFunction(appendFunction, "appends more strings to a string or arbitrary items into a vector"), - "prepend": types.BasicFunction(prependFunction, "prepends more strings to a string or arbitrary items into a vector"), - "reverse": types.BasicFunction(reverseFunction, "reverses a string or the elements of a vector"), - "range": types.BasicFunction(rangeFunction, "allows to iterate (loop) over a vector or object"), - "map": types.BasicFunction(mapFunction, "applies an expression to every element in a vector or object"), - "filter": types.BasicFunction(filterFunction, "returns a copy of a given vector/object with only those elements remaining that satisfy a condition"), - "contains?": types.BasicFunction(containsFunction, "returns true if a string contains a substring or a vector contains the given element"), - - // logic - "and": types.BasicFunction(andFunction, "returns true if all arguments are true"), - "or": types.BasicFunction(orFunction, "returns true if any of the arguments is true"), - "not": types.BasicFunction(notFunction, "negates the given argument"), - - // comparisons - "eq?": makeEqualityFunc(func(ctx types.Context) coalescing.Coalescer { - return ctx.Coalesce() - }, "equality check: return true if both arguments are the same"), - "identical?": makeEqualityFunc(func(ctx types.Context) coalescing.Coalescer { - return coalescing.NewStrict() - }, "like `eq?`, but always uses strict coalecsing"), - "like?": makeEqualityFunc(func(ctx types.Context) coalescing.Coalescer { - return coalescing.NewHumane() - }, "like `eq?`, but always uses humane coalecsing"), - - "lt?": makeNumberComparatorFunc( - func(a, b int64) (bool, error) { return a < b, nil }, - func(a, b float64) (bool, error) { return a < b, nil }, - "returns a < b", - ), - "lte?": makeNumberComparatorFunc( - func(a, b int64) (bool, error) { return a <= b, nil }, - func(a, b float64) (bool, error) { return a <= b, nil }, - "return a <= b", - ), - "gt?": makeNumberComparatorFunc( - func(a, b int64) (bool, error) { return a > b, nil }, - func(a, b float64) (bool, error) { return a > b, nil }, - "returns a > b", - ), - "gte?": makeNumberComparatorFunc( - func(a, b int64) (bool, error) { return a >= b, nil }, - func(a, b float64) (bool, error) { return a >= b, nil }, - "returns a >= b", - ), - - // types - "type-of": types.BasicFunction(typeOfFunction, `returns the type of a given value (e.g. "string" or "number")`), - "to-bool": types.BasicFunction(toBoolFunction, "try to convert the given argument losslessly to a bool"), - "to-float": types.BasicFunction(toFloatFunction, "try to convert the given argument losslessly to a float64"), - "to-int": types.BasicFunction(toIntFunction, "try to convert the given argument losslessly to an int64"), - "to-string": types.BasicFunction(toStringFunction, "try to convert the given argument losslessly to a string"), - - // hashes - "sha1": types.BasicFunction(sha1Function, "return the lowercase hex representation of the SHA-1 hash"), - "sha256": types.BasicFunction(sha256Function, "return the lowercase hex representation of the SHA-256 hash"), - "sha512": types.BasicFunction(sha512Function, "return the lowercase hex representation of the SHA-512 hash"), - - // encoding - "to-base64": types.BasicFunction(toBase64Function, "apply base64 encoding to the given string"), - "from-base64": types.BasicFunction(fromBase64Function, "decode a base64 encoded string"), - - // dates & time - "now": types.BasicFunction(nowFunction, "returns the current date & time (UTC), formatted like a Go date"), -} +var ( + CoreFunctions = types.Functions{ + "default": types.BasicFunction(defaultFunction, "returns the default value if the first argument is empty"), + "delete": deleteFunction{}, + "do": types.BasicFunction(doFunction, "eval a sequence of statements where only one expression is valid"), + "empty?": types.BasicFunction(isEmptyFunction, "returns true when the given value is empty-ish (0, false, null, \"\", ...)"), + "has?": types.BasicFunction(hasFunction, "returns true if the given symbol's path expression points to an existing value"), + "if": types.BasicFunction(ifFunction, "evaluate one of two expressions based on a condition"), + "set": types.BasicFunction(setFunction, "set a value in a variable/document, only really useful with ! modifier (set!)"), + "try": types.BasicFunction(tryFunction, "returns the fallback if the first expression errors out"), + } + + LogicFunctions = types.Functions{ + "and": types.BasicFunction(andFunction, "returns true if all arguments are true"), + "or": types.BasicFunction(orFunction, "returns true if any of the arguments is true"), + "not": types.BasicFunction(notFunction, "negates the given argument"), + } + + ComparisonFunctions = types.Functions{ + "eq?": makeEqualityFunc(func(ctx types.Context) coalescing.Coalescer { + return ctx.Coalesce() + }, "equality check: return true if both arguments are the same"), + "identical?": makeEqualityFunc(func(ctx types.Context) coalescing.Coalescer { + return coalescing.NewStrict() + }, "like `eq?`, but always uses strict coalecsing"), + "like?": makeEqualityFunc(func(ctx types.Context) coalescing.Coalescer { + return coalescing.NewHumane() + }, "like `eq?`, but always uses humane coalecsing"), + + "lt?": makeNumberComparatorFunc( + func(a, b int64) (bool, error) { return a < b, nil }, + func(a, b float64) (bool, error) { return a < b, nil }, + "returns a < b", + ), + "lte?": makeNumberComparatorFunc( + func(a, b int64) (bool, error) { return a <= b, nil }, + func(a, b float64) (bool, error) { return a <= b, nil }, + "return a <= b", + ), + "gt?": makeNumberComparatorFunc( + func(a, b int64) (bool, error) { return a > b, nil }, + func(a, b float64) (bool, error) { return a > b, nil }, + "returns a > b", + ), + "gte?": makeNumberComparatorFunc( + func(a, b int64) (bool, error) { return a >= b, nil }, + func(a, b float64) (bool, error) { return a >= b, nil }, + "returns a >= b", + ), + } + + MathFunctions = types.Functions{ + "+": types.BasicFunction(sumFunction, "returns the sum of all of its arguments"), + "-": types.BasicFunction(subFunction, "returns arg1 - arg2 - .. - argN"), + "*": types.BasicFunction(multiplyFunction, "returns the product of all of its arguments"), + "/": types.BasicFunction(divideFunction, "returns arg1 / arg2 / .. / argN"), + + // aliases to make bang functions nicer (sum! vs +!) + "sum": types.BasicFunction(sumFunction, "alias for +"), + "sub": types.BasicFunction(subFunction, "alias for -"), + "mult": types.BasicFunction(multiplyFunction, "alias for *"), + "div": types.BasicFunction(divideFunction, "alias for div"), + } + + StringsFunctions = types.Functions{ + // these ones are shared with ListsFunctions + "len": types.BasicFunction(lenFunction, "returns the length of a string, vector or object"), + "append": types.BasicFunction(appendFunction, "appends more strings to a string or arbitrary items into a vector"), + "prepend": types.BasicFunction(prependFunction, "prepends more strings to a string or arbitrary items into a vector"), + "reverse": types.BasicFunction(reverseFunction, "reverses a string or the elements of a vector"), + "contains?": types.BasicFunction(containsFunction, "returns true if a string contains a substring or a vector contains the given element"), + + "concat": types.BasicFunction(concatFunction, "concatenate items in a vector using a common glue string"), + "split": fromStringFunc(splitFunction, 2, "split a string into a vector"), + "has-prefix?": fromStringFunc(hasPrefixFunction, 2, "returns true if the given string has the prefix"), + "has-suffix?": fromStringFunc(hasSuffixFunction, 2, "returns true if the given string has the suffix"), + "trim-prefix": fromStringFunc(trimPrefixFunction, 2, "removes the prefix from the string, if it exists"), + "trim-suffix": fromStringFunc(trimSuffixFunction, 2, "removes the suffix from the string, if it exists"), + "to-lower": fromStringFunc(toLowerFunction, 1, "returns the lowercased version of the given string"), + "to-upper": fromStringFunc(toUpperFunction, 1, "returns the uppercased version of the given string"), + "trim": fromStringFunc(trimFunction, 1, "returns the given whitespace with leading/trailing whitespace removed"), + } + + ListsFunctions = types.Functions{ + // these ones are shared with StringsFunctions + "len": types.BasicFunction(lenFunction, "returns the length of a string, vector or object"), + "append": types.BasicFunction(appendFunction, "appends more strings to a string or arbitrary items into a vector"), + "prepend": types.BasicFunction(prependFunction, "prepends more strings to a string or arbitrary items into a vector"), + "reverse": types.BasicFunction(reverseFunction, "reverses a string or the elements of a vector"), + "contains?": types.BasicFunction(containsFunction, "returns true if a string contains a substring or a vector contains the given element"), + + "range": types.BasicFunction(rangeFunction, "allows to iterate (loop) over a vector or object"), + "map": types.BasicFunction(mapFunction, "applies an expression to every element in a vector or object"), + "filter": types.BasicFunction(filterFunction, "returns a copy of a given vector/object with only those elements remaining that satisfy a condition"), + } + + HashingFunctions = types.Functions{ + "sha1": types.BasicFunction(sha1Function, "return the lowercase hex representation of the SHA-1 hash"), + "sha256": types.BasicFunction(sha256Function, "return the lowercase hex representation of the SHA-256 hash"), + "sha512": types.BasicFunction(sha512Function, "return the lowercase hex representation of the SHA-512 hash"), + } + + EncodingFunctions = types.Functions{ + "to-base64": types.BasicFunction(toBase64Function, "apply base64 encoding to the given string"), + "from-base64": types.BasicFunction(fromBase64Function, "decode a base64 encoded string"), + } + + DateTimeFunctions = types.Functions{ + "now": types.BasicFunction(nowFunction, "returns the current date & time (UTC), formatted like a Go date"), + } + + TypeFunctions = types.Functions{ + "type-of": types.BasicFunction(typeOfFunction, `returns the type of a given value (e.g. "string" or "number")`), + "to-bool": types.BasicFunction(toBoolFunction, "try to convert the given argument losslessly to a bool"), + "to-float": types.BasicFunction(toFloatFunction, "try to convert the given argument losslessly to a float64"), + "to-int": types.BasicFunction(toIntFunction, "try to convert the given argument losslessly to an int64"), + "to-string": types.BasicFunction(toStringFunction, "try to convert the given argument losslessly to a string"), + } + + CoalescingContextFunctions = types.Functions{ + "strictly": types.BasicFunction(strictlyFunction, "evaluates the child expressions using strict coalescing"), + "pedantically": types.BasicFunction(pedanticallyFunction, "evaluates the child expressions using pedantic coalescing"), + "humanely": types.BasicFunction(humanelyFunction, "evaluates the child expressions using humane coalescing"), + } + + AllFunctions = types.Functions{}. + Add(CoreFunctions). + Add(LogicFunctions). + Add(ComparisonFunctions). + Add(MathFunctions). + Add(StringsFunctions). + Add(ListsFunctions). + Add(HashingFunctions). + Add(EncodingFunctions). + Add(DateTimeFunctions). + Add(TypeFunctions). + Add(CoalescingContextFunctions) +) diff --git a/pkg/eval/builtin/hashing_test.go b/pkg/eval/builtin/hashing_test.go index f79c090..3c1e8ba 100644 --- a/pkg/eval/builtin/hashing_test.go +++ b/pkg/eval/builtin/hashing_test.go @@ -47,7 +47,7 @@ func TestSha1Function(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -90,7 +90,7 @@ func TestSha256Function(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -133,7 +133,7 @@ func TestSha512Function(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } diff --git a/pkg/eval/builtin/lists_test.go b/pkg/eval/builtin/lists_test.go index 4078293..1d1ddcc 100644 --- a/pkg/eval/builtin/lists_test.go +++ b/pkg/eval/builtin/lists_test.go @@ -59,7 +59,7 @@ func TestLenFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -124,7 +124,7 @@ func TestAppendFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -193,7 +193,7 @@ func TestPrependFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -256,7 +256,7 @@ func TestReverseFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -364,7 +364,7 @@ func TestRangeFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -493,7 +493,7 @@ func TestMapFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } diff --git a/pkg/eval/builtin/logic_test.go b/pkg/eval/builtin/logic_test.go index 19e8aa2..2afefe7 100644 --- a/pkg/eval/builtin/logic_test.go +++ b/pkg/eval/builtin/logic_test.go @@ -74,7 +74,7 @@ func TestAndFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -144,7 +144,7 @@ func TestOrFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -210,7 +210,7 @@ func TestNotFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } diff --git a/pkg/eval/builtin/math_test.go b/pkg/eval/builtin/math_test.go index 050a38a..508a236 100644 --- a/pkg/eval/builtin/math_test.go +++ b/pkg/eval/builtin/math_test.go @@ -58,7 +58,7 @@ func TestSumFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -108,7 +108,7 @@ func TestMinusFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -158,7 +158,7 @@ func TestMultiplyFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -216,7 +216,7 @@ func TestDivideFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } diff --git a/pkg/eval/builtin/strings_test.go b/pkg/eval/builtin/strings_test.go index f85c709..07ae470 100644 --- a/pkg/eval/builtin/strings_test.go +++ b/pkg/eval/builtin/strings_test.go @@ -70,7 +70,7 @@ func TestConcatFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -124,7 +124,7 @@ func TestSplitFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -166,7 +166,7 @@ func TestToUpperFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -208,7 +208,7 @@ func TestToLowerFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } diff --git a/pkg/eval/builtin/types_test.go b/pkg/eval/builtin/types_test.go index ad5d032..997b304 100644 --- a/pkg/eval/builtin/types_test.go +++ b/pkg/eval/builtin/types_test.go @@ -62,7 +62,7 @@ func TestToStringFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -128,7 +128,7 @@ func TestToIntFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -194,7 +194,7 @@ func TestToFloatFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -264,7 +264,7 @@ func TestToBoolFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } @@ -338,7 +338,7 @@ func TestTypeOfFunction(t *testing.T) { } for _, testcase := range testcases { - testcase.Functions = Functions + testcase.Functions = AllFunctions t.Run(testcase.String(), testcase.Run) } } diff --git a/pkg/eval/types/context.go b/pkg/eval/types/context.go index be53dcb..633399c 100644 --- a/pkg/eval/types/context.go +++ b/pkg/eval/types/context.go @@ -143,11 +143,28 @@ func (f Functions) Set(name string, fun Function) Functions { return f } +// Set removes a function from the set. +// The function returns the same Functions to allow fluent access. +func (f Functions) Delete(name string) Functions { + delete(f, name) + return f +} + // Add adds all functions from other to the current set. // The function returns the same Functions to allow fluent access. func (f Functions) Add(other Functions) Functions { - for k, v := range other { - f[k] = v + for name, fun := range other { + f[name] = fun + } + return f +} + +// Remove removes all functions from this set that are part of the other set, +// to enable constructs like AllFunctions.Remove(MathFunctions) +// The function returns the same Functions to allow fluent access. +func (f Functions) Remove(other Functions) Functions { + for name := range other { + f.Delete(name) } return f }