1use crate::metadata::{FunctionCategory, FunctionInfo, ParameterInfo, PropertyInfo};
7
8#[derive(Clone, Debug)]
12pub struct BuiltinMetadata {
13 pub name: &'static str,
15 pub signature: &'static str,
17 pub description: &'static str,
19 pub category: &'static str,
21 pub parameters: &'static [BuiltinParam],
23 pub return_type: &'static str,
25 pub example: Option<&'static str>,
27}
28
29#[derive(Clone, Debug)]
31pub struct BuiltinParam {
32 pub name: &'static str,
34 pub param_type: &'static str,
36 pub optional: bool,
38 pub description: &'static str,
40}
41
42#[derive(Clone, Debug)]
44pub struct TypeMetadata {
45 pub name: &'static str,
47 pub description: &'static str,
49 pub properties: &'static [PropertyMetadata],
51}
52
53#[derive(Clone, Debug)]
55pub struct PropertyMetadata {
56 pub name: &'static str,
58 pub prop_type: &'static str,
60 pub description: &'static str,
62}
63
64impl TypeMetadata {
65 pub fn to_property_infos(&self) -> Vec<PropertyInfo> {
67 self.properties
68 .iter()
69 .map(|p| PropertyInfo {
70 name: p.name.to_string(),
71 property_type: p.prop_type.to_string(),
72 description: p.description.to_string(),
73 })
74 .collect()
75 }
76}
77
78impl From<&BuiltinMetadata> for FunctionInfo {
79 fn from(meta: &BuiltinMetadata) -> Self {
80 let category = match meta.category {
81 "Simulation" => FunctionCategory::Simulation,
82 "Math" => FunctionCategory::Math,
83 "Vec" => FunctionCategory::Array,
84 "Column" => FunctionCategory::Column,
85 "Statistics" => FunctionCategory::Statistics,
86 "Data" => FunctionCategory::Data,
87 _ => FunctionCategory::Utility,
88 };
89
90 FunctionInfo {
91 name: meta.name.to_string(),
92 signature: meta.signature.to_string(),
93 description: meta.description.to_string(),
94 category,
95 parameters: meta
96 .parameters
97 .iter()
98 .map(|p| ParameterInfo {
99 name: p.name.to_string(),
100 param_type: p.param_type.to_string(),
101 optional: p.optional,
102 description: p.description.to_string(),
103 constraints: None, })
105 .collect(),
106 return_type: meta.return_type.to_string(),
107 example: meta.example.map(|s| s.to_string()),
108 implemented: true,
109 comptime_only: meta.category == "Comptime",
110 }
111 }
112}
113
114static CORE_BUILTINS: &[BuiltinMetadata] = &[
120 BuiltinMetadata {
122 name: "abs",
123 signature: "abs(value: number) -> number",
124 description: "Return the absolute value of a number.",
125 category: "Math",
126 parameters: &[BuiltinParam {
127 name: "value",
128 param_type: "number",
129 optional: false,
130 description: "Input value",
131 }],
132 return_type: "number",
133 example: Some("abs(-5) // 5"),
134 },
135 BuiltinMetadata {
136 name: "sqrt",
137 signature: "sqrt(value: number) -> number",
138 description: "Return the square root of a number.",
139 category: "Math",
140 parameters: &[BuiltinParam {
141 name: "value",
142 param_type: "number",
143 optional: false,
144 description: "Input value",
145 }],
146 return_type: "number",
147 example: Some("sqrt(16) // 4"),
148 },
149 BuiltinMetadata {
150 name: "pow",
151 signature: "pow(base: number, exponent: number) -> number",
152 description: "Raise base to the power of exponent.",
153 category: "Math",
154 parameters: &[
155 BuiltinParam {
156 name: "base",
157 param_type: "number",
158 optional: false,
159 description: "Base value",
160 },
161 BuiltinParam {
162 name: "exponent",
163 param_type: "number",
164 optional: false,
165 description: "Exponent",
166 },
167 ],
168 return_type: "number",
169 example: Some("pow(2, 3) // 8"),
170 },
171 BuiltinMetadata {
172 name: "log",
173 signature: "log(value: number) -> number",
174 description: "Return the natural logarithm of a number.",
175 category: "Math",
176 parameters: &[BuiltinParam {
177 name: "value",
178 param_type: "number",
179 optional: false,
180 description: "Input value",
181 }],
182 return_type: "number",
183 example: Some("log(2.718) // ~1.0"),
184 },
185 BuiltinMetadata {
186 name: "exp",
187 signature: "exp(value: number) -> number",
188 description: "Return e raised to the power of value.",
189 category: "Math",
190 parameters: &[BuiltinParam {
191 name: "value",
192 param_type: "number",
193 optional: false,
194 description: "Exponent",
195 }],
196 return_type: "number",
197 example: Some("exp(1) // ~2.718"),
198 },
199 BuiltinMetadata {
200 name: "floor",
201 signature: "floor(value: number) -> number",
202 description: "Round down to the nearest integer.",
203 category: "Math",
204 parameters: &[BuiltinParam {
205 name: "value",
206 param_type: "number",
207 optional: false,
208 description: "Input value",
209 }],
210 return_type: "number",
211 example: Some("floor(3.7) // 3"),
212 },
213 BuiltinMetadata {
214 name: "ceil",
215 signature: "ceil(value: number) -> number",
216 description: "Round up to the nearest integer.",
217 category: "Math",
218 parameters: &[BuiltinParam {
219 name: "value",
220 param_type: "number",
221 optional: false,
222 description: "Input value",
223 }],
224 return_type: "number",
225 example: Some("ceil(3.2) // 4"),
226 },
227 BuiltinMetadata {
228 name: "round",
229 signature: "round(value: number, decimals?: number) -> number",
230 description: "Round a number to the specified number of decimal places.",
231 category: "Math",
232 parameters: &[
233 BuiltinParam {
234 name: "value",
235 param_type: "number",
236 optional: false,
237 description: "Input value",
238 },
239 BuiltinParam {
240 name: "decimals",
241 param_type: "number",
242 optional: true,
243 description: "Decimal places (default 0)",
244 },
245 ],
246 return_type: "number",
247 example: Some("round(3.456, 2) // 3.46"),
248 },
249 BuiltinMetadata {
250 name: "max",
251 signature: "max(a: number, b: number) -> number",
252 description: "Return the larger of two numbers.",
253 category: "Math",
254 parameters: &[
255 BuiltinParam {
256 name: "a",
257 param_type: "number",
258 optional: false,
259 description: "First value",
260 },
261 BuiltinParam {
262 name: "b",
263 param_type: "number",
264 optional: false,
265 description: "Second value",
266 },
267 ],
268 return_type: "number",
269 example: Some("max(3, 7) // 7"),
270 },
271 BuiltinMetadata {
272 name: "min",
273 signature: "min(a: number, b: number) -> number",
274 description: "Return the smaller of two numbers.",
275 category: "Math",
276 parameters: &[
277 BuiltinParam {
278 name: "a",
279 param_type: "number",
280 optional: false,
281 description: "First value",
282 },
283 BuiltinParam {
284 name: "b",
285 param_type: "number",
286 optional: false,
287 description: "Second value",
288 },
289 ],
290 return_type: "number",
291 example: Some("min(3, 7) // 3"),
292 },
293 BuiltinMetadata {
295 name: "print",
296 signature: "print(...values) -> ()",
297 description: "Print values to output. Supports string interpolation and meta format functions.",
298 category: "Utility",
299 parameters: &[BuiltinParam {
300 name: "values",
301 param_type: "any",
302 optional: false,
303 description: "Values to print",
304 }],
305 return_type: "()",
306 example: Some("print(\"hello\", x)"),
307 },
308 BuiltinMetadata {
309 name: "len",
310 signature: "len(value) -> number",
311 description: "Return the length of an array, string, or collection.",
312 category: "Utility",
313 parameters: &[BuiltinParam {
314 name: "value",
315 param_type: "any",
316 optional: false,
317 description: "Collection or string",
318 }],
319 return_type: "number",
320 example: Some("len([1, 2, 3]) // 3"),
321 },
322 BuiltinMetadata {
323 name: "range",
324 signature: "range(start, end, step?) -> Vec<number>",
325 description: "Generate an array of numbers from start to end.",
326 category: "Utility",
327 parameters: &[
328 BuiltinParam {
329 name: "start",
330 param_type: "number",
331 optional: false,
332 description: "Start value",
333 },
334 BuiltinParam {
335 name: "end",
336 param_type: "number",
337 optional: false,
338 description: "End value (exclusive)",
339 },
340 BuiltinParam {
341 name: "step",
342 param_type: "number",
343 optional: true,
344 description: "Step size (default 1)",
345 },
346 ],
347 return_type: "Vec<number>",
348 example: Some("range(0, 5) // [0, 1, 2, 3, 4]"),
349 },
350 BuiltinMetadata {
353 name: "avg",
354 signature: "avg(collection, value: number) -> number",
355 description: "Compute the average of values in a collection.",
356 category: "Statistics",
357 parameters: &[
358 BuiltinParam {
359 name: "collection",
360 param_type: "any",
361 optional: false,
362 description: "Input collection",
363 },
364 BuiltinParam {
365 name: "value",
366 param_type: "number",
367 optional: false,
368 description: "Value to average",
369 },
370 ],
371 return_type: "number",
372 example: Some("avg(items, row => row.price)"),
373 },
374 BuiltinMetadata {
375 name: "sum",
376 signature: "sum(table: Table<any>) -> number",
377 description: "Compute the sum of all values in a series.",
378 category: "Statistics",
379 parameters: &[BuiltinParam {
380 name: "series",
381 param_type: "Table<any>",
382 optional: false,
383 description: "Input series",
384 }],
385 return_type: "number",
386 example: Some("sum(volumes)"),
387 },
388 BuiltinMetadata {
389 name: "mean",
390 signature: "mean(table: Table<any>) -> number",
391 description: "Compute the mean of all values in a series.",
392 category: "Statistics",
393 parameters: &[BuiltinParam {
394 name: "series",
395 param_type: "Table<any>",
396 optional: false,
397 description: "Input series",
398 }],
399 return_type: "number",
400 example: Some("mean(prices)"),
401 },
402 BuiltinMetadata {
403 name: "stddev",
404 signature: "stddev(values) -> number",
405 description: "Compute the standard deviation.",
406 category: "Statistics",
407 parameters: &[BuiltinParam {
408 name: "values",
409 param_type: "any",
410 optional: false,
411 description: "Input values",
412 }],
413 return_type: "number",
414 example: Some("stddev(returns)"),
415 },
416 BuiltinMetadata {
417 name: "count",
418 signature: "count(array: Vec) -> number",
419 description: "Count the number of elements in an array.",
420 category: "Vec",
421 parameters: &[BuiltinParam {
422 name: "array",
423 param_type: "Vec",
424 optional: false,
425 description: "Input array",
426 }],
427 return_type: "number",
428 example: Some("count(items)"),
429 },
430 BuiltinMetadata {
431 name: "highest",
432 signature: "highest(collection, count: number) -> number",
433 description: "Return the highest value from a collection.",
434 category: "Vec",
435 parameters: &[
436 BuiltinParam {
437 name: "collection",
438 param_type: "any",
439 optional: false,
440 description: "Input collection",
441 },
442 BuiltinParam {
443 name: "count",
444 param_type: "number",
445 optional: false,
446 description: "Number of values",
447 },
448 ],
449 return_type: "number",
450 example: Some("highest(prices, 10)"),
451 },
452 BuiltinMetadata {
453 name: "lowest",
454 signature: "lowest(collection, count: number) -> number",
455 description: "Return the lowest value from a collection.",
456 category: "Vec",
457 parameters: &[
458 BuiltinParam {
459 name: "collection",
460 param_type: "any",
461 optional: false,
462 description: "Input collection",
463 },
464 BuiltinParam {
465 name: "count",
466 param_type: "number",
467 optional: false,
468 description: "Number of values",
469 },
470 ],
471 return_type: "number",
472 example: Some("lowest(prices, 10)"),
473 },
474 BuiltinMetadata {
476 name: "format",
477 signature: "format(value, template) -> string",
478 description: "Format a value using a template string.",
479 category: "Utility",
480 parameters: &[
481 BuiltinParam {
482 name: "value",
483 param_type: "any",
484 optional: false,
485 description: "Value to format",
486 },
487 BuiltinParam {
488 name: "template",
489 param_type: "any",
490 optional: false,
491 description: "Format template",
492 },
493 ],
494 return_type: "string",
495 example: Some("format(0.15, \"percent\") // \"15%\""),
496 },
497 BuiltinMetadata {
498 name: "format_percent",
499 signature: "format_percent(value) -> string",
500 description: "Format a number as a percentage string.",
501 category: "Utility",
502 parameters: &[BuiltinParam {
503 name: "value",
504 param_type: "number",
505 optional: false,
506 description: "Decimal value",
507 }],
508 return_type: "string",
509 example: Some("format_percent(0.15) // \"15%\""),
510 },
511 BuiltinMetadata {
512 name: "format_number",
513 signature: "format_number(value, decimals?) -> string",
514 description: "Format a number with optional decimal places.",
515 category: "Utility",
516 parameters: &[
517 BuiltinParam {
518 name: "value",
519 param_type: "number",
520 optional: false,
521 description: "Number to format",
522 },
523 BuiltinParam {
524 name: "decimals",
525 param_type: "number",
526 optional: true,
527 description: "Decimal places",
528 },
529 ],
530 return_type: "string",
531 example: Some("format_number(1234.5, 2) // \"1234.50\""),
532 },
533 BuiltinMetadata {
535 name: "shift",
536 signature: "shift(table: Table<any>, periods: number) -> Table<any>",
537 description: "Shift series values by a number of periods.",
538 category: "Column",
539 parameters: &[
540 BuiltinParam {
541 name: "series",
542 param_type: "Table<any>",
543 optional: false,
544 description: "Input series",
545 },
546 BuiltinParam {
547 name: "periods",
548 param_type: "number",
549 optional: false,
550 description: "Number of periods to shift",
551 },
552 ],
553 return_type: "Table<any>",
554 example: Some("shift(prices, 1) // previous day's prices"),
555 },
556 BuiltinMetadata {
557 name: "resample",
558 signature: "resample(table: Table<any>, timeframe: string, method: string) -> Table<any>",
559 description: "Resample a series to a different timeframe.",
560 category: "Column",
561 parameters: &[
562 BuiltinParam {
563 name: "series",
564 param_type: "Table<any>",
565 optional: false,
566 description: "Input series",
567 },
568 BuiltinParam {
569 name: "timeframe",
570 param_type: "string",
571 optional: false,
572 description: "Target timeframe",
573 },
574 BuiltinParam {
575 name: "method",
576 param_type: "string",
577 optional: false,
578 description: "Aggregation method",
579 },
580 ],
581 return_type: "Table<any>",
582 example: Some("resample(prices, \"1h\", \"last\")"),
583 },
584 BuiltinMetadata {
585 name: "map",
586 signature: "map(table: Table<any>, fn: Function) -> Table<any>",
587 description: "Apply a function to each element of a series.",
588 category: "Column",
589 parameters: &[
590 BuiltinParam {
591 name: "series",
592 param_type: "Table<any>",
593 optional: false,
594 description: "Input series",
595 },
596 BuiltinParam {
597 name: "fn",
598 param_type: "Function",
599 optional: false,
600 description: "Transform function",
601 },
602 ],
603 return_type: "Table<any>",
604 example: Some("map(prices, (p) => p * 1.1)"),
605 },
606 BuiltinMetadata {
607 name: "filter",
608 signature: "filter(table: Table<any>, predicate: Function) -> Table<any>",
609 description: "Filter series elements by a predicate function.",
610 category: "Column",
611 parameters: &[
612 BuiltinParam {
613 name: "series",
614 param_type: "Table<any>",
615 optional: false,
616 description: "Input series",
617 },
618 BuiltinParam {
619 name: "predicate",
620 param_type: "Function",
621 optional: false,
622 description: "Filter predicate",
623 },
624 ],
625 return_type: "Table<any>",
626 example: Some("filter(prices, (p) => p > 100)"),
627 },
628 BuiltinMetadata {
630 name: "Ok",
631 signature: "Ok(value) -> Result<T>",
632 description: "Wrap a value in a successful Result.",
633 category: "Utility",
634 parameters: &[BuiltinParam {
635 name: "value",
636 param_type: "any",
637 optional: false,
638 description: "Success value",
639 }],
640 return_type: "Result<T>",
641 example: Some("Ok(42)"),
642 },
643 BuiltinMetadata {
644 name: "Err",
645 signature: "Err(error) -> Result<T>",
646 description: "Create an error Result.",
647 category: "Utility",
648 parameters: &[BuiltinParam {
649 name: "error",
650 param_type: "any",
651 optional: false,
652 description: "Error value",
653 }],
654 return_type: "Result<T>",
655 example: Some("Err(\"not found\")"),
656 },
657 BuiltinMetadata {
659 name: "snapshot",
660 signature: "snapshot() -> Snapshot",
661 description: "Create a snapshot suspension point. Returns Snapshot::Hash(id) after saving, or Snapshot::Resumed when restoring from a snapshot.",
662 category: "Resumability",
663 parameters: &[],
664 return_type: "Snapshot",
665 example: Some(
666 "let result = snapshot()\nmatch result {\n Snapshot::Hash(id) => print(\"Saved: \" + id),\n Snapshot::Resumed => print(\"Restored!\"),\n}",
667 ),
668 },
669 BuiltinMetadata {
670 name: "exit",
671 signature: "exit(code?: number) -> ()",
672 description: "Terminate the process with an optional exit code.",
673 category: "Utility",
674 parameters: &[BuiltinParam {
675 name: "code",
676 param_type: "number",
677 optional: true,
678 description: "Exit code (default 0)",
679 }],
680 return_type: "()",
681 example: Some("exit(0)"),
682 },
683 BuiltinMetadata {
685 name: "implements",
686 signature: "implements(type_name: string, trait_name: string) -> bool",
687 description: "Returns true if the given type implements the specified trait. Only valid inside comptime blocks.",
688 category: "Comptime",
689 parameters: &[
690 BuiltinParam {
691 name: "type_name",
692 param_type: "string",
693 optional: false,
694 description: "Type name to check",
695 },
696 BuiltinParam {
697 name: "trait_name",
698 param_type: "string",
699 optional: false,
700 description: "Trait name to check",
701 },
702 ],
703 return_type: "bool",
704 example: Some("comptime { implements(\"Point\", \"Display\") }"),
705 },
706 BuiltinMetadata {
707 name: "warning",
708 signature: "warning(msg: string) -> ()",
709 description: "Emit a compile-time warning. Only valid inside comptime blocks.",
710 category: "Comptime",
711 parameters: &[BuiltinParam {
712 name: "msg",
713 param_type: "string",
714 optional: false,
715 description: "Warning message",
716 }],
717 return_type: "()",
718 example: Some("comptime { warning(\"generated fallback path\") }"),
719 },
720 BuiltinMetadata {
721 name: "error",
722 signature: "error(msg: string) -> never",
723 description: "Emit a compile-time error and abort compilation. Only valid inside comptime blocks.",
724 category: "Comptime",
725 parameters: &[BuiltinParam {
726 name: "msg",
727 param_type: "string",
728 optional: false,
729 description: "Error message",
730 }],
731 return_type: "never",
732 example: Some("comptime { error(\"invariant violated\") }"),
733 },
734 BuiltinMetadata {
735 name: "build_config",
736 signature: "build_config() -> Object",
737 description: "Returns build-time configuration (debug, version, target_os, target_arch). Only valid inside comptime blocks.",
738 category: "Comptime",
739 parameters: &[],
740 return_type: "Object",
741 example: Some("let v = comptime { build_config().version }"),
742 },
743];
744
745pub fn collect_builtin_metadata() -> Vec<&'static BuiltinMetadata> {
749 CORE_BUILTINS.iter().collect()
750}
751
752pub fn builtin_functions_from_macros() -> Vec<FunctionInfo> {
754 collect_builtin_metadata()
755 .into_iter()
756 .map(|m| m.into())
757 .collect()
758}
759
760pub fn is_comptime_builtin_function(name: &str) -> bool {
764 CORE_BUILTINS
765 .iter()
766 .any(|m| m.name == name && m.category == "Comptime")
767}
768
769pub static TYPE_METADATA_ROW: TypeMetadata = TypeMetadata {
773 name: "Row",
774 description: "Generic data row with dynamic fields",
775 properties: &[],
776};
777
778pub fn collect_core_type_metadata() -> Vec<&'static TypeMetadata> {
784 vec![&TYPE_METADATA_ROW]
785}
786
787pub fn collect_domain_type_metadata() -> Vec<&'static TypeMetadata> {
793 vec![]
794}
795
796pub fn collect_type_metadata() -> Vec<&'static TypeMetadata> {
806 let mut types = collect_core_type_metadata();
807 types.extend(collect_domain_type_metadata());
808 types
809}
810
811#[cfg(test)]
812mod tests {
813 use super::*;
814
815 #[test]
816 fn test_builtin_metadata_to_function_info() {
817 static TEST_PARAMS: &[BuiltinParam] = &[BuiltinParam {
818 name: "value",
819 param_type: "Number",
820 optional: false,
821 description: "Input value",
822 }];
823
824 let meta = BuiltinMetadata {
825 name: "test_fn",
826 signature: "test_fn(value: Number) -> Number",
827 description: "A test function",
828 category: "Math",
829 parameters: TEST_PARAMS,
830 return_type: "Number",
831 example: Some("test_fn(42)"),
832 };
833
834 let info: FunctionInfo = (&meta).into();
835
836 assert_eq!(info.name, "test_fn");
837 assert_eq!(info.signature, "test_fn(value: Number) -> Number");
838 assert_eq!(info.description, "A test function");
839 assert_eq!(info.category, FunctionCategory::Math);
840 assert_eq!(info.parameters.len(), 1);
841 assert_eq!(info.parameters[0].name, "value");
842 assert_eq!(info.return_type, "Number");
843 assert_eq!(info.example, Some("test_fn(42)".to_string()));
844 assert!(info.implemented);
845 }
846}