Skip to content

Commit

Permalink
split Functions into smaller chunks, make it easier to merge Function…
Browse files Browse the repository at this point in the history
… sets
  • Loading branch information
xrstf committed Dec 2, 2023
1 parent 6883ec9 commit 29b1f08
Show file tree
Hide file tree
Showing 13 changed files with 198 additions and 148 deletions.
4 changes: 2 additions & 2 deletions aliases.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion docs/embed.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/eval/builtin/comparisons_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand Down Expand Up @@ -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)
}
}
Expand Down Expand Up @@ -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)
}
}
16 changes: 8 additions & 8 deletions pkg/eval/builtin/core_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand Down Expand Up @@ -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)
}
}
Expand Down Expand Up @@ -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)
}
}
Expand Down Expand Up @@ -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)
}
}
Expand Down Expand Up @@ -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)
}
}
Expand Down Expand Up @@ -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)
}
}
Expand Down Expand Up @@ -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)
}
}
Expand Down Expand Up @@ -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)
}
}
4 changes: 2 additions & 2 deletions pkg/eval/builtin/encoding_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand Down Expand Up @@ -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)
}
}
243 changes: 138 additions & 105 deletions pkg/eval/builtin/funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
)
Loading

0 comments on commit 29b1f08

Please sign in to comment.