Add documentation infrastructure for RTL symbols
Introduces `RtlDocEntry` and `RtlRegistration` structs to store and manage documentation for native functions and constants. The `Environment` struct is updated to include a registry for these documentation entries. The `register_native_fn` and `register_constant` methods now return an `RtlRegistration` builder, allowing for optional chaining of `.doc()`, `.description()`, and `.examples()` methods before the registration is finalized when the builder is dropped. Macros `rtl_fn!` and `rtl_const!` are introduced to simplify the registration process with documentation. The MCP server is extended with `get_rtl_docs` and `get_symbol_doc` tools to expose this documentation externally. Specific RTL functions and constants (e.g., `+`, `-`, `*`, `/`, `NaN`, `true`, `false`, `date`, `now`, math functions, `series`, `push`, `len`, `create-random-ohlc`, `create-ticker`, `pipe`) have been updated to include their respective documentation using the new infrastructure. The `Signature` and `StaticType` types have gained `to_doc_string` methods for generating human-readable documentation strings.
This commit is contained in:
+36
-36
@@ -6,8 +6,10 @@ use std::rc::Rc;
|
||||
|
||||
pub fn register(env: &Environment) {
|
||||
// Constants
|
||||
env.register_constant("PI", StaticType::Float, Value::Float(consts::PI));
|
||||
env.register_constant("E", StaticType::Float, Value::Float(consts::E));
|
||||
env.register_constant("PI", StaticType::Float, Value::Float(consts::PI))
|
||||
.doc("Mathematical constant π ≈ 3.14159265.");
|
||||
env.register_constant("E", StaticType::Float, Value::Float(consts::E))
|
||||
.doc("Mathematical constant e ≈ 2.71828182 (Euler's number).");
|
||||
|
||||
// Helper to get f64 from Value (Int or Float)
|
||||
fn to_f64(v: &Value) -> Option<f64> {
|
||||
@@ -19,7 +21,7 @@ pub fn register(env: &Environment) {
|
||||
}
|
||||
|
||||
// Unary functions (float -> float)
|
||||
let register_unary = |name: &'static str, f: fn(f64) -> f64| {
|
||||
let register_unary = |name: &'static str, f: fn(f64) -> f64, doc: &'static str| {
|
||||
let ty = StaticType::Function(Box::new(Signature {
|
||||
params: StaticType::Tuple(vec![StaticType::Float]),
|
||||
ret: StaticType::Float,
|
||||
@@ -30,11 +32,11 @@ pub fn register(env: &Environment) {
|
||||
} else {
|
||||
Value::Void
|
||||
}
|
||||
});
|
||||
}).doc(doc);
|
||||
};
|
||||
|
||||
// Unary functions (float -> int)
|
||||
let register_to_int = |name: &'static str, f: fn(f64) -> f64| {
|
||||
let register_to_int = |name: &'static str, f: fn(f64) -> f64, doc: &'static str| {
|
||||
let ty = StaticType::Function(Box::new(Signature {
|
||||
params: StaticType::Tuple(vec![StaticType::Float]),
|
||||
ret: StaticType::Int,
|
||||
@@ -45,29 +47,29 @@ pub fn register(env: &Environment) {
|
||||
} else {
|
||||
Value::Void
|
||||
}
|
||||
});
|
||||
}).doc(doc);
|
||||
};
|
||||
|
||||
register_unary("sqrt", f64::sqrt);
|
||||
register_unary("sin", f64::sin);
|
||||
register_unary("cos", f64::cos);
|
||||
register_unary("tan", f64::tan);
|
||||
register_unary("asin", f64::asin);
|
||||
register_unary("acos", f64::acos);
|
||||
register_unary("atan", f64::atan);
|
||||
register_unary("exp", f64::exp);
|
||||
register_unary("ln", f64::ln);
|
||||
register_unary("log10", f64::log10);
|
||||
register_unary("fract", f64::fract);
|
||||
register_unary("sqrt", f64::sqrt, "Returns the square root of x.");
|
||||
register_unary("sin", f64::sin, "Returns the sine of x (radians).");
|
||||
register_unary("cos", f64::cos, "Returns the cosine of x (radians).");
|
||||
register_unary("tan", f64::tan, "Returns the tangent of x (radians).");
|
||||
register_unary("asin", f64::asin, "Returns the arcsine of x in radians.");
|
||||
register_unary("acos", f64::acos, "Returns the arccosine of x in radians.");
|
||||
register_unary("atan", f64::atan, "Returns the arctangent of x in radians.");
|
||||
register_unary("exp", f64::exp, "Returns e raised to the power of x.");
|
||||
register_unary("ln", f64::ln, "Returns the natural logarithm of x.");
|
||||
register_unary("log10",f64::log10,"Returns the base-10 logarithm of x.");
|
||||
register_unary("fract",f64::fract,"Returns the fractional part of x.");
|
||||
|
||||
// Rounding functions returning Int
|
||||
register_to_int("round", f64::round);
|
||||
register_to_int("floor", f64::floor);
|
||||
register_to_int("ceil", f64::ceil);
|
||||
register_to_int("trunc", f64::trunc);
|
||||
register_to_int("round", f64::round, "Rounds x to the nearest integer.");
|
||||
register_to_int("floor", f64::floor, "Rounds x down to the largest integer ≤ x.");
|
||||
register_to_int("ceil", f64::ceil, "Rounds x up to the smallest integer ≥ x.");
|
||||
register_to_int("trunc", f64::trunc, "Truncates x towards zero.");
|
||||
|
||||
// Binary functions (float, float -> float)
|
||||
let register_binary = |name: &'static str, f: fn(f64, f64) -> f64| {
|
||||
let register_binary = |name: &'static str, f: fn(f64, f64) -> f64, doc: &'static str| {
|
||||
let ty = StaticType::Function(Box::new(Signature {
|
||||
params: StaticType::Tuple(vec![StaticType::Float, StaticType::Float]),
|
||||
ret: StaticType::Float,
|
||||
@@ -78,12 +80,12 @@ pub fn register(env: &Environment) {
|
||||
} else {
|
||||
Value::Void
|
||||
}
|
||||
});
|
||||
}).doc(doc);
|
||||
};
|
||||
|
||||
register_binary("atan2", f64::atan2);
|
||||
register_binary("pow", f64::powf);
|
||||
register_binary("log", f64::log);
|
||||
register_binary("atan2", f64::atan2, "Returns the arctangent of y/x, using signs to determine the quadrant.");
|
||||
register_binary("pow", f64::powf, "Returns x raised to the power y.");
|
||||
register_binary("log", f64::log, "Returns the logarithm of x in the given base: (log base x).");
|
||||
|
||||
// Specialized abs to handle Int -> Int, Float -> Float
|
||||
let abs_ty = StaticType::Function(Box::new(Signature {
|
||||
@@ -99,7 +101,8 @@ pub fn register(env: &Environment) {
|
||||
Value::Float(f) => Value::Float(f.abs()),
|
||||
_ => Value::Void,
|
||||
}
|
||||
});
|
||||
}).doc("Returns the absolute value of a number. Works for both int and float.")
|
||||
.examples(&["(abs -5)", "(abs -3.14)"]);
|
||||
|
||||
// Variadic min / max
|
||||
let variadic_ty = StaticType::Function(Box::new(Signature {
|
||||
@@ -120,7 +123,7 @@ pub fn register(env: &Environment) {
|
||||
}
|
||||
}
|
||||
best
|
||||
});
|
||||
}).doc("Returns the minimum of its arguments. Variadic: (min 3 1 2) => 1.");
|
||||
|
||||
env.register_native_fn("max", variadic_ty, Purity::Pure, |args| {
|
||||
if args.is_empty() {
|
||||
@@ -135,7 +138,7 @@ pub fn register(env: &Environment) {
|
||||
}
|
||||
}
|
||||
best
|
||||
});
|
||||
}).doc("Returns the maximum of its arguments. Variadic: (max 3 1 2) => 3.");
|
||||
|
||||
// Random generator factory (Closure-based)
|
||||
let generator_sig = Signature {
|
||||
@@ -154,11 +157,7 @@ pub fn register(env: &Environment) {
|
||||
},
|
||||
]);
|
||||
|
||||
env.register_native_fn(
|
||||
"make-random",
|
||||
make_random_ty,
|
||||
Purity::SideEffectFree,
|
||||
|args| {
|
||||
env.register_native_fn("make-random", make_random_ty, Purity::SideEffectFree, |args| {
|
||||
let rng = if args.is_empty() {
|
||||
fastrand::Rng::new()
|
||||
} else if let Value::Int(s) = args[0] {
|
||||
@@ -173,6 +172,7 @@ pub fn register(env: &Environment) {
|
||||
func: Rc::new(move |_args| Value::Float(prng.borrow_mut().f64())),
|
||||
purity: Purity::Impure,
|
||||
}))
|
||||
},
|
||||
);
|
||||
}).doc("Creates a random number generator function returning floats in [0, 1).")
|
||||
.description("Optionally seeded: (make-random seed) for reproducible sequences.")
|
||||
.examples(&["(def rng (make-random 42))", "(rng)"]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user