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
64fn 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 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#[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}