///|
/// Broad grouping used by generated documentation and editor integrations.
pub(all) enum FunctionCategory {
Collection
String
Number
Conversion
Predicate
} derive(Eq, Debug, ToJson, FromJson)
///|
/// Machine-readable description of a function built into MoonRule.
///
/// Keeping this metadata in the library lets command-line tools and web
/// editors provide completion without maintaining a second function list.
pub(all) struct FunctionSpec {
name : String
category : FunctionCategory
min_arguments : Int
max_arguments : Int
signature : String
summary : String
} derive(Eq, Debug, ToJson, FromJson)
///|
fn function_spec(
name : String,
category : FunctionCategory,
arguments : Int,
signature : String,
summary : String,
) -> FunctionSpec {
{
name,
category,
min_arguments: arguments,
max_arguments: arguments,
signature,
summary,
}
}
///|
fn variadic_function_spec(
name : String,
category : FunctionCategory,
min_arguments : Int,
max_arguments : Int,
signature : String,
summary : String,
) -> FunctionSpec {
{ name, category, min_arguments, max_arguments, signature, summary }
}
///|
/// Return the stable catalog of functions supported by the evaluator.
pub fn builtin_functions() -> Array[FunctionSpec] {
[
function_spec(
"len",
Collection,
1,
"len(value)",
"Return the character, array, or object length.",
),
function_spec(
"contains",
Collection,
2,
"contains(container, value)",
"Test string, array, or object-key membership.",
),
function_spec(
"has",
Collection,
2,
"has(object, key)",
"Test whether an object contains a key.",
),
function_spec(
"get",
Collection,
3,
"get(object, key, default)",
"Read an object key and return a default when it is absent.",
),
function_spec(
"starts_with",
String,
2,
"starts_with(text, prefix)",
"Test whether text starts with a prefix.",
),
function_spec(
"ends_with",
String,
2,
"ends_with(text, suffix)",
"Test whether text ends with a suffix.",
),
function_spec(
"lower",
String,
1,
"lower(text)",
"Convert text to lowercase.",
),
function_spec(
"upper",
String,
1,
"upper(text)",
"Convert text to uppercase.",
),
function_spec(
"matches",
String,
2,
"matches(text, pattern)",
"Test text with a regular expression.",
),
function_spec(
"is_date",
Predicate,
1,
"is_date(text)",
"Validate an ISO 8601 calendar date in YYYY-MM-DD form.",
),
function_spec(
"is_datetime",
Predicate,
1,
"is_datetime(text)",
"Validate an RFC 3339 timestamp with seconds and a timezone.",
),
function_spec(
"is_ipv4",
Predicate,
1,
"is_ipv4(text)",
"Validate a canonical dotted-decimal IPv4 address.",
),
function_spec(
"is_email",
Predicate,
1,
"is_email(text)",
"Validate a conservative ASCII email-address syntax.",
),
function_spec(
"is_uuid",
Predicate,
1,
"is_uuid(text)",
"Validate the canonical 8-4-4-4-12 UUID text form.",
),
function_spec(
"is_semver",
Predicate,
1,
"is_semver(text)",
"Validate a Semantic Versioning 2.0.0 version string.",
),
function_spec(
"abs",
Number,
1,
"abs(number)",
"Return the absolute value of a number.",
),
function_spec(
"min",
Number,
2,
"min(left, right)",
"Return the smaller of two numbers.",
),
function_spec(
"max",
Number,
2,
"max(left, right)",
"Return the larger of two numbers.",
),
function_spec(
"clamp",
Number,
3,
"clamp(value, minimum, maximum)",
"Constrain a number to an inclusive range.",
),
function_spec(
"sum",
Number,
1,
"sum(numbers)",
"Add all numbers in an array.",
),
function_spec(
"type_of",
Conversion,
1,
"type_of(value)",
"Return the MoonRule type name for a value.",
),
variadic_function_spec(
"coalesce",
Conversion,
1,
32,
"coalesce(first, ...fallbacks)",
"Return the first value that is not null.",
),
function_spec(
"exists",
Predicate,
1,
"exists(value)",
"Test whether a value is not null.",
),
function_spec(
"all",
Predicate,
1,
"all(booleans)",
"Test whether every array item is true.",
),
function_spec(
"any",
Predicate,
1,
"any(booleans)",
"Test whether at least one array item is true.",
),
]
}
///|
/// Look up one built-in function by its exact rule-language name.
pub fn find_builtin_function(name : String) -> FunctionSpec? {
for specification in builtin_functions() {
if specification.name == name {
return Some(specification)
}
}
None
}
///|
/// Return true when an argument count is accepted by a function specification.
pub fn FunctionSpec::accepts_arity(
self : FunctionSpec,
arguments : Int,
) -> Bool {
arguments >= self.min_arguments && arguments <= self.max_arguments
}
///|
/// Render a concise argument-count description for diagnostics.
pub fn FunctionSpec::arity_description(self : FunctionSpec) -> String {
if self.min_arguments == self.max_arguments {
"\{self.min_arguments}"
} else {
"\{self.min_arguments}..\{self.max_arguments}"
}
}
///|
/// Serialize the function catalog for documentation generators and IDEs.
pub fn builtin_functions_json(indent? : Int = 2) -> String {
builtin_functions().to_json().stringify(indent~)
}