hyperon/metta/runner/stdlib/
mod.rs

1#[macro_use]
2pub mod math;
3pub mod atom;
4pub mod module;
5#[cfg(feature = "pkg_mgmt")]
6pub mod package;
7pub mod string;
8pub mod debug;
9pub mod space;
10pub mod core;
11pub mod arithmetics;
12
13use hyperon_atom::*;
14use hyperon_space::*;
15use crate::metta::*;
16use crate::metta::text::{Tokenizer, SExprParser};
17use hyperon_common::shared::Shared;
18use crate::metta::runner::{Metta, RunContext, ModuleLoader, PragmaSettings};
19use crate::metta::runner::modules::MettaMod;
20
21use regex::Regex;
22
23macro_rules! grounded_op {
24    ($name:ident, $disp:literal) => {
25        impl PartialEq for $name {
26            fn eq(&self, _other: &Self) -> bool {
27                true
28            }
29        }
30
31        impl std::fmt::Display for $name {
32            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33                write!(f, $disp)
34            }
35        }
36    }
37}
38
39pub(crate) use grounded_op;
40
41pub(crate) fn unit_result() -> Result<Vec<Atom>, ExecError> {
42    Ok(vec![UNIT_ATOM])
43}
44
45pub(crate) fn regex(regex: &str) -> Regex {
46    Regex::new(regex).unwrap()
47}
48
49pub fn interpret(space: DynSpace, expr: &Atom, settings: PragmaSettings) -> Result<Vec<Atom>, String> {
50    let expr = Atom::expr([METTA_SYMBOL, expr.clone(), ATOM_TYPE_UNDEFINED, Atom::gnd(space.clone())]);
51    let mut state = crate::metta::interpreter::interpret_init(space, &expr);
52    
53    if let Some(depth) = settings.get_string("max-stack-depth") {
54        let depth = depth.parse::<usize>().unwrap();
55        state.set_max_stack_depth(depth);
56    }
57
58    while state.has_next() {
59        state = crate::metta::interpreter::interpret_step(state);
60    }
61    state.into_result()
62}
63
64//TODO: The additional arguments are a temporary hack on account of the way the operation atoms store references
65// to the runner & module state.  https://github.com/trueagi-io/hyperon-experimental/issues/410
66fn register_context_dependent_tokens(tref: &mut Tokenizer, tokenizer: Shared<Tokenizer>, space: &DynSpace, metta: &Metta) {
67
68    atom::register_context_dependent_tokens(tref, space);
69    core::register_context_dependent_tokens(tref, space, metta);
70    module::register_context_dependent_tokens(tref, tokenizer.clone(), metta);
71    #[cfg(feature = "pkg_mgmt")]
72    package::register_context_dependent_tokens(tref, metta);
73
74    // &self should be updated
75    // TODO: adding &self might be done not by stdlib, but by MeTTa itself.
76    // TODO: adding &self introduces self referencing and thus prevents space
77    // from being freed. There are two options to eliminate this. (1) use weak
78    // pointer and somehow use the same type to represent weak and strong
79    // pointers to the atomspace. (2) resolve &self in GroundingSpace::query
80    // method without adding it into container.
81    let self_atom = Atom::gnd(space.clone());
82    tref.register_token(regex(r"&self"), move |_| { self_atom.clone() });
83}
84
85fn register_context_independent_tokens(tref: &mut Tokenizer) {
86    atom::register_context_independent_tokens(tref);
87    core::register_context_independent_tokens(tref);
88    debug::register_context_independent_tokens(tref);
89    math::register_context_independent_tokens(tref);
90    arithmetics::register_context_independent_tokens(tref);
91    string::register_context_independent_tokens(tref);
92    space::register_context_independent_tokens(tref);
93    module::register_context_independent_tokens(tref);
94}
95
96
97pub(crate) fn register_all_corelib_tokens(tref: &mut Tokenizer, tokenizer: Shared<Tokenizer>, space: &DynSpace, metta: &Metta){
98    register_context_dependent_tokens(tref, tokenizer.clone(),space, metta);
99    register_context_independent_tokens(tref);
100}
101
102pub static METTA_CODE: &'static str = include_str!("stdlib.metta");
103
104/// Loader to Initialize the corelib module
105///
106/// NOTE: the corelib will be loaded automatically if the runner is initialized with one of the high-level
107/// init functions such as [Metta::new] and [Metta::new_with_stdlib_loader]
108#[derive(Debug)]
109pub(crate) struct CoreLibLoader;
110
111impl Default for CoreLibLoader {
112    fn default() -> Self {
113        CoreLibLoader
114    }
115}
116
117impl ModuleLoader for CoreLibLoader {
118    fn load(&self, context: &mut RunContext) -> Result<(), String> {
119        let space = GroundingSpace::new();
120        context.init_self_module(space.into(), None);
121
122        self.load_tokens(context.module(), context.metta.clone())?;
123
124        let parser = SExprParser::new(METTA_CODE);
125        context.push_parser(Box::new(parser));
126        Ok(())
127    }
128
129    fn load_tokens(&self, target: &MettaMod, metta: Metta) -> Result<(), String> {
130        let tokenizer = target.tokenizer();
131        register_all_corelib_tokens(tokenizer.borrow_mut().deref_mut(),
132            tokenizer.clone(), &target.space(), &metta);
133        Ok(())
134    }
135}
136
137#[cfg(test)]
138mod tests {
139    use super::*;
140    use crate::metta::text::SExprParser;
141    use crate::metta::runner::EnvBuilder;
142    use hyperon_atom::gnd::str::Str;
143    use hyperon_atom::matcher::atoms_are_equivalent;
144    use hyperon_atom::gnd::bool::Bool;
145    use hyperon_atom::gnd::number::Number;
146    use crate::metta::runner::run_program;
147    use hyperon_atom::gnd::GroundedFunctionAtom;
148    use hyperon_common::assert_eq_metta_results;
149
150    use std::fmt::Display;
151    use hyperon_atom::gnd::number::Number::Integer;
152
153    #[test]
154    fn metta_switch() {
155        let result = run_program("!(switch (A $b) ( (($a B) ($b $a)) ((B C) (C B)) ))");
156        assert_eq!(result, Ok(vec![vec![expr!("B" "A")]]));
157        let result = run_program("!(switch (A $b) ( ((B C) (C B)) (($a B) ($b $a)) ))");
158        assert_eq!(result, Ok(vec![vec![expr!("B" "A")]]));
159        let result = run_program("!(switch (A $b) ( ((B C) (C B)) ((D E) (E B)) ))");
160        assert_eq!(result, Ok(vec![vec![]]));
161    }
162
163    #[test]
164    fn metta_is_function() {
165        let result = run_program("!(is-function (-> $t))");
166        assert_eq!(result, Ok(vec![vec![expr!({Bool(true)})]]));
167        let result = run_program("!(is-function (A $t))");
168        assert_eq!(result, Ok(vec![vec![expr!({Bool(false)})]]));
169        let result = run_program("!(is-function %Undefined%)");
170        assert_eq!(result, Ok(vec![vec![expr!({Bool(false)})]]));
171    }
172
173    #[test]
174    fn metta_type_cast() {
175        assert_eq!(run_program("(: a A) !(type-cast a A &self)"), Ok(vec![vec![expr!("a")]]));
176        assert_eq!(run_program("(: a A) !(type-cast a B &self)"), Ok(vec![vec![expr!("Error" "a" "BadType")]]));
177        assert_eq!(run_program("(: a A) !(type-cast a %Undefined% &self)"), Ok(vec![vec![expr!("a")]]));
178        assert_eq!(run_program("!(type-cast a B &self)"), Ok(vec![vec![expr!("a")]]));
179        assert_eq!(run_program("!(type-cast 42 Number &self)"), Ok(vec![vec![expr!({Number::Integer(42)})]]));
180        assert_eq!(run_program("!(type-cast 42 %Undefined% &self)"), Ok(vec![vec![expr!({Number::Integer(42)})]]));
181        assert_eq!(run_program("(: a A) !(type-cast a Atom &self)"), Ok(vec![vec![expr!("a")]]));
182        assert_eq!(run_program("(: a A) !(type-cast a Symbol &self)"), Ok(vec![vec![expr!("a")]]));
183        assert_eq!(run_program("!(type-cast 42 Grounded &self)"), Ok(vec![vec![expr!({Number::Integer(42)})]]));
184        assert_eq!(run_program("!(type-cast () Expression &self)"), Ok(vec![vec![expr!()]]));
185        assert_eq!(run_program("!(type-cast (a b) Expression &self)"), Ok(vec![vec![expr!("a" "b")]]));
186        assert_eq!(run_program("!(type-cast $v Variable &self)"), Ok(vec![vec![expr!(v)]]));
187        assert_eq!(run_program("(: a A) (: b B) !(type-cast (a b) (A B) &self)"), Ok(vec![vec![expr!("a" "b")]]));
188        assert_eq!(run_program("(: a A) (: a B) !(type-cast a A &self)"), Ok(vec![vec![expr!("a")]]));
189    }
190
191    #[test]
192    fn metta_interpret_single_atom_as_atom() {
193        let result = run_program("!(metta A Atom &self)");
194        assert_eq!(result, Ok(vec![vec![expr!("A")]]));
195    }
196
197    #[test]
198    fn metta_interpret_single_atom_as_meta_type() {
199        assert_eq!(run_program("!(metta A Symbol &self)"), Ok(vec![vec![expr!("A")]]));
200        assert_eq!(run_program("!(metta $x Variable &self)"), Ok(vec![vec![expr!(x)]]));
201        assert_eq!(run_program("!(metta (A B) Expression &self)"), Ok(vec![vec![expr!("A" "B")]]));
202        assert_eq!(run_program("!(metta 42 Grounded &self)"), Ok(vec![vec![expr!({Number::Integer(42)})]]));
203    }
204
205    #[test]
206    fn metta_check_bad_type_from_function_type_is_applicable_match_branch_1() {
207        assert_eq!(run_program("!(assertEqual (metta (+ 1 2) (-> Atom Atom $t) &self) (Error (+ 1 2) (BadType (-> Atom Atom $t) Number)))"), Ok(vec![vec![UNIT_ATOM]]));
208    }
209
210    #[test]
211    fn metta_interpret_symbol_or_grounded_value_as_type() {
212        assert_eq!(run_program("(: a A) !(metta a A &self)"), Ok(vec![vec![expr!("a")]]));
213        assert_eq!(run_program("(: a A) !(metta a B &self)"), Ok(vec![vec![expr!("Error" "a" ("BadType" "B" "A"))]]));
214        assert_eq!(run_program("!(metta 42 Number &self)"), Ok(vec![vec![expr!({Integer(42)})]]));
215    }
216
217    #[test]
218    fn metta_interpret_function_as_type() {
219        assert_eq!(run_program("(: foo (-> Atom Atom Atom)) !(metta foo Number &self)"), Ok(vec![vec![expr!("Error" "foo" ("BadType" "Number" ("->" "Atom" "Atom" "Atom")))]]));
220    }
221
222    #[test]
223    fn metta_interpret_variable_as_type() {
224        assert_eq!(run_program("!(metta $x %Undefined% &self)"), Ok(vec![vec![expr!(x)]]));
225        assert_eq!(run_program("!(metta $x SomeType &self)"), Ok(vec![vec![expr!(x)]]));
226    }
227
228    #[test]
229    fn metta_interpret_empty_expression_as_type() {
230        assert_eq!(run_program("!(metta () %Undefined% &self)"), Ok(vec![vec![expr!(())]]));
231        assert_eq!(run_program("!(metta () SomeType &self)"), Ok(vec![vec![expr!(())]]));
232    }
233
234    #[test]
235    fn metta_interpret_single_atom_as_variable_type() {
236        let result = run_program("
237            (: S Int)
238            !(chain (metta S $t &self) $res (: $res $t))
239        ");
240        assert_eq!(result, Ok(vec![vec![expr!(":" "S" "Int")]]));
241    }
242
243    #[test]
244    fn metta_interpret_func() {
245        let result = run_program("
246            (: a T)
247            (: foo (-> T T))
248            (= (foo $x) $x)
249            (= (bar $x) $x)
250            !(metta (foo (bar a)) %Undefined% &self)
251        ");
252        assert_eq!(result, Ok(vec![vec![expr!("a")]]));
253        let result = run_program("
254            (: b B)
255            (: foo (-> T T))
256            (= (foo $x) $x)
257            !(assertEqual
258                (metta (foo b) %Undefined% &self)
259                (Error (foo b) (BadArgType 1 T B)))
260        ");
261        assert_eq!(result, Ok(vec![vec![UNIT_ATOM]]));
262        let result = run_program("
263            (: Nil (List $t))
264            (: Z Nat)
265            (: S (-> Nat Nat))
266            (: Cons (-> $t (List $t) (List $t)))
267            !(assertEqual
268                (metta (Cons S (Cons Z Nil)) %Undefined% &self)
269                (Error (Cons S (Cons Z Nil)) (BadArgType 2 (List (-> Nat Nat)) (List Nat))))
270        ");
271        assert_eq!(result, Ok(vec![vec![UNIT_ATOM]]));
272        let result = run_program("
273            (: (c d) (C D))
274
275            (: foo (-> (A B) %Undefined%))
276            (= (foo $x) succ)
277
278            !(assertEqual
279                (foo (c d))
280                (Error (foo (c d)) (BadArgType 1 (A B) (C D))))
281        ");
282        assert_eq!(result, Ok(vec![vec![UNIT_ATOM]]));
283    }
284
285    #[test]
286    fn metta_interpret_tuple() {
287        assert_eq!(run_program("!(metta () %Undefined% &self)"), Ok(vec![vec![expr!(())]]));
288        assert_eq!(run_program("!(metta (a) %Undefined% &self)"), Ok(vec![vec![expr!(("a"))]]));
289        assert_eq!(run_program("!(metta (a b) %Undefined% &self)"), Ok(vec![vec![expr!(("a" "b"))]]));
290        assert_eq!(run_program("
291            (= (foo $x) (bar $x))
292            (= (bar $x) (baz $x))
293            (= (baz $x) $x)
294            !(metta ((foo A) (foo B)) %Undefined% &self)
295        "), Ok(vec![vec![expr!("A" "B")]]));
296    }
297
298    #[test]
299    fn metta_interpret_expression_as_type() {
300        assert_eq!(run_program("(= (foo $x) $x) !(metta (foo a) %Undefined% &self)"), Ok(vec![vec![expr!("a")]]));
301        assert_eq!(run_program("!(metta (foo a) %Undefined% &self)"), Ok(vec![vec![expr!("foo" "a")]]));
302        assert_eq!(run_program("!(metta () SomeType &self)"), Ok(vec![vec![expr!(())]]));
303    }
304
305    #[test]
306    fn metta_issue_872() {
307        assert_eq!(run_program("!(bind! &i 0) !(assertEqual (bind! &i 1) (Error (bind! 0 1) (BadArgType 1 Symbol Number)))"),
308                   Ok(vec![vec![UNIT_ATOM], vec![UNIT_ATOM]]));
309    }
310
311    #[test]
312    fn metta_interpret_single_atom_with_two_types() {
313        let result = run_program("(: a A) (: a B) !(metta a %Undefined% &self)");
314        assert_eq!(result, Ok(vec![vec![expr!("a")]]));
315    }
316
317    #[test]
318    fn metta_let_novar() {
319        let result = run_program("!(let (P A $b) (P $a B) (P $b $a))");
320        assert_eq!(result, Ok(vec![vec![expr!("P" "B" "A")]]));
321        let result = run_program("
322            (= (foo) (P A B))
323            !(let (P A $b) (foo) (P $b A))
324            ");
325        assert_eq!(result, Ok(vec![vec![expr!("P" "B" "A")]]));
326        let result = run_program("
327            (= (foo) (P A B))
328            !(let (foo) (P A $b) (P $b A))
329            ");
330        assert_eq!(result, Ok(vec![vec![]]));
331        let result = run_program("!(let (P A $b) (P B C) (P C B))");
332        assert_eq!(result, Ok(vec![vec![]]));
333    }
334
335    #[test]
336    fn metta_let_var() {
337        let result = run_program("!(let* () result)");
338        assert_eq!(result, Ok(vec![vec![expr!("result")]]));
339        let result = run_program("!(let* ( ((P A $b) (P $a B)) ) (P $b $a))");
340        assert_eq!(result, Ok(vec![vec![expr!("P" "B" "A")]]));
341        let result = run_program("!(let* ( ((P $a) (P A)) ((P B) (P $b)) ) (P $b $a))");
342        assert_eq!(result, Ok(vec![vec![expr!("P" "B" "A")]]));
343        let result = run_program("!(let* ( ((P $a) (P A)) ((P B) (P C)) ) (P $b $a))");
344        assert_eq!(result, Ok(vec![vec![]]));
345    }
346
347    #[test]
348    fn metta_quote_unquote() {
349        let header = "
350            (= (foo) A)
351            (= (bar $x) $x)
352        ";
353        assert_eq!(run_program(&format!("{header} !(bar (foo))")), Ok(vec![vec![sym!("A")]]), "sanity check");
354        assert_eq!(run_program(&format!("{header} !(bar (quote (foo)))")), Ok(vec![vec![expr!("quote" ("foo"))]]), "quote");
355        assert_eq!(run_program(&format!("{header} !(bar (unquote (quote (foo))))")), Ok(vec![vec![expr!("A")]]), "unquote before call");
356        assert_eq!(run_program(&format!("{header} !(unquote (bar (quote (foo))))")), Ok(vec![vec![expr!("A")]]), "unquote after call");
357    }
358
359    #[test]
360    fn metta_add_reducts() {
361        assert_eq!(run_program(&format!("!(let $newspace (new-space) (add-reducts k1))")), Ok(vec![vec![expr!("Error" ("add-reducts" "k1") "IncorrectNumberOfArguments")]]));
362
363        assert_eq!(run_program(&format!("!(let $newspace (new-space)
364                                                 (assertEqual
365                                                     (add-reducts $newspace ((k1 v1) (k2 v2) (k3 v3)))
366                                                     ()))")),
367                   Ok(vec![vec![UNIT_ATOM]]));
368
369        assert_eq!(run_program(&format!("!(let $newspace (new-space)
370                                                    (let $f (add-reducts $newspace ((k1 v1) (k2 v2) (k3 v3)))
371                                                        (assertEqual
372                                                            (match $newspace (k1 $v) $v)
373                                                            v1)))")),
374                   Ok(vec![vec![UNIT_ATOM]]));
375
376        assert_eq!(run_program(&format!("(= (pair1) (k1 v1))
377                                                 (= (pair2) (k2 v2))
378                                                 (= (pair3) (k3 v3))
379                                                 !(let $newspace (new-space)
380                                                    (let $f (add-reducts $newspace ((pair1) (pair2) (pair3)))
381                                                        (assertEqual
382                                                            (match $newspace (k1 $v) $v)
383                                                            v1)))")),
384                   Ok(vec![vec![UNIT_ATOM]]));
385    }
386
387    #[test]
388    fn metta_add_atoms() {
389        assert_eq!(run_program(&format!("!(let $newspace (new-space) (add-atoms k1))")), Ok(vec![vec![expr!("Error" ("add-atoms" "k1") "IncorrectNumberOfArguments")]]));
390
391        assert_eq!(run_program(&format!("!(let $newspace (new-space)
392                                                 (assertEqual
393                                                     (add-atoms $newspace ((k1 v1) (k2 v2) (k3 v3)))
394                                                     ()))")),
395                   Ok(vec![vec![UNIT_ATOM]]));
396
397        assert_eq!(run_program(&format!("!(let $newspace (new-space)
398                                                    (let $f (add-atoms $newspace ((k1 v1) (k2 v2) (k3 v3)))
399                                                        (assertEqual
400                                                            (match $newspace (k1 $v) $v)
401                                                            v1)))")),
402                   Ok(vec![vec![UNIT_ATOM]]));
403
404        assert_eq!(run_program(&format!("(= (pair1) (k1 v1))
405                                                 (= (pair2) (k2 v2))
406                                                 (= (pair3) (k3 v3))
407                                                 !(let $newspace (new-space)
408                                                    (let $f (add-atoms $newspace ((pair1) (pair2) (pair3)))
409                                                        (assertEqual
410                                                            (match $newspace (k1 $v) $v)
411                                                            (empty))))")),
412                   Ok(vec![vec![UNIT_ATOM]]));
413    }
414
415    #[test]
416    fn test_frog_reasoning() {
417        let program = "
418            (= (is Fritz croaks) True)
419            (= (is Fritz eats-flies) True)
420
421            (= (is Tweety chirps) True)
422            (= (is Tweety yellow) True)
423            (= (is Tweety eats-flies) True)
424
425            !(metta (if (and (is $x croaks) (is $x eats-flies)) (= (is $x frog) True) Empty) %Undefined% &self)
426        ";
427
428        assert_eq!(run_program(program),
429            Ok(vec![vec![expr!("=" ("is" "Fritz" "frog") {Bool(true)})]]));
430    }
431
432    #[test]
433    fn test_match_all() {
434        let program = "
435            (= (color) blue)
436            (= (color) red)
437            (= (color) green)
438
439            !(metta (color) %Undefined% &self)
440        ";
441
442        assert_eq_metta_results!(run_program(program),
443            Ok(vec![vec![expr!("blue"), expr!("red"), expr!("green")]]));
444    }
445
446    #[test]
447    fn test_variable_keeps_value_in_different_sub_expressions() {
448        let program = "
449            (= (eq $x $x) True)
450            (= (plus Z $y) $y)
451            (= (plus (S $k) $y) (S (plus $k $y)))
452
453            !(metta (eq (plus Z $n) $n) %Undefined% &self)
454            !(metta (eq (plus (S Z) $n) $n) %Undefined% &self)
455        ";
456
457        assert_eq_metta_results!(run_program(program),
458            Ok(vec![vec![expr!({Bool(true)})], vec![expr!("eq" ("S" n) n)]]));
459    }
460
461    #[test]
462    fn test_variable_defined_via_variable() {
463        let program = "
464            (= (myif T $y) $y)
465            (= (mynot F) T)
466            (= (a $z) (mynot (b $z)))
467            (= (b d) F)
468
469            !(metta (myif (a $x) $x) %Undefined% &self)
470        ";
471
472        assert_eq_metta_results!(run_program(program),
473            Ok(vec![vec![expr!("d")]]));
474    }
475
476    #[test]
477    fn test_variable_name_conflict() {
478        let program = "
479            (= (a ($W)) True)
480
481            !(metta (a $W) %Undefined% &self)
482        ";
483
484        assert_eq_metta_results!(run_program(program),
485            Ok(vec![vec![expr!({Bool(true)})]]));
486    }
487
488    #[test]
489    fn test_variable_name_conflict_renaming() {
490        let program = "
491            (= (b ($x $y)) (c $x $y))
492
493            !(metta (a (b $a) $x $y) %Undefined% &self)
494        ";
495
496        let result = run_program(program);
497        assert!(result.is_ok_and(|res| res.len() == 1 && res[0].len() == 1 &&
498            atoms_are_equivalent(&res[0][0], &expr!("a" ("c" a b) c d))));
499    }
500
501    #[test]
502    fn test_operation_is_expression() {
503        let program = "
504            (: foo (-> (-> A A)))
505            (: a A)
506            (= (foo) bar)
507            (= (bar $x) $x)
508
509            !(metta ((foo) a) %Undefined% &self)
510        ";
511
512        assert_eq_metta_results!(run_program(program), Ok(vec![vec![expr!("a")]]));
513    }
514
515    fn id_num(args: &[Atom]) -> Result<Vec<Atom>, ExecError> {
516        let arg_error = || ExecError::from("id_num expects one argument: number");
517        let num = args.get(0).ok_or_else(arg_error)?;
518        Ok(vec![num.clone()])
519    }
520
521    #[test]
522    fn test_return_bad_type_error() {
523        let program1 = "
524            (: myAtom myType)
525            (: id_a (-> A A))
526            (= (id_a $a) $a)
527
528            !(assertEqual
529                (metta (id_a myAtom) %Undefined% &self)
530                (Error (id_a myAtom) (BadArgType 1 A myType)))
531        ";
532
533        let metta = Metta::new(Some(EnvBuilder::test_env()));
534        metta.tokenizer().borrow_mut().register_function(
535            GroundedFunctionAtom::new("id_num".into(), expr!("->" "Number" "Number"), id_num));
536
537        assert_eq!(metta.run(SExprParser::new(program1)),
538            Ok(vec![vec![UNIT_ATOM]]));
539
540        let program2 = "
541            !(assertEqual
542                (metta (id_num myAtom) %Undefined% &self)
543                (Error (id_num myAtom) (BadArgType 1 Number myType)))
544        ";
545
546        assert_eq!(metta.run(SExprParser::new(program2)),
547            Ok(vec![vec![UNIT_ATOM]]));
548    }
549
550    #[test]
551    fn test_check_if_function_type_is_applicable_returns_bad_type() {
552        let program = "!(assertEqual (metta (+ 1 2) (-> Atom Atom $t) &self) (Error (+ 1 2) (BadType (-> Atom Atom $t) Number)))";
553        let metta = Metta::new(Some(EnvBuilder::test_env()));
554        assert_eq!(metta.run(SExprParser::new(program)),
555                   Ok(vec![vec![UNIT_ATOM]]));
556    }
557
558    #[test]
559    fn test_return_incorrect_number_of_args_error() {
560        let program1 = "
561            (: a A)
562            (: b B)
563            (: c C)
564            (: foo (-> A B C))
565            (= (foo $a $b) c)
566
567            !(metta (foo a b) %Undefined% &self)
568        ";
569
570        let metta = Metta::new(Some(EnvBuilder::test_env()));
571        metta.tokenizer().borrow_mut().register_function(
572            GroundedFunctionAtom::new("id_num".into(), expr!("->" "Number" "Number"), id_num));
573
574        assert_eq!(metta.run(SExprParser::new(program1)),
575            Ok(vec![vec![expr!("c")]]));
576
577        let program2 = "!(metta (foo a) %Undefined% &self)";
578
579        assert_eq!(metta.run(SExprParser::new(program2)),
580            Ok(vec![vec![expr!("Error" ("foo" "a") "IncorrectNumberOfArguments")]]));
581
582        let program3 = "!(metta (foo a b c) %Undefined% &self)";
583
584        assert_eq!(metta.run(SExprParser::new(program3)),
585            Ok(vec![vec![expr!("Error" ("foo" "a" "b" "c") "IncorrectNumberOfArguments")]]));
586    }
587
588    #[derive(Clone, PartialEq, Debug)]
589    pub struct SomeGndAtom { }
590
591    impl Display for SomeGndAtom {
592        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
593            write!(f, "some-gnd-atom")
594        }
595    }
596
597    impl Grounded for SomeGndAtom {
598        fn type_(&self) -> Atom {
599            Atom::expr([ARROW_SYMBOL, sym!("Arg1Type"), sym!("Arg2Type"), sym!("RetType")])
600        }
601    }
602
603    #[test]
604    fn test_get_doc_func() {
605        let metta = Metta::new(Some(EnvBuilder::test_env()));
606        let parser = SExprParser::new(r#"
607            (: Arg1Type Type)
608            (: Arg2Type Type)
609            (: RetType Type)
610            (: some-func (-> Arg1Type Arg2Type RetType))
611            (@doc some-func
612              (@desc "Test function")
613              (@params (
614                (@param "First argument")
615                (@param "Second argument")
616              ))
617              (@return "Return value")
618            )
619            
620            !(get-doc &self some-func)
621        "#);
622
623        assert_eq_metta_results!(metta.run(parser), Ok(vec![
624            vec![expr!("@doc-formal"
625                ("@item" "some-func")
626                ("@kind" "function")
627                ("@type" ("->" "Arg1Type" "Arg2Type" "RetType"))
628                ("@desc" {Str::from_str("Test function")})
629                ("@params" (
630                    ("@param" ("@type" "Arg1Type") ("@desc" {Str::from_str("First argument")}))
631                    ("@param" ("@type" "Arg2Type") ("@desc" {Str::from_str("Second argument")})) ))
632                ("@return" ("@type" "RetType") ("@desc" {Str::from_str("Return value")})) )],
633        ]));
634    }
635
636    #[test]
637    fn test_get_doc_atom() {
638        let metta = Metta::new(Some(EnvBuilder::test_env()));
639        let parser = SExprParser::new(r#"
640            (: SomeAtom SomeType)
641            (@doc SomeAtom (@desc "Test symbol atom having specific type"))
642
643            !(get-doc &self SomeAtom)
644        "#);
645
646        assert_eq_metta_results!(metta.run(parser), Ok(vec![
647            vec![expr!("@doc-formal"
648                ("@item" "SomeAtom")
649                ("@kind" "atom")
650                ("@type" "SomeType")
651                ("@desc" {Str::from_str("Test symbol atom having specific type")}) )],
652        ]));
653    }
654
655    #[test]
656    fn test_get_doc_gnd_func() {
657        let metta = Metta::new(Some(EnvBuilder::test_env()));
658        metta.tokenizer().borrow_mut()
659            .register_token(regex::Regex::new(r"some-gnd-atom").unwrap(), |_| Atom::gnd(SomeGndAtom{}));
660        let parser = SExprParser::new(r#"
661            (@doc some-gnd-atom
662              (@desc "Test function")
663              (@params (
664                (@param "First argument")
665                (@param "Second argument")
666              ))
667              (@return "Return value")
668            )
669            !(get-doc &self some-gnd-atom)
670        "#);
671
672        assert_eq_metta_results!(metta.run(parser), Ok(vec![
673            vec![expr!("@doc-formal"
674                ("@item" {SomeGndAtom{}})
675                ("@kind" "function")
676                ("@type" ("->" "Arg1Type" "Arg2Type" "RetType"))
677                ("@desc" {Str::from_str("Test function")})
678                ("@params" (
679                    ("@param" ("@type" "Arg1Type") ("@desc" {Str::from_str("First argument")}))
680                    ("@param" ("@type" "Arg2Type") ("@desc" {Str::from_str("Second argument")})) ))
681                ("@return" ("@type" "RetType") ("@desc" {Str::from_str("Return value")})) )],
682        ]));
683    }
684
685    #[test]
686    fn test_get_doc_no_doc() {
687        let metta = Metta::new(Some(EnvBuilder::test_env()));
688        let parser = SExprParser::new(r#"
689            !(get-doc &self NoSuchAtom)
690        "#);
691
692        assert_eq_metta_results!(metta.run(parser), Ok(vec![
693            vec![expr!("@doc-formal"
694                ("@item" "NoSuchAtom")
695                ("@kind" "atom")
696                ("@type" "%Undefined%")
697                ("@desc" {Str::from_str("No documentation")}) )],
698        ]));
699    }
700
701    #[test]
702    fn test_get_doc_function_call() {
703        let metta = Metta::new(Some(EnvBuilder::test_env()));
704        let parser = SExprParser::new(r#"
705            (: Arg1Type Type)
706            (: Arg2Type Type)
707            (: RetType Type)
708            (: some-func (-> Arg1Type Arg2Type RetType))
709            (@doc some-func
710              (@desc "Test function")
711              (@params (
712                (@param "First argument")
713                (@param "Second argument")
714              ))
715              (@return "Return value")
716            )
717
718            !(get-doc &self (some-func arg1 arg2))
719        "#);
720
721        assert_eq_metta_results!(metta.run(parser), Ok(vec![
722            vec![expr!("@doc-formal"
723                ("@item" ("some-func" "arg1" "arg2"))
724                ("@kind" "atom")
725                ("@type" "RetType")
726                ("@desc" {Str::from_str("No documentation")}) )],
727        ]));
728    }
729
730    #[test]
731    fn test_get_doc_no_type() {
732        let metta = Metta::new(Some(EnvBuilder::test_env()));
733        let parser = SExprParser::new(r#"
734            (@doc some-func-no-type
735              (@desc "Test function")
736              (@params (
737                (@param "First argument")
738                (@param "Second argument")
739              ))
740              (@return "Return value")
741            )
742
743            !(get-doc &self some-func-no-type)
744        "#);
745
746        assert_eq_metta_results!(metta.run(parser), Ok(vec![
747            vec![expr!("@doc-formal"
748                ("@item" "some-func-no-type")
749                ("@kind" "function")
750                ("@type" "%Undefined%")
751                ("@desc" {Str::from_str("Test function")})
752                ("@params" (
753                    ("@param" ("@type" "%Undefined%") ("@desc" {Str::from_str("First argument")}))
754                    ("@param" ("@type" "%Undefined%") ("@desc" {Str::from_str("Second argument")})) ))
755                ("@return" ("@type" "%Undefined%") ("@desc" {Str::from_str("Return value")})) )],
756        ]));
757    }
758
759    #[test]
760    fn test_string_parsing() {
761        let metta = Metta::new(Some(EnvBuilder::test_env()));
762        let parser = SExprParser::new(r#"
763            !(id "test")
764            !(id "te st")
765            !(id "te\"st")
766            !(id "")
767            !(id "te\nst")
768            !("te\nst"test)
769        "#);
770
771        assert_eq_metta_results!(metta.run(parser), Ok(vec![
772            vec![expr!({Str::from_str("test")})],
773            vec![expr!({Str::from_str("te st")})],
774            vec![expr!({Str::from_str("te\"st")})],
775            vec![expr!({Str::from_str("")})],
776            vec![expr!({Str::from_str("te\nst")})],
777            vec![expr!({Str::from_str("te\nst")} "test")],
778        ]));
779    }
780
781    #[test]
782    fn let_op_keep_variables_equalities_issue290() {
783        assert_eq_metta_results!(run_program("!(let* (($f f) ($f $x)) $x)"), Ok(vec![vec![expr!("f")]]));
784        assert_eq_metta_results!(run_program("!(let* (($f $x) ($f f)) $x)"), Ok(vec![vec![expr!("f")]]));
785        assert_eq_metta_results!(run_program("!(let (quote ($x $x)) (quote ($z $y)) (let $y A ($z $y)))"), Ok(vec![vec![expr!("A" "A")]]));
786        assert_eq_metta_results!(run_program("!(let (quote ($x $x)) (quote ($z $y)) (let $z A ($z $y)))"), Ok(vec![vec![expr!("A" "A")]]));
787    }
788
789    #[test]
790    fn test_stdlib_uses_rust_grounded_tokens() {
791        assert_eq!(run_program("!(if True ok nok)"), Ok(vec![vec![Atom::sym("ok")]]));
792    }
793
794    #[test]
795    fn test_let_op_inside_other_operation() {
796        assert_eq!(run_program("!(and True (let $x False $x))"), Ok(vec![vec![expr!({Bool(false)})]]));
797    }
798
799    #[test]
800    fn test_quote() {
801        let metta = Metta::new(Some(EnvBuilder::test_env()));
802        let parser = SExprParser::new("
803            (= (foo) a)
804            (= (foo) b)
805            !(foo)
806            !(quote (foo))
807        ");
808
809        assert_eq_metta_results!(metta.run(parser),
810            Ok(vec![
811                vec![expr!("a"), expr!("b")],
812                vec![expr!("quote" ("foo"))],
813            ]));
814    }
815
816    #[test]
817    fn test_unify() {
818        let metta = Metta::new(Some(EnvBuilder::test_env()));
819        let parser = SExprParser::new("
820            !(unify (a $b 1 (d)) (a $a 1 (d)) ok nok)
821            !(unify (a $b c) (a b $c) (ok $b $c) nok)
822            !(unify $a (a b c) (ok $a) nok)
823            !(unify (a b c) $a (ok $a) nok)
824            !(unify (a b c) (a b d) ok nok)
825            !(unify ($x a) (b $x) ok nok)
826        ");
827
828        assert_eq_metta_results!(metta.run(parser),
829            Ok(vec![
830                vec![expr!("ok")],
831                vec![expr!("ok" "b" "c")],
832                vec![expr!("ok" ("a" "b" "c"))],
833                vec![expr!("ok" ("a" "b" "c"))],
834                vec![expr!("nok")],
835                vec![expr!("nok")]
836            ]));
837    }
838
839    #[test]
840    fn test_empty() {
841        let metta = Metta::new(Some(EnvBuilder::test_env()));
842        let parser = SExprParser::new("
843            !(empty)
844        ");
845
846        assert_eq_metta_results!(metta.run(parser),
847            Ok(vec![vec![]]));
848    }
849}