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: "range",
310 signature: "range(start, end, step?) -> Vec<number>",
311 description: "Generate an array of numbers from start to end.",
312 category: "Utility",
313 parameters: &[
314 BuiltinParam {
315 name: "start",
316 param_type: "number",
317 optional: false,
318 description: "Start value",
319 },
320 BuiltinParam {
321 name: "end",
322 param_type: "number",
323 optional: false,
324 description: "End value (exclusive)",
325 },
326 BuiltinParam {
327 name: "step",
328 param_type: "number",
329 optional: true,
330 description: "Step size (default 1)",
331 },
332 ],
333 return_type: "Vec<number>",
334 example: Some("range(0, 5) // [0, 1, 2, 3, 4]"),
335 },
336 BuiltinMetadata {
339 name: "avg",
340 signature: "avg(collection, value: number) -> number",
341 description: "Compute the average of values in a collection.",
342 category: "Statistics",
343 parameters: &[
344 BuiltinParam {
345 name: "collection",
346 param_type: "any",
347 optional: false,
348 description: "Input collection",
349 },
350 BuiltinParam {
351 name: "value",
352 param_type: "number",
353 optional: false,
354 description: "Value to average",
355 },
356 ],
357 return_type: "number",
358 example: Some("avg(items, row => row.price)"),
359 },
360 BuiltinMetadata {
361 name: "sum",
362 signature: "sum(table: Table<any>) -> number",
363 description: "Compute the sum of all values in a series.",
364 category: "Statistics",
365 parameters: &[BuiltinParam {
366 name: "series",
367 param_type: "Table<any>",
368 optional: false,
369 description: "Input series",
370 }],
371 return_type: "number",
372 example: Some("sum(volumes)"),
373 },
374 BuiltinMetadata {
375 name: "mean",
376 signature: "mean(table: Table<any>) -> number",
377 description: "Compute the mean 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("mean(prices)"),
387 },
388 BuiltinMetadata {
389 name: "stddev",
390 signature: "stddev(values) -> number",
391 description: "Compute the standard deviation.",
392 category: "Statistics",
393 parameters: &[BuiltinParam {
394 name: "values",
395 param_type: "any",
396 optional: false,
397 description: "Input values",
398 }],
399 return_type: "number",
400 example: Some("stddev(returns)"),
401 },
402 BuiltinMetadata {
403 name: "count",
404 signature: "count(array: Vec) -> number",
405 description: "Count the number of elements in an array.",
406 category: "Vec",
407 parameters: &[BuiltinParam {
408 name: "array",
409 param_type: "Vec",
410 optional: false,
411 description: "Input array",
412 }],
413 return_type: "number",
414 example: Some("count(items)"),
415 },
416 BuiltinMetadata {
417 name: "highest",
418 signature: "highest(collection, count: number) -> number",
419 description: "Return the highest value from a collection.",
420 category: "Vec",
421 parameters: &[
422 BuiltinParam {
423 name: "collection",
424 param_type: "any",
425 optional: false,
426 description: "Input collection",
427 },
428 BuiltinParam {
429 name: "count",
430 param_type: "number",
431 optional: false,
432 description: "Number of values",
433 },
434 ],
435 return_type: "number",
436 example: Some("highest(prices, 10)"),
437 },
438 BuiltinMetadata {
439 name: "lowest",
440 signature: "lowest(collection, count: number) -> number",
441 description: "Return the lowest value from a collection.",
442 category: "Vec",
443 parameters: &[
444 BuiltinParam {
445 name: "collection",
446 param_type: "any",
447 optional: false,
448 description: "Input collection",
449 },
450 BuiltinParam {
451 name: "count",
452 param_type: "number",
453 optional: false,
454 description: "Number of values",
455 },
456 ],
457 return_type: "number",
458 example: Some("lowest(prices, 10)"),
459 },
460 BuiltinMetadata {
462 name: "format",
463 signature: "format(value, template) -> string",
464 description: "Format a value using a template string.",
465 category: "Utility",
466 parameters: &[
467 BuiltinParam {
468 name: "value",
469 param_type: "any",
470 optional: false,
471 description: "Value to format",
472 },
473 BuiltinParam {
474 name: "template",
475 param_type: "any",
476 optional: false,
477 description: "Format template",
478 },
479 ],
480 return_type: "string",
481 example: Some("format(0.15, \"percent\") // \"15%\""),
482 },
483 BuiltinMetadata {
491 name: "shift",
492 signature: "shift(table: Table<any>, periods: number) -> Table<any>",
493 description: "Shift series values by a number of periods.",
494 category: "Column",
495 parameters: &[
496 BuiltinParam {
497 name: "series",
498 param_type: "Table<any>",
499 optional: false,
500 description: "Input series",
501 },
502 BuiltinParam {
503 name: "periods",
504 param_type: "number",
505 optional: false,
506 description: "Number of periods to shift",
507 },
508 ],
509 return_type: "Table<any>",
510 example: Some("shift(prices, 1) // previous day's prices"),
511 },
512 BuiltinMetadata {
513 name: "resample",
514 signature: "resample(table: Table<any>, timeframe: string, method: string) -> Table<any>",
515 description: "Resample a series to a different timeframe.",
516 category: "Column",
517 parameters: &[
518 BuiltinParam {
519 name: "series",
520 param_type: "Table<any>",
521 optional: false,
522 description: "Input series",
523 },
524 BuiltinParam {
525 name: "timeframe",
526 param_type: "string",
527 optional: false,
528 description: "Target timeframe",
529 },
530 BuiltinParam {
531 name: "method",
532 param_type: "string",
533 optional: false,
534 description: "Aggregation method",
535 },
536 ],
537 return_type: "Table<any>",
538 example: Some("resample(prices, \"1h\", \"last\")"),
539 },
540 BuiltinMetadata {
541 name: "map",
542 signature: "map(table: Table<any>, fn: Function) -> Table<any>",
543 description: "Apply a function to each element of a series.",
544 category: "Column",
545 parameters: &[
546 BuiltinParam {
547 name: "series",
548 param_type: "Table<any>",
549 optional: false,
550 description: "Input series",
551 },
552 BuiltinParam {
553 name: "fn",
554 param_type: "Function",
555 optional: false,
556 description: "Transform function",
557 },
558 ],
559 return_type: "Table<any>",
560 example: Some("map(prices, (p) => p * 1.1)"),
561 },
562 BuiltinMetadata {
563 name: "filter",
564 signature: "filter(table: Table<any>, predicate: Function) -> Table<any>",
565 description: "Filter series elements by a predicate function.",
566 category: "Column",
567 parameters: &[
568 BuiltinParam {
569 name: "series",
570 param_type: "Table<any>",
571 optional: false,
572 description: "Input series",
573 },
574 BuiltinParam {
575 name: "predicate",
576 param_type: "Function",
577 optional: false,
578 description: "Filter predicate",
579 },
580 ],
581 return_type: "Table<any>",
582 example: Some("filter(prices, (p) => p > 100)"),
583 },
584 BuiltinMetadata {
586 name: "Ok",
587 signature: "Ok(value) -> Result<T>",
588 description: "Wrap a value in a successful Result.",
589 category: "Utility",
590 parameters: &[BuiltinParam {
591 name: "value",
592 param_type: "any",
593 optional: false,
594 description: "Success value",
595 }],
596 return_type: "Result<T>",
597 example: Some("Ok(42)"),
598 },
599 BuiltinMetadata {
600 name: "Err",
601 signature: "Err(error) -> Result<T>",
602 description: "Create an error Result.",
603 category: "Utility",
604 parameters: &[BuiltinParam {
605 name: "error",
606 param_type: "any",
607 optional: false,
608 description: "Error value",
609 }],
610 return_type: "Result<T>",
611 example: Some("Err(\"not found\")"),
612 },
613 BuiltinMetadata {
615 name: "snapshot",
616 signature: "snapshot() -> Snapshot",
617 description: "Create a snapshot suspension point. Returns Snapshot::Hash(id) after saving, or Snapshot::Resumed when restoring from a snapshot.",
618 category: "Resumability",
619 parameters: &[],
620 return_type: "Snapshot",
621 example: Some(
622 "let result = snapshot()\nmatch result {\n Snapshot::Hash(id) => print(\"Saved: \" + id),\n Snapshot::Resumed => print(\"Restored!\"),\n}",
623 ),
624 },
625 BuiltinMetadata {
626 name: "exit",
627 signature: "exit(code?: number) -> ()",
628 description: "Terminate the process with an optional exit code.",
629 category: "Utility",
630 parameters: &[BuiltinParam {
631 name: "code",
632 param_type: "number",
633 optional: true,
634 description: "Exit code (default 0)",
635 }],
636 return_type: "()",
637 example: Some("exit(0)"),
638 },
639 BuiltinMetadata {
641 name: "implements",
642 signature: "implements(type_name: string, trait_name: string) -> bool",
643 description: "Returns true if the given type implements the specified trait. Only valid inside comptime blocks.",
644 category: "Comptime",
645 parameters: &[
646 BuiltinParam {
647 name: "type_name",
648 param_type: "string",
649 optional: false,
650 description: "Type name to check",
651 },
652 BuiltinParam {
653 name: "trait_name",
654 param_type: "string",
655 optional: false,
656 description: "Trait name to check",
657 },
658 ],
659 return_type: "bool",
660 example: Some("comptime { implements(\"Point\", \"Display\") }"),
661 },
662 BuiltinMetadata {
663 name: "warning",
664 signature: "warning(msg: string) -> ()",
665 description: "Emit a compile-time warning. Only valid inside comptime blocks.",
666 category: "Comptime",
667 parameters: &[BuiltinParam {
668 name: "msg",
669 param_type: "string",
670 optional: false,
671 description: "Warning message",
672 }],
673 return_type: "()",
674 example: Some("comptime { warning(\"generated fallback path\") }"),
675 },
676 BuiltinMetadata {
677 name: "error",
678 signature: "error(msg: string) -> never",
679 description: "Emit a compile-time error and abort compilation. Only valid inside comptime blocks.",
680 category: "Comptime",
681 parameters: &[BuiltinParam {
682 name: "msg",
683 param_type: "string",
684 optional: false,
685 description: "Error message",
686 }],
687 return_type: "never",
688 example: Some("comptime { error(\"invariant violated\") }"),
689 },
690 BuiltinMetadata {
691 name: "build_config",
692 signature: "build_config() -> Object",
693 description: "Returns build-time configuration (debug, version, target_os, target_arch). Only valid inside comptime blocks.",
694 category: "Comptime",
695 parameters: &[],
696 return_type: "Object",
697 example: Some("let v = comptime { build_config().version }"),
698 },
699 BuiltinMetadata {
706 name: "type_info",
707 signature: "type_info(type_name: string) -> TypeInfo",
708 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.",
709 category: "Comptime",
710 parameters: &[BuiltinParam {
711 name: "type_name",
712 param_type: "string",
713 optional: false,
714 description: "Type name to reflect on (bare identifiers are auto-stringified at the call site)",
715 }],
716 return_type: "TypeInfo",
717 example: Some("comptime { let ti = type_info(Point); print(ti.name) }"),
718 },
719];
720
721pub fn collect_builtin_metadata() -> Vec<&'static BuiltinMetadata> {
725 CORE_BUILTINS.iter().collect()
726}
727
728pub fn builtin_functions_from_macros() -> Vec<FunctionInfo> {
730 collect_builtin_metadata()
731 .into_iter()
732 .map(|m| m.into())
733 .collect()
734}
735
736pub fn is_comptime_builtin_function(name: &str) -> bool {
740 CORE_BUILTINS
741 .iter()
742 .any(|m| m.name == name && m.category == "Comptime")
743}
744
745pub static TYPE_METADATA_ROW: TypeMetadata = TypeMetadata {
749 name: "Row",
750 description: "Generic data row with dynamic fields",
751 properties: &[],
752};
753
754pub fn collect_core_type_metadata() -> Vec<&'static TypeMetadata> {
760 vec![&TYPE_METADATA_ROW]
761}
762
763pub fn collect_domain_type_metadata() -> Vec<&'static TypeMetadata> {
769 vec![]
770}
771
772pub fn collect_type_metadata() -> Vec<&'static TypeMetadata> {
782 let mut types = collect_core_type_metadata();
783 types.extend(collect_domain_type_metadata());
784 types
785}
786
787#[cfg(test)]
788mod tests {
789 use super::*;
790
791 #[test]
792 fn test_builtin_metadata_to_function_info() {
793 static TEST_PARAMS: &[BuiltinParam] = &[BuiltinParam {
794 name: "value",
795 param_type: "Number",
796 optional: false,
797 description: "Input value",
798 }];
799
800 let meta = BuiltinMetadata {
801 name: "test_fn",
802 signature: "test_fn(value: Number) -> Number",
803 description: "A test function",
804 category: "Math",
805 parameters: TEST_PARAMS,
806 return_type: "Number",
807 example: Some("test_fn(42)"),
808 };
809
810 let info: FunctionInfo = (&meta).into();
811
812 assert_eq!(info.name, "test_fn");
813 assert_eq!(info.signature, "test_fn(value: Number) -> Number");
814 assert_eq!(info.description, "A test function");
815 assert_eq!(info.category, FunctionCategory::Math);
816 assert_eq!(info.parameters.len(), 1);
817 assert_eq!(info.parameters[0].name, "value");
818 assert_eq!(info.return_type, "Number");
819 assert_eq!(info.example, Some("test_fn(42)".to_string()));
820 assert!(info.implemented);
821 }
822}