use crate::metadata::{FunctionCategory, FunctionInfo, ParameterInfo, PropertyInfo};
#[derive(Clone, Debug)]
pub struct BuiltinMetadata {
pub name: &'static str,
pub signature: &'static str,
pub description: &'static str,
pub category: &'static str,
pub parameters: &'static [BuiltinParam],
pub return_type: &'static str,
pub example: Option<&'static str>,
}
#[derive(Clone, Debug)]
pub struct BuiltinParam {
pub name: &'static str,
pub param_type: &'static str,
pub optional: bool,
pub description: &'static str,
}
#[derive(Clone, Debug)]
pub struct TypeMetadata {
pub name: &'static str,
pub description: &'static str,
pub properties: &'static [PropertyMetadata],
}
#[derive(Clone, Debug)]
pub struct PropertyMetadata {
pub name: &'static str,
pub prop_type: &'static str,
pub description: &'static str,
}
impl TypeMetadata {
pub fn to_property_infos(&self) -> Vec<PropertyInfo> {
self.properties
.iter()
.map(|p| PropertyInfo {
name: p.name.to_string(),
property_type: p.prop_type.to_string(),
description: p.description.to_string(),
})
.collect()
}
}
impl From<&BuiltinMetadata> for FunctionInfo {
fn from(meta: &BuiltinMetadata) -> Self {
let category = match meta.category {
"Simulation" => FunctionCategory::Simulation,
"Math" => FunctionCategory::Math,
"Vec" => FunctionCategory::Array,
"Column" => FunctionCategory::Column,
"Statistics" => FunctionCategory::Statistics,
"Data" => FunctionCategory::Data,
_ => FunctionCategory::Utility,
};
FunctionInfo {
name: meta.name.to_string(),
signature: meta.signature.to_string(),
description: meta.description.to_string(),
category,
parameters: meta
.parameters
.iter()
.map(|p| ParameterInfo {
name: p.name.to_string(),
param_type: p.param_type.to_string(),
optional: p.optional,
description: p.description.to_string(),
constraints: None, })
.collect(),
return_type: meta.return_type.to_string(),
example: meta.example.map(|s| s.to_string()),
implemented: true,
comptime_only: meta.category == "Comptime",
}
}
}
static CORE_BUILTINS: &[BuiltinMetadata] = &[
BuiltinMetadata {
name: "abs",
signature: "abs(value: number) -> number",
description: "Return the absolute value of a number.",
category: "Math",
parameters: &[BuiltinParam {
name: "value",
param_type: "number",
optional: false,
description: "Input value",
}],
return_type: "number",
example: Some("abs(-5) // 5"),
},
BuiltinMetadata {
name: "sqrt",
signature: "sqrt(value: number) -> number",
description: "Return the square root of a number.",
category: "Math",
parameters: &[BuiltinParam {
name: "value",
param_type: "number",
optional: false,
description: "Input value",
}],
return_type: "number",
example: Some("sqrt(16) // 4"),
},
BuiltinMetadata {
name: "pow",
signature: "pow(base: number, exponent: number) -> number",
description: "Raise base to the power of exponent.",
category: "Math",
parameters: &[
BuiltinParam {
name: "base",
param_type: "number",
optional: false,
description: "Base value",
},
BuiltinParam {
name: "exponent",
param_type: "number",
optional: false,
description: "Exponent",
},
],
return_type: "number",
example: Some("pow(2, 3) // 8"),
},
BuiltinMetadata {
name: "log",
signature: "log(value: number) -> number",
description: "Return the natural logarithm of a number.",
category: "Math",
parameters: &[BuiltinParam {
name: "value",
param_type: "number",
optional: false,
description: "Input value",
}],
return_type: "number",
example: Some("log(2.718) // ~1.0"),
},
BuiltinMetadata {
name: "exp",
signature: "exp(value: number) -> number",
description: "Return e raised to the power of value.",
category: "Math",
parameters: &[BuiltinParam {
name: "value",
param_type: "number",
optional: false,
description: "Exponent",
}],
return_type: "number",
example: Some("exp(1) // ~2.718"),
},
BuiltinMetadata {
name: "floor",
signature: "floor(value: number) -> number",
description: "Round down to the nearest integer.",
category: "Math",
parameters: &[BuiltinParam {
name: "value",
param_type: "number",
optional: false,
description: "Input value",
}],
return_type: "number",
example: Some("floor(3.7) // 3"),
},
BuiltinMetadata {
name: "ceil",
signature: "ceil(value: number) -> number",
description: "Round up to the nearest integer.",
category: "Math",
parameters: &[BuiltinParam {
name: "value",
param_type: "number",
optional: false,
description: "Input value",
}],
return_type: "number",
example: Some("ceil(3.2) // 4"),
},
BuiltinMetadata {
name: "round",
signature: "round(value: number, decimals?: number) -> number",
description: "Round a number to the specified number of decimal places.",
category: "Math",
parameters: &[
BuiltinParam {
name: "value",
param_type: "number",
optional: false,
description: "Input value",
},
BuiltinParam {
name: "decimals",
param_type: "number",
optional: true,
description: "Decimal places (default 0)",
},
],
return_type: "number",
example: Some("round(3.456, 2) // 3.46"),
},
BuiltinMetadata {
name: "max",
signature: "max(a: number, b: number) -> number",
description: "Return the larger of two numbers.",
category: "Math",
parameters: &[
BuiltinParam {
name: "a",
param_type: "number",
optional: false,
description: "First value",
},
BuiltinParam {
name: "b",
param_type: "number",
optional: false,
description: "Second value",
},
],
return_type: "number",
example: Some("max(3, 7) // 7"),
},
BuiltinMetadata {
name: "min",
signature: "min(a: number, b: number) -> number",
description: "Return the smaller of two numbers.",
category: "Math",
parameters: &[
BuiltinParam {
name: "a",
param_type: "number",
optional: false,
description: "First value",
},
BuiltinParam {
name: "b",
param_type: "number",
optional: false,
description: "Second value",
},
],
return_type: "number",
example: Some("min(3, 7) // 3"),
},
BuiltinMetadata {
name: "print",
signature: "print(...values) -> ()",
description: "Print values to output. Supports string interpolation and meta format functions.",
category: "Utility",
parameters: &[BuiltinParam {
name: "values",
param_type: "any",
optional: false,
description: "Values to print",
}],
return_type: "()",
example: Some("print(\"hello\", x)"),
},
BuiltinMetadata {
name: "range",
signature: "range(start, end, step?) -> Vec<number>",
description: "Generate an array of numbers from start to end.",
category: "Utility",
parameters: &[
BuiltinParam {
name: "start",
param_type: "number",
optional: false,
description: "Start value",
},
BuiltinParam {
name: "end",
param_type: "number",
optional: false,
description: "End value (exclusive)",
},
BuiltinParam {
name: "step",
param_type: "number",
optional: true,
description: "Step size (default 1)",
},
],
return_type: "Vec<number>",
example: Some("range(0, 5) // [0, 1, 2, 3, 4]"),
},
BuiltinMetadata {
name: "avg",
signature: "avg(collection, value: number) -> number",
description: "Compute the average of values in a collection.",
category: "Statistics",
parameters: &[
BuiltinParam {
name: "collection",
param_type: "any",
optional: false,
description: "Input collection",
},
BuiltinParam {
name: "value",
param_type: "number",
optional: false,
description: "Value to average",
},
],
return_type: "number",
example: Some("avg(items, row => row.price)"),
},
BuiltinMetadata {
name: "sum",
signature: "sum(table: Table<any>) -> number",
description: "Compute the sum of all values in a series.",
category: "Statistics",
parameters: &[BuiltinParam {
name: "series",
param_type: "Table<any>",
optional: false,
description: "Input series",
}],
return_type: "number",
example: Some("sum(volumes)"),
},
BuiltinMetadata {
name: "mean",
signature: "mean(table: Table<any>) -> number",
description: "Compute the mean of all values in a series.",
category: "Statistics",
parameters: &[BuiltinParam {
name: "series",
param_type: "Table<any>",
optional: false,
description: "Input series",
}],
return_type: "number",
example: Some("mean(prices)"),
},
BuiltinMetadata {
name: "stddev",
signature: "stddev(values) -> number",
description: "Compute the standard deviation.",
category: "Statistics",
parameters: &[BuiltinParam {
name: "values",
param_type: "any",
optional: false,
description: "Input values",
}],
return_type: "number",
example: Some("stddev(returns)"),
},
BuiltinMetadata {
name: "count",
signature: "count(array: Vec) -> number",
description: "Count the number of elements in an array.",
category: "Vec",
parameters: &[BuiltinParam {
name: "array",
param_type: "Vec",
optional: false,
description: "Input array",
}],
return_type: "number",
example: Some("count(items)"),
},
BuiltinMetadata {
name: "highest",
signature: "highest(collection, count: number) -> number",
description: "Return the highest value from a collection.",
category: "Vec",
parameters: &[
BuiltinParam {
name: "collection",
param_type: "any",
optional: false,
description: "Input collection",
},
BuiltinParam {
name: "count",
param_type: "number",
optional: false,
description: "Number of values",
},
],
return_type: "number",
example: Some("highest(prices, 10)"),
},
BuiltinMetadata {
name: "lowest",
signature: "lowest(collection, count: number) -> number",
description: "Return the lowest value from a collection.",
category: "Vec",
parameters: &[
BuiltinParam {
name: "collection",
param_type: "any",
optional: false,
description: "Input collection",
},
BuiltinParam {
name: "count",
param_type: "number",
optional: false,
description: "Number of values",
},
],
return_type: "number",
example: Some("lowest(prices, 10)"),
},
BuiltinMetadata {
name: "format",
signature: "format(value, template) -> string",
description: "Format a value using a template string.",
category: "Utility",
parameters: &[
BuiltinParam {
name: "value",
param_type: "any",
optional: false,
description: "Value to format",
},
BuiltinParam {
name: "template",
param_type: "any",
optional: false,
description: "Format template",
},
],
return_type: "string",
example: Some("format(0.15, \"percent\") // \"15%\""),
},
BuiltinMetadata {
name: "shift",
signature: "shift(table: Table<any>, periods: number) -> Table<any>",
description: "Shift series values by a number of periods.",
category: "Column",
parameters: &[
BuiltinParam {
name: "series",
param_type: "Table<any>",
optional: false,
description: "Input series",
},
BuiltinParam {
name: "periods",
param_type: "number",
optional: false,
description: "Number of periods to shift",
},
],
return_type: "Table<any>",
example: Some("shift(prices, 1) // previous day's prices"),
},
BuiltinMetadata {
name: "resample",
signature: "resample(table: Table<any>, timeframe: string, method: string) -> Table<any>",
description: "Resample a series to a different timeframe.",
category: "Column",
parameters: &[
BuiltinParam {
name: "series",
param_type: "Table<any>",
optional: false,
description: "Input series",
},
BuiltinParam {
name: "timeframe",
param_type: "string",
optional: false,
description: "Target timeframe",
},
BuiltinParam {
name: "method",
param_type: "string",
optional: false,
description: "Aggregation method",
},
],
return_type: "Table<any>",
example: Some("resample(prices, \"1h\", \"last\")"),
},
BuiltinMetadata {
name: "map",
signature: "map(table: Table<any>, fn: Function) -> Table<any>",
description: "Apply a function to each element of a series.",
category: "Column",
parameters: &[
BuiltinParam {
name: "series",
param_type: "Table<any>",
optional: false,
description: "Input series",
},
BuiltinParam {
name: "fn",
param_type: "Function",
optional: false,
description: "Transform function",
},
],
return_type: "Table<any>",
example: Some("map(prices, (p) => p * 1.1)"),
},
BuiltinMetadata {
name: "filter",
signature: "filter(table: Table<any>, predicate: Function) -> Table<any>",
description: "Filter series elements by a predicate function.",
category: "Column",
parameters: &[
BuiltinParam {
name: "series",
param_type: "Table<any>",
optional: false,
description: "Input series",
},
BuiltinParam {
name: "predicate",
param_type: "Function",
optional: false,
description: "Filter predicate",
},
],
return_type: "Table<any>",
example: Some("filter(prices, (p) => p > 100)"),
},
BuiltinMetadata {
name: "Ok",
signature: "Ok(value) -> Result<T>",
description: "Wrap a value in a successful Result.",
category: "Utility",
parameters: &[BuiltinParam {
name: "value",
param_type: "any",
optional: false,
description: "Success value",
}],
return_type: "Result<T>",
example: Some("Ok(42)"),
},
BuiltinMetadata {
name: "Err",
signature: "Err(error) -> Result<T>",
description: "Create an error Result.",
category: "Utility",
parameters: &[BuiltinParam {
name: "error",
param_type: "any",
optional: false,
description: "Error value",
}],
return_type: "Result<T>",
example: Some("Err(\"not found\")"),
},
BuiltinMetadata {
name: "snapshot",
signature: "snapshot() -> Snapshot",
description: "Create a snapshot suspension point. Returns Snapshot::Hash(id) after saving, or Snapshot::Resumed when restoring from a snapshot.",
category: "Resumability",
parameters: &[],
return_type: "Snapshot",
example: Some(
"let result = snapshot()\nmatch result {\n Snapshot::Hash(id) => print(\"Saved: \" + id),\n Snapshot::Resumed => print(\"Restored!\"),\n}",
),
},
BuiltinMetadata {
name: "exit",
signature: "exit(code?: number) -> ()",
description: "Terminate the process with an optional exit code.",
category: "Utility",
parameters: &[BuiltinParam {
name: "code",
param_type: "number",
optional: true,
description: "Exit code (default 0)",
}],
return_type: "()",
example: Some("exit(0)"),
},
BuiltinMetadata {
name: "implements",
signature: "implements(type_name: string, trait_name: string) -> bool",
description: "Returns true if the given type implements the specified trait. Only valid inside comptime blocks.",
category: "Comptime",
parameters: &[
BuiltinParam {
name: "type_name",
param_type: "string",
optional: false,
description: "Type name to check",
},
BuiltinParam {
name: "trait_name",
param_type: "string",
optional: false,
description: "Trait name to check",
},
],
return_type: "bool",
example: Some("comptime { implements(\"Point\", \"Display\") }"),
},
BuiltinMetadata {
name: "warning",
signature: "warning(msg: string) -> ()",
description: "Emit a compile-time warning. Only valid inside comptime blocks.",
category: "Comptime",
parameters: &[BuiltinParam {
name: "msg",
param_type: "string",
optional: false,
description: "Warning message",
}],
return_type: "()",
example: Some("comptime { warning(\"generated fallback path\") }"),
},
BuiltinMetadata {
name: "error",
signature: "error(msg: string) -> never",
description: "Emit a compile-time error and abort compilation. Only valid inside comptime blocks.",
category: "Comptime",
parameters: &[BuiltinParam {
name: "msg",
param_type: "string",
optional: false,
description: "Error message",
}],
return_type: "never",
example: Some("comptime { error(\"invariant violated\") }"),
},
BuiltinMetadata {
name: "build_config",
signature: "build_config() -> Object",
description: "Returns build-time configuration (debug, version, target_os, target_arch). Only valid inside comptime blocks.",
category: "Comptime",
parameters: &[],
return_type: "Object",
example: Some("let v = comptime { build_config().version }"),
},
BuiltinMetadata {
name: "type_info",
signature: "type_info(type_name: string) -> TypeInfo",
description: "Returns the `TypeInfo` reflection record for the named type. Only valid inside comptime blocks. Bare type identifiers passed at the call site are rewritten to string literals by the comptime preprocessor.",
category: "Comptime",
parameters: &[BuiltinParam {
name: "type_name",
param_type: "string",
optional: false,
description: "Type name to reflect on (bare identifiers are auto-stringified at the call site)",
}],
return_type: "TypeInfo",
example: Some("comptime { let ti = type_info(Point); print(ti.name) }"),
},
];
pub fn collect_builtin_metadata() -> Vec<&'static BuiltinMetadata> {
CORE_BUILTINS.iter().collect()
}
pub fn builtin_functions_from_macros() -> Vec<FunctionInfo> {
collect_builtin_metadata()
.into_iter()
.map(|m| m.into())
.collect()
}
pub fn is_comptime_builtin_function(name: &str) -> bool {
CORE_BUILTINS
.iter()
.any(|m| m.name == name && m.category == "Comptime")
}
pub static TYPE_METADATA_ROW: TypeMetadata = TypeMetadata {
name: "Row",
description: "Generic data row with dynamic fields",
properties: &[],
};
pub fn collect_core_type_metadata() -> Vec<&'static TypeMetadata> {
vec![&TYPE_METADATA_ROW]
}
pub fn collect_domain_type_metadata() -> Vec<&'static TypeMetadata> {
vec![]
}
pub fn collect_type_metadata() -> Vec<&'static TypeMetadata> {
let mut types = collect_core_type_metadata();
types.extend(collect_domain_type_metadata());
types
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_builtin_metadata_to_function_info() {
static TEST_PARAMS: &[BuiltinParam] = &[BuiltinParam {
name: "value",
param_type: "Number",
optional: false,
description: "Input value",
}];
let meta = BuiltinMetadata {
name: "test_fn",
signature: "test_fn(value: Number) -> Number",
description: "A test function",
category: "Math",
parameters: TEST_PARAMS,
return_type: "Number",
example: Some("test_fn(42)"),
};
let info: FunctionInfo = (&meta).into();
assert_eq!(info.name, "test_fn");
assert_eq!(info.signature, "test_fn(value: Number) -> Number");
assert_eq!(info.description, "A test function");
assert_eq!(info.category, FunctionCategory::Math);
assert_eq!(info.parameters.len(), 1);
assert_eq!(info.parameters[0].name, "value");
assert_eq!(info.return_type, "Number");
assert_eq!(info.example, Some("test_fn(42)".to_string()));
assert!(info.implemented);
}
}