1use std::collections::HashMap;
7
8use crate::ty::{FnSig, Type};
9
10#[derive(Debug)]
12pub struct StdlibRegistry {
13 modules: HashMap<String, HashMap<String, FnSig>>,
14 constants: HashMap<String, HashMap<String, Type>>,
16}
17
18impl StdlibRegistry {
19 pub fn new() -> Self {
21 let mut reg = Self {
22 modules: HashMap::new(),
23 constants: HashMap::new(),
24 };
25 reg.register_core();
26 reg.register_math();
27 reg.register_string();
28 reg.register_list();
29 reg.register_record();
30 reg.register_time();
31 reg.register_convert();
32 reg.register_json();
33 reg.register_timer();
34 reg.register_http();
35 reg.register_storage();
36 reg.register_location();
37 reg.register_notifications();
38 reg
39 }
40
41 pub fn get(&self, module: &str, function: &str) -> Option<&FnSig> {
43 self.modules.get(module)?.get(function)
44 }
45
46 pub fn has_module(&self, module: &str) -> bool {
48 self.modules.contains_key(module) || self.constants.contains_key(module)
49 }
50
51 pub fn get_constant(&self, module: &str, name: &str) -> Option<&Type> {
53 self.constants.get(module)?.get(name)
54 }
55
56 pub fn modules(&self) -> &HashMap<String, HashMap<String, FnSig>> {
58 &self.modules
59 }
60
61 pub fn all_constants(&self) -> &HashMap<String, HashMap<String, Type>> {
63 &self.constants
64 }
65
66 fn add(&mut self, module: &str, name: &str, sig: FnSig) {
71 self.modules
72 .entry(module.to_string())
73 .or_default()
74 .insert(name.to_string(), sig);
75 }
76
77 fn add_const(&mut self, module: &str, name: &str, ty: Type) {
78 self.constants
79 .entry(module.to_string())
80 .or_default()
81 .insert(name.to_string(), ty);
82 }
83
84 fn sig(params: Vec<(&str, Type)>, ret: Type) -> FnSig {
85 FnSig {
86 params: params
87 .into_iter()
88 .map(|(n, t)| (n.to_string(), t))
89 .collect(),
90 ret,
91 variadic: false,
92 }
93 }
94
95 fn variadic_sig(params: Vec<(&str, Type)>, ret: Type) -> FnSig {
96 FnSig {
97 params: params
98 .into_iter()
99 .map(|(n, t)| (n.to_string(), t))
100 .collect(),
101 ret,
102 variadic: true,
103 }
104 }
105
106 fn register_core(&mut self) {
112 use Type::*;
113 self.add("core", "log", Self::sig(vec![("value", Any)], Nil));
114 self.add(
115 "core",
116 "assert",
117 Self::sig(vec![("condition", Bool), ("message", String)], Nil),
118 );
119 self.add("core", "type_of", Self::sig(vec![("value", Any)], String));
120 self.add(
121 "core",
122 "capability",
123 Self::sig(vec![("name", String)], Bool),
124 );
125 }
126
127 fn register_math(&mut self) {
129 use Type::*;
130 self.add("math", "abs", Self::sig(vec![("x", Number)], Number));
131 self.add(
132 "math",
133 "min",
134 Self::sig(vec![("a", Number), ("b", Number)], Number),
135 );
136 self.add(
137 "math",
138 "max",
139 Self::sig(vec![("a", Number), ("b", Number)], Number),
140 );
141 self.add("math", "floor", Self::sig(vec![("x", Number)], Number));
142 self.add("math", "ceil", Self::sig(vec![("x", Number)], Number));
143 self.add("math", "round", Self::sig(vec![("x", Number)], Number));
144 self.add(
145 "math",
146 "round_to",
147 Self::sig(vec![("x", Number), ("decimals", Number)], Number),
148 );
149 self.add(
150 "math",
151 "pow",
152 Self::sig(vec![("base", Number), ("exp", Number)], Number),
153 );
154 self.add(
155 "math",
156 "clamp",
157 Self::sig(vec![("x", Number), ("min", Number), ("max", Number)], Number),
158 );
159 self.add("math", "sqrt", Self::sig(vec![("x", Number)], Number));
160
161 self.add_const("math", "PI", Number);
163 self.add_const("math", "E", Number);
164 }
165
166 fn register_string(&mut self) {
168 use Type::*;
169 self.add(
170 "string",
171 "length",
172 Self::sig(vec![("s", String)], Number),
173 );
174 self.add(
175 "string",
176 "concat",
177 Self::sig(vec![("a", String), ("b", String)], String),
178 );
179 self.add(
180 "string",
181 "contains",
182 Self::sig(vec![("s", String), ("substr", String)], Bool),
183 );
184 self.add(
185 "string",
186 "slice",
187 Self::sig(
188 vec![("s", String), ("start", Number), ("end", Number)],
189 String,
190 ),
191 );
192 self.add("string", "trim", Self::sig(vec![("s", String)], String));
193 self.add(
194 "string",
195 "split",
196 Self::sig(
197 vec![("s", String), ("delimiter", String)],
198 List(Box::new(String)),
199 ),
200 );
201 self.add(
202 "string",
203 "to_upper",
204 Self::sig(vec![("s", String)], String),
205 );
206 self.add(
207 "string",
208 "to_lower",
209 Self::sig(vec![("s", String)], String),
210 );
211 self.add(
212 "string",
213 "starts_with",
214 Self::sig(vec![("s", String), ("prefix", String)], Bool),
215 );
216 self.add(
217 "string",
218 "ends_with",
219 Self::sig(vec![("s", String), ("suffix", String)], Bool),
220 );
221 self.add(
222 "string",
223 "replace",
224 Self::sig(
225 vec![("s", String), ("from", String), ("to", String)],
226 String,
227 ),
228 );
229 self.add(
230 "string",
231 "replace_all",
232 Self::sig(
233 vec![("s", String), ("from", String), ("to", String)],
234 String,
235 ),
236 );
237 self.add(
238 "string",
239 "pad_start",
240 Self::sig(
241 vec![("s", String), ("length", Number), ("pad", String)],
242 String,
243 ),
244 );
245 self.add(
246 "string",
247 "pad_end",
248 Self::sig(
249 vec![("s", String), ("length", Number), ("pad", String)],
250 String,
251 ),
252 );
253 self.add(
254 "string",
255 "repeat",
256 Self::sig(vec![("s", String), ("count", Number)], String),
257 );
258 self.add(
259 "string",
260 "join",
261 Self::sig(
262 vec![("items", List(Box::new(String))), ("separator", String)],
263 String,
264 ),
265 );
266 self.add(
267 "string",
268 "format",
269 Self::sig(
270 vec![("template", String), ("values", Record(vec![]))],
271 String,
272 ),
273 );
274 self.add("string", "from", Self::sig(vec![("value", Any)], String));
275 self.add(
276 "string",
277 "is_empty",
278 Self::sig(vec![("s", String)], Bool),
279 );
280 self.add(
281 "string",
282 "index_of",
283 Self::sig(vec![("s", String), ("substr", String)], Number),
284 );
285 }
286
287 fn register_list(&mut self) {
289 use Type::*;
290 let t = || Any; let list_t = || List(Box::new(Any));
292
293 self.add("list", "empty", Self::sig(vec![], list_t()));
295 self.add("list", "of", Self::variadic_sig(vec![("items", t())], list_t()));
296 self.add(
297 "list",
298 "repeat",
299 Self::sig(vec![("value", t()), ("count", Number)], list_t()),
300 );
301 self.add(
302 "list",
303 "range",
304 Self::sig(vec![("start", Number), ("end", Number)], List(Box::new(Number))),
305 );
306
307 self.add(
309 "list",
310 "length",
311 Self::sig(vec![("items", list_t())], Number),
312 );
313 self.add(
314 "list",
315 "get",
316 Self::sig(vec![("items", list_t()), ("index", Number)], t()),
317 );
318 self.add(
319 "list",
320 "first",
321 Self::sig(vec![("items", list_t())], t()),
322 );
323 self.add(
324 "list",
325 "last",
326 Self::sig(vec![("items", list_t())], t()),
327 );
328 self.add(
329 "list",
330 "index_of",
331 Self::sig(vec![("items", list_t()), ("value", t())], Number),
332 );
333
334 self.add(
336 "list",
337 "append",
338 Self::sig(vec![("items", list_t()), ("value", t())], list_t()),
339 );
340 self.add(
341 "list",
342 "prepend",
343 Self::sig(vec![("items", list_t()), ("value", t())], list_t()),
344 );
345 self.add(
346 "list",
347 "insert",
348 Self::sig(
349 vec![("items", list_t()), ("index", Number), ("value", t())],
350 list_t(),
351 ),
352 );
353 self.add(
354 "list",
355 "remove",
356 Self::sig(vec![("items", list_t()), ("index", Number)], list_t()),
357 );
358 self.add(
359 "list",
360 "update",
361 Self::sig(
362 vec![("items", list_t()), ("index", Number), ("value", t())],
363 list_t(),
364 ),
365 );
366 self.add(
368 "list",
369 "set",
370 Self::sig(
371 vec![("items", list_t()), ("index", Number), ("value", t())],
372 list_t(),
373 ),
374 );
375 self.add(
376 "list",
377 "slice",
378 Self::sig(
379 vec![("items", list_t()), ("start", Number), ("end", Number)],
380 list_t(),
381 ),
382 );
383 self.add(
384 "list",
385 "concat",
386 Self::sig(vec![("a", list_t()), ("b", list_t())], list_t()),
387 );
388 self.add(
389 "list",
390 "reverse",
391 Self::sig(vec![("items", list_t())], list_t()),
392 );
393 self.add(
394 "list",
395 "flatten",
396 Self::sig(vec![("items", list_t())], list_t()),
397 );
398 self.add(
399 "list",
400 "unique",
401 Self::sig(vec![("items", list_t())], list_t()),
402 );
403
404 self.add(
406 "list",
407 "map",
408 Self::sig(
409 vec![
410 ("items", list_t()),
411 ("f", Function(vec![t()], Box::new(t()))),
412 ],
413 list_t(),
414 ),
415 );
416 self.add(
417 "list",
418 "filter",
419 Self::sig(
420 vec![
421 ("items", list_t()),
422 ("predicate", Function(vec![t()], Box::new(Bool))),
423 ],
424 list_t(),
425 ),
426 );
427 self.add(
428 "list",
429 "reduce",
430 Self::sig(
431 vec![
432 ("items", list_t()),
433 ("initial", t()),
434 ("f", Function(vec![t(), t()], Box::new(t()))),
435 ],
436 t(),
437 ),
438 );
439 self.add(
440 "list",
441 "find",
442 Self::sig(
443 vec![
444 ("items", list_t()),
445 ("predicate", Function(vec![t()], Box::new(Bool))),
446 ],
447 Nullable(Box::new(t())),
448 ),
449 );
450 self.add(
451 "list",
452 "find_index",
453 Self::sig(
454 vec![
455 ("items", list_t()),
456 ("predicate", Function(vec![t()], Box::new(Bool))),
457 ],
458 Number,
459 ),
460 );
461 self.add(
462 "list",
463 "every",
464 Self::sig(
465 vec![
466 ("items", list_t()),
467 ("predicate", Function(vec![t()], Box::new(Bool))),
468 ],
469 Bool,
470 ),
471 );
472 self.add(
474 "list",
475 "any",
476 Self::sig(
477 vec![
478 ("items", list_t()),
479 ("predicate", Function(vec![t()], Box::new(Bool))),
480 ],
481 Bool,
482 ),
483 );
484 self.add(
485 "list",
486 "some",
487 Self::sig(
488 vec![
489 ("items", list_t()),
490 ("predicate", Function(vec![t()], Box::new(Bool))),
491 ],
492 Bool,
493 ),
494 );
495 self.add(
496 "list",
497 "sort",
498 Self::sig(
499 vec![
500 ("items", list_t()),
501 ("compare", Function(vec![t(), t()], Box::new(Number))),
502 ],
503 list_t(),
504 ),
505 );
506 self.add(
507 "list",
508 "contains",
509 Self::sig(vec![("items", list_t()), ("value", t())], Bool),
510 );
511 self.add(
512 "list",
513 "count",
514 Self::sig(
515 vec![
516 ("items", list_t()),
517 ("predicate", Function(vec![t()], Box::new(Bool))),
518 ],
519 Number,
520 ),
521 );
522 self.add(
523 "list",
524 "zip",
525 Self::sig(vec![("a", list_t()), ("b", list_t())], list_t()),
526 );
527 self.add(
528 "list",
529 "take",
530 Self::sig(vec![("items", list_t()), ("n", Number)], list_t()),
531 );
532 self.add(
533 "list",
534 "drop",
535 Self::sig(vec![("items", list_t()), ("n", Number)], list_t()),
536 );
537 }
538
539 fn register_record(&mut self) {
541 use Type::*;
542 self.add(
543 "record",
544 "get",
545 Self::sig(vec![("rec", Record(vec![])), ("key", String)], Any),
546 );
547 self.add(
548 "record",
549 "set",
550 Self::sig(
551 vec![("rec", Record(vec![])), ("key", String), ("value", Any)],
552 Record(vec![]),
553 ),
554 );
555 self.add(
556 "record",
557 "has",
558 Self::sig(vec![("rec", Record(vec![])), ("key", String)], Bool),
559 );
560 self.add(
561 "record",
562 "keys",
563 Self::sig(
564 vec![("rec", Record(vec![]))],
565 List(Box::new(String)),
566 ),
567 );
568 self.add(
569 "record",
570 "values",
571 Self::sig(vec![("rec", Record(vec![]))], List(Box::new(Any))),
572 );
573 }
574
575 fn register_time(&mut self) {
577 use Type::*;
578 self.add("time", "now", Self::sig(vec![], Number));
579 self.add(
580 "time",
581 "format",
582 Self::sig(vec![("timestamp", Number), ("pattern", String)], String),
583 );
584 self.add(
585 "time",
586 "diff",
587 Self::sig(vec![("a", Number), ("b", Number)], Number),
588 );
589 self.add(
590 "time",
591 "day_of_week",
592 Self::sig(vec![("timestamp", Number)], Number),
593 );
594 self.add(
595 "time",
596 "start_of_day",
597 Self::sig(vec![("timestamp", Number)], Number),
598 );
599 }
600
601 fn register_convert(&mut self) {
603 use Type::*;
604 self.add(
605 "convert",
606 "to_string",
607 Self::sig(vec![("value", Any)], String),
608 );
609 self.add(
610 "convert",
611 "to_number",
612 Self::sig(
613 vec![("value", Any)],
614 Result(Box::new(Number), Box::new(String)),
615 ),
616 );
617 self.add(
618 "convert",
619 "parse_int",
620 Self::sig(
621 vec![("s", String)],
622 Result(Box::new(Number), Box::new(String)),
623 ),
624 );
625 self.add(
626 "convert",
627 "parse_float",
628 Self::sig(
629 vec![("s", String)],
630 Result(Box::new(Number), Box::new(String)),
631 ),
632 );
633 self.add(
634 "convert",
635 "to_bool",
636 Self::sig(vec![("value", Any)], Bool),
637 );
638 }
639
640 fn register_json(&mut self) {
642 use Type::*;
643 self.add(
644 "json",
645 "parse",
646 Self::sig(
647 vec![("s", String)],
648 Result(Box::new(Any), Box::new(String)),
649 ),
650 );
651 self.add(
652 "json",
653 "stringify",
654 Self::sig(vec![("value", Any)], String),
655 );
656 }
657
658 fn register_timer(&mut self) {
660 use Type::*;
661 self.add(
662 "timer",
663 "start",
664 Self::sig(vec![("id", String), ("interval_ms", Number)], String),
665 );
666 self.add(
667 "timer",
668 "start_once",
669 Self::sig(vec![("id", String), ("delay_ms", Number)], String),
670 );
671 self.add(
672 "timer",
673 "stop",
674 Self::sig(vec![("id", String)], Nil),
675 );
676 self.add("timer", "stop_all", Self::sig(vec![], Nil));
677 }
678
679 fn register_http(&mut self) {
681 use Type::*;
682 let result_ty = |ok: Type| Result(Box::new(ok), Box::new(String));
683 self.add("http", "get", Self::sig(vec![("url", String)], result_ty(String)));
684 self.add(
685 "http",
686 "post",
687 Self::sig(vec![("url", String), ("body", String)], result_ty(String)),
688 );
689 self.add(
690 "http",
691 "put",
692 Self::sig(vec![("url", String), ("body", String)], result_ty(String)),
693 );
694 self.add(
695 "http",
696 "patch",
697 Self::sig(vec![("url", String), ("body", String)], result_ty(String)),
698 );
699 self.add("http", "delete", Self::sig(vec![("url", String)], result_ty(String)));
700 }
701
702 fn register_storage(&mut self) {
704 use Type::*;
705 self.add("storage", "get", Self::sig(vec![("key", String)], Nullable(Box::new(String))));
706 self.add("storage", "set", Self::sig(vec![("key", String), ("value", String)], Nil));
707 self.add("storage", "delete", Self::sig(vec![("key", String)], Nil));
709 self.add(
710 "storage",
711 "keys",
712 Self::sig(vec![], List(Box::new(String))),
713 );
714 }
715
716 fn register_location(&mut self) {
718 use Type::*;
719 self.add(
720 "location",
721 "current",
722 Self::sig(
723 vec![],
724 Record(vec![
725 crate::ty::RecordField { name: "lat".into(), ty: Number, optional: false },
726 crate::ty::RecordField { name: "lon".into(), ty: Number, optional: false },
727 ]),
728 ),
729 );
730 }
731
732 fn register_notifications(&mut self) {
734 use Type::*;
735 self.add(
736 "notifications",
737 "send",
738 Self::sig(vec![("title", String), ("body", String)], Nil),
739 );
740 }
741}
742
743impl Default for StdlibRegistry {
744 fn default() -> Self {
745 Self::new()
746 }
747}
748
749pub fn capability_modules() -> HashMap<&'static str, &'static str> {
751 let mut m = HashMap::new();
752 m.insert("http", "http");
753 m.insert("storage", "storage");
754 m.insert("location", "location");
755 m.insert("notifications", "notifications");
756 m.insert("timer", "timer");
757 m
758}