import pytest from core.builtin_concepts import BuiltinConcepts from core.concept import Concept, PROPERTIES_TO_SERIALIZE, simplec from evaluators.MutipleSameSuccessEvaluator import MultipleSameSuccessEvaluator from parsers.BaseNodeParser import SyaAssociativity from parsers.BnfNodeParser import Sequence, StrMatch, OrderedChoice, Optional, ConceptExpression from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka class TestSheerkaNonRegMemory(TestUsingMemoryBasedSheerka): def init_scenario(self, init_expressions): sheerka = self.get_sheerka() for expression in init_expressions: res = sheerka.evaluate_user_input(expression) assert len(res) == 1, f"Failed to execute '{expression}'" assert res[0].status, f"Error while executing '{expression}'" return sheerka @pytest.mark.parametrize("text, expected", [ ("1 + 1", 2), ("sheerka.test()", 'I have access to Sheerka !') ]) def test_i_can_evaluate_python_expressions_with_no_variable(self, text, expected): sheerka = self.get_sheerka() res = sheerka.evaluate_user_input(text) assert len(res) == 1 assert res[0].status assert res[0].value == expected def test_i_can_recognize_concept_with_python_body(self): sheerka = self.get_sheerka() concept = Concept(name="one", body="1") sheerka.add_in_cache(concept) text = "one" res = sheerka.evaluate_user_input(text) assert len(res) == 1 assert res[0].status assert res[0].value == concept # sanity check evaluated = sheerka.evaluate_concept(self.get_context(eval_body=True), res[0].value) assert evaluated == simplec("one", 1) def test_i_can_recognize_concept_with_concept_body(self): sheerka = self.get_sheerka() concept_one = Concept(name="one") concept_un = Concept(name="un", body="one") sheerka.add_in_cache(concept_one) sheerka.add_in_cache(concept_un) res = sheerka.evaluate_user_input("un") return_value = res[0].value assert len(res) == 1 assert res[0].status assert return_value == concept_un # sanity check evaluated = sheerka.evaluate_concept(self.get_context(eval_body=True), return_value) assert evaluated == simplec("un", simplec("one", None)) def test_i_can_recognize_concept_with_no_body(self): sheerka = self.get_sheerka() concept = Concept(name="one") sheerka.add_in_cache(concept) text = "one" res = sheerka.evaluate_user_input(text) assert len(res) == 1 assert res[0].status assert res[0].value == concept assert id(res[0].value) != id(concept) def test_is_unique_property_is_used_when_evaluating(self): sheerka = self.get_sheerka() concept = Concept(name="one", is_unique=True) sheerka.add_in_cache(concept) text = "one" res = sheerka.evaluate_user_input(text) assert len(res) == 1 assert res[0].status assert res[0].value == concept assert id(res[0].value) == id(concept) def test_i_can_evaluate_def_concept_request(self): text = """ def concept a + b where isinstance(a, int) and isinstance(b, int) pre isinstance(a, int) and isinstance(b, int) post isinstance(res, int) as: def func(x,y): return x+y func(a,b) """ expected = self.get_default_concept() expected.metadata.id = "1001" expected.metadata.desc = None expected.metadata.variables = [("a", None), ("b", None)] expected.init_key() sheerka = self.get_sheerka(cache_only=False) res = sheerka.evaluate_user_input(text) assert len(res) == 1 assert res[0].status assert sheerka.isinstance(res[0].value, BuiltinConcepts.NEW_CONCEPT) concept_saved = res[0].value.body for prop in PROPERTIES_TO_SERIALIZE: assert getattr(concept_saved.metadata, prop) == getattr(expected.metadata, prop) # cache is up to date assert sheerka.has_key(concept_saved.key) assert sheerka.has_id(concept_saved.id) assert sheerka.has_name(concept_saved.name) assert sheerka.has_hash(concept_saved.get_definition_hash()) assert sheerka.cache_manager.copy(sheerka.CONCEPTS_BY_FIRST_KEYWORD_ENTRY) == {'+': ['1001']} # sdp is up to date assert sheerka.sdp.exists(sheerka.CONCEPTS_BY_KEY_ENTRY, expected.key) def test_i_can_evaluate_def_concept_part_when_one_part_is_a_ref_of_another_concept(self): """ In this test, we test that the properties of 'concept a xx b' (which are 'a' and 'b') are correctly detected, thanks to the source code 'a plus b' in its body :return: """ sheerka = self.get_sheerka() # concept 'a plus b' is known concept_a_plus_b = Concept(name="a plus b").def_var("a").def_var("b").init_key() sheerka.add_in_cache(concept_a_plus_b) res = sheerka.evaluate_user_input("def concept a xx b as a plus b") expected = Concept(name="a xx b", body="a plus b").def_var("a").def_var("b").init_key() expected.metadata.id = "1001" assert len(res) == 1 assert res[0].status assert sheerka.isinstance(res[0].value, BuiltinConcepts.NEW_CONCEPT) concept_saved = res[0].value.body for prop in PROPERTIES_TO_SERIALIZE: assert getattr(concept_saved.metadata, prop) == getattr(expected.metadata, prop) assert sheerka.has_key(concept_saved.key) def test_i_cannot_evaluate_the_same_def_concept_twice(self): text = """ def concept a + b where isinstance(a, int) and isinstance(b, int) pre isinstance(a, int) and isinstance(b, int) post isinstance(res, int) as: def func(x,y): return x+y func(a,b) """ sheerka = self.get_sheerka() sheerka.evaluate_user_input(text) res = sheerka.evaluate_user_input(text) assert len(res) == 1 assert not res[0].status assert sheerka.isinstance(res[0].value, BuiltinConcepts.CONCEPT_ALREADY_DEFINED) @pytest.mark.parametrize("text", [ "", " ", "\n", ]) def test_i_can_recognize_a_empty_input(self, text): sheerka = self.get_sheerka() res = sheerka.evaluate_user_input(text) assert len(res) == 1 assert res[0].status assert sheerka.isinstance(res[0].value, BuiltinConcepts.NOP) def test_i_can_recognize_concept_with_variable(self): sheerka, context, concept_foo, concept_hello = self.init_concepts( "foo", Concept(name="hello a").def_var("a"), create_new=True) res = sheerka.evaluate_user_input("hello foo") return_value = res[0].value assert len(res) == 1 assert res[0].status assert sheerka.isinstance(return_value, concept_hello) # sanity check evaluated = sheerka.evaluate_concept(self.get_context(eval_body=True), return_value) assert evaluated.get_value("a") == concept_foo def test_i_can_recognize_concept_with_variable_and_python_as_body(self): sheerka = self.get_sheerka() hello_a = sheerka.add_in_cache(Concept(name="hello a", body="'hello ' + a").def_var("a")) sheerka.add_in_cache(Concept(name="foo", body="'foo'")) res = sheerka.evaluate_user_input("hello foo") assert len(res) == 1 assert res[0].status assert sheerka.isinstance(res[0].value, hello_a) # sanity check evaluated = sheerka.evaluate_concept(self.get_context(eval_body=True), res[0].value) assert evaluated.body == "hello foo" assert evaluated.metadata.is_evaluated assert evaluated.get_value("a") == simplec("foo", "foo") assert evaluated.get_value("a").metadata.is_evaluated def test_i_can_recognize_duplicate_concepts_with_same_value(self): sheerka = self.get_sheerka() self.create_concept_lite(sheerka, Concept(name="hello a", body="'hello ' + a"), variables=["a"]) self.create_concept_lite(sheerka, Concept(name="hello foo", body="'hello foo'")) self.create_concept_lite(sheerka, Concept(name="foo", body="'foo'")) res = sheerka.evaluate_user_input("hello foo") assert len(res) == 1 assert res[0].status assert res[0].value.body == "hello foo" assert res[0].who == sheerka.get_evaluator_name(MultipleSameSuccessEvaluator.NAME) def test_i_cannot_manage_duplicate_concepts_when_the_values_are_different(self): sheerka = self.get_sheerka() self.create_concept_lite(sheerka, Concept(name="hello a", body="'hello ' + a"), variables=["a"]) self.create_concept_lite(sheerka, Concept(name="hello foo", body="'hello foo'")) self.create_concept_lite(sheerka, Concept(name="foo", body="'another value'")) res = sheerka.evaluate_user_input("hello foo") assert len(res) == 1 assert not res[0].status assert sheerka.isinstance(res[0].value, BuiltinConcepts.TOO_MANY_SUCCESS) concepts = res[0].value.body assert len(concepts) == 2 sorted_values = sorted(concepts, key=lambda x: x.value.body) assert sorted_values[0].value.body == "hello another value" assert sorted_values[1].value.body == "hello foo" def test_i_can_manage_concepts_with_the_same_key_when_values_are_the_same(self): sheerka = self.get_sheerka() context = self.get_context(sheerka) sheerka.create_new_concept(context, Concept(name="hello a", body="'hello ' + a").def_var("a")) sheerka.create_new_concept(context, Concept(name="hello b", body="'hello ' + b").def_var("b")) res = sheerka.evaluate_user_input("hello 'foo'") assert len(res) == 1 assert res[0].status assert res[0].value.body == "hello foo" # I don't know yet the one to choose assert res[0].who == sheerka.get_evaluator_name(MultipleSameSuccessEvaluator.NAME) def test_i_can_create_concepts_with_python_code_as_body(self): sheerka = self.get_sheerka() context = self.get_context(sheerka) sheerka.create_new_concept(context, Concept(name="concepts", body="sheerka.test()")) res = sheerka.evaluate_user_input("eval concepts") assert len(res) == 1 assert res[0].status assert res[0].value == sheerka.test() def test_i_can_recognize_bnf_definitions(self): sheerka = self.get_sheerka() concept_a = sheerka.evaluate_user_input("def concept a from bnf 'one' | 'two'")[0].body.body res = sheerka.evaluate_user_input("one") assert len(res) == 1 assert res[0].status assert sheerka.isinstance(res[0].value, concept_a) def test_i_can_recognize_bnf_definitions_with_variables(self): sheerka = self.get_sheerka() concept_a = sheerka.evaluate_user_input("def concept a from bnf 'one' | 'two'")[0].body.body concept_b = sheerka.evaluate_user_input("def concept b from bnf a 'three'")[0].body.body res = sheerka.evaluate_user_input("one three") assert len(res) == 1 assert res[0].status return_value = res[0].value assert sheerka.isinstance(return_value, concept_b) # sanity check evaluated = sheerka.evaluate_concept(self.get_context(sheerka=sheerka, eval_body=True), return_value) assert evaluated.body == "one three" assert evaluated.metadata.is_evaluated assert evaluated.get_value("a") == sheerka.new(concept_a.key, body="one").init_key() assert evaluated.get_value("a").metadata.is_evaluated @pytest.mark.parametrize("user_input", [ "def concept greetings from def hello a where a", "def concept greetings from hello a where a"]) def test_i_can_recognize_a_concept_defined_using_from_def(self, user_input): sheerka = self.get_sheerka() greetings = sheerka.evaluate_user_input(user_input)[0].body.body res = sheerka.evaluate_user_input("hello 'foo'") assert len(res) == 1 assert res[0].status concept_found = res[0].value assert sheerka.isinstance(concept_found, greetings) assert concept_found.get_value("a") == "foo" assert concept_found.metadata.need_validation res = sheerka.evaluate_user_input("greetings") assert len(res) == 1 assert res[0].status concept_found = res[0].value assert sheerka.isinstance(concept_found, greetings) assert concept_found.get_value("a") is None assert not concept_found.metadata.need_validation @pytest.mark.parametrize("desc, definitions", [ ("Simple form", [ "def concept one as 1", "def concept two as 2", "def concept twenties from bnf 'twenty' (one|two)=unit as 20 + unit" ]), ("When twenty is a concept", [ "def concept one as 1", "def concept two as 2", "def concept twenty as 20", "def concept twenties from bnf twenty (one|two)=unit as twenty + unit" ]), ("When digit is a concept", [ "def concept one as 1", "def concept two as 2", "def concept twenty as 20", "def concept digit from bnf one|two", "def concept twenties from bnf twenty digit as twenty + digit" ]), ("When using isa and concept twenty", [ "def concept one as 1", "def concept two as 2", "def concept number", "one isa number", "two isa number", "def concept twenties from bnf 'twenty' number as 20 + number" ]), ("When using isa and concept twenty", [ "def concept one as 1", "def concept two as 2", "def concept twenty as 20", "def concept number", "one isa number", "two isa number", "def concept twenties from bnf twenty number as 20 + number" ]), ]) def test_i_can_mix_concept_with_python_to_define_numbers(self, desc, definitions): sheerka = self.get_sheerka() for definition in definitions: sheerka.evaluate_user_input(definition) res = sheerka.evaluate_user_input("twenty one") assert len(res) == 1 assert res[0].status assert sheerka.isinstance(res[0].body, "twenties") assert sheerka.evaluate_concept(self.get_context(sheerka=sheerka, eval_body=True), res[0].body).body == 21 res = sheerka.evaluate_user_input("twenty one + 1") assert len(res) == 1 assert res[0].status assert res[0].body == 22 res = sheerka.evaluate_user_input("twenty one + one") assert len(res) == 1 assert res[0].status assert res[0].body == 22 res = sheerka.evaluate_user_input("twenty one + twenty two") assert len(res) == 1 assert res[0].status assert res[0].body == 43 res = sheerka.evaluate_user_input("1 + twenty one") assert len(res) == 1 assert res[0].status assert res[0].body == 22 res = sheerka.evaluate_user_input("1 + 1 + twenty one") assert len(res) == 1 assert res[0].status assert res[0].body == 23 def test_i_can_mix_bnf_and_isa(self): """ if 'one' isa 'number, twenty number should be recognized :return: """ sheerka = self.get_sheerka() sheerka.evaluate_user_input("def concept one as 1") sheerka.evaluate_user_input("def concept two as 2") sheerka.evaluate_user_input("def concept number") sheerka.evaluate_user_input("one isa number") sheerka.evaluate_user_input("two isa number") sheerka.evaluate_user_input("def concept twenties from bnf 'twenty' number as 20 + number") res = sheerka.evaluate_user_input("twenty one") assert len(res) == 1 assert res[0].status assert sheerka.isinstance(res[0].body, "twenties") assert sheerka.evaluate_concept(self.get_context(sheerka=sheerka, eval_body=True), res[0].value).body == 21 res = sheerka.evaluate_user_input("twenty one + 1") assert len(res) == 1 assert res[0].status assert res[0].body == 22 res = sheerka.evaluate_user_input("twenty one + one") assert len(res) == 1 assert res[0].status assert res[0].body == 22 res = sheerka.evaluate_user_input("twenty one + twenty two") assert len(res) == 1 assert res[0].status assert res[0].body == 43 res = sheerka.evaluate_user_input("1 + twenty one") assert len(res) == 1 assert res[0].status assert res[0].body == 22 res = sheerka.evaluate_user_input("1 + 1 + twenty one") assert len(res) == 1 assert res[0].status assert res[0].body == 23 def test_i_can_mix_bnf_and_isa_2(self): sheerka = self.get_sheerka() init = [ "def concept one as 1", "def concept twenty as 20", "def concept number", "one isa number", "twenty isa number", "def concept twenties from bnf twenty number as twenty + number" ] for exp in init: sheerka.evaluate_user_input(exp) res = sheerka.evaluate_user_input("eval twenty one") assert len(res) == 1 assert res[0].status assert res[0].body == 21 def test_i_can_use_concepts_defined_with_from(self): sheerka = self.get_sheerka() init = [ "def concept plus from a plus b as a + b", "def concept one as 1", ] for exp in init: sheerka.evaluate_user_input(exp) res = sheerka.evaluate_user_input("eval one plus one") assert len(res) == 1 assert res[0].status assert res[0].body == 2 res = sheerka.evaluate_user_input("eval 1 plus one") assert len(res) == 1 assert res[0].status assert res[0].body == 2 res = sheerka.evaluate_user_input("eval one plus 1") assert len(res) == 1 assert res[0].status assert res[0].body == 2 res = sheerka.evaluate_user_input("eval 1 plus 2") assert len(res) == 1 assert res[0].status assert res[0].body == 3 res = sheerka.evaluate_user_input("eval 1 plus 1") assert len(res) == 1 assert res[0].status assert res[0].body == 2 def test_i_can_mix_bnf_concept_and_concept(self): definitions = [ "def concept one as 1", "def concept two as 2", "def concept twenties from bnf 'twenty' (one|two)=unit as 20 + unit", "def concept a plus b as a + b" ] sheerka = self.init_scenario(definitions) res = sheerka.evaluate_user_input("eval 1 plus 2") assert len(res) == 1 assert res[0].status assert res[0].body == 3 res = sheerka.evaluate_user_input("eval 1 plus one") assert len(res) == 1 assert res[0].status assert res[0].body == 2 res = sheerka.evaluate_user_input("eval 1 + 1 plus 1") assert len(res) == 1 assert res[0].status assert res[0].body == 3 res = sheerka.evaluate_user_input("eval 1 plus twenty one") assert len(res) == 1 assert res[0].status assert res[0].body == 22 res = sheerka.evaluate_user_input("eval one plus 1") assert len(res) == 1 assert res[0].status assert res[0].body == 2 res = sheerka.evaluate_user_input("eval one plus two") assert len(res) == 1 assert res[0].status assert res[0].body == 3 res = sheerka.evaluate_user_input("eval one plus twenty one") assert len(res) == 1 assert res[0].status assert res[0].body == 22 res = sheerka.evaluate_user_input("eval twenty one plus 1") assert len(res) == 1 assert res[0].status assert res[0].body == 22 res = sheerka.evaluate_user_input("eval twenty one plus one") assert len(res) == 1 assert res[0].status assert res[0].body == 22 res = sheerka.evaluate_user_input("eval twenty one plus twenty two") assert len(res) == 1 assert res[0].status assert res[0].body == 43 def test_i_can_use_bnf_alias(self): definitions = [ "def concept two as 2", "def concept number", "two isa number", "def concept plus_one from bnf number=n1 'plus_one' as n1 + 1", ] sheerka = self.init_scenario(definitions) res = sheerka.evaluate_user_input("eval two plus_one") assert len(res) == 1 assert res[0].status assert res[0].body == 3 def test_i_can_say_that_a_concept_isa_another_concept(self): sheerka = self.get_sheerka() sheerka.evaluate_user_input("def concept foo") sheerka.evaluate_user_input("def concept bar") res = sheerka.evaluate_user_input("foo isa bar") assert len(res) == 1 assert res[0].status assert sheerka.isinstance(res[0].body, BuiltinConcepts.SUCCESS) def test_eval_does_not_break_valid_result(self): sheerka = self.get_sheerka() sheerka.evaluate_user_input("def concept one as 1") sheerka.evaluate_user_input("def concept two as 2") res = sheerka.evaluate_user_input("one + two") assert len(res) == 1 assert res[0].status assert res[0].body == 3 res = sheerka.evaluate_user_input("eval one + two") assert len(res) == 1 assert res[0].status assert res[0].body == 3 @pytest.mark.parametrize("text", [ "'hello", '"foo" + "string', "c::", "c:foo\nbar:", "c:foo", "def concept 'name", "def concept name from bnf 'name" ]) def test_i_can_manage_tokenizer_error(self, text): sheerka = self.get_sheerka() sheerka.add_in_cache(Concept("foo")) res = sheerka.evaluate_user_input(text) assert len(res) > 1 for r in [r for r in res if r.who.startswith("parsers.")]: assert not r.status def test_i_can_recognize_concept_from_string(self): sheerka = self.get_sheerka() sheerka.add_in_cache(Concept("one", body="1")) res = sheerka.evaluate_user_input("'one'") assert len(res) == 1 assert res[0].status assert res[0].body == "one" res = sheerka.evaluate_user_input("eval 'one'") assert len(res) == 1 assert res[0].status assert res[0].body == "one" @pytest.mark.parametrize("expression", [ "def concept twenties from bnf 'twenty' (one | two)=unit as 20 + unit", "def concept twenties from bnf 'twenty' (one | two)=unit as twenty + unit", "def concept twenties from bnf twenty (one | two)=unit as 20 + unit", "def concept twenties from bnf twenty (one | two)=unit as twenty + unit", ]) def test_i_can_evaluate_bnf_concepts(self, expression): sheerka = self.get_sheerka() sheerka.evaluate_user_input("def concept one as 1") sheerka.evaluate_user_input("def concept two as 2") sheerka.evaluate_user_input("def concept twenty as 20") sheerka.evaluate_user_input(expression) res = sheerka.evaluate_user_input("eval twenty one") assert len(res) == 1 assert res[0].status assert res[0].body == 21 def test_i_can_use_where_in_bnf(self): sheerka = self.get_sheerka() init = [ "def concept one as 1", "def concept two as 2", "def concept three as 3", "def concept twenty as 20", "def concept number", "one isa number", "two isa number", "three isa number", "def concept twenties from bnf twenty number where number <= 2 as twenty + number" ] for exp in init: sheerka.evaluate_user_input(exp) res = sheerka.evaluate_user_input("twenty one") assert len(res) == 1 assert res[0].status assert sheerka.isinstance(res[0].body, "twenties") res = sheerka.evaluate_user_input("eval twenty one") assert len(res) == 1 assert res[0].status assert res[0].body == 21 res = sheerka.evaluate_user_input("twenty two") assert len(res) == 1 assert res[0].status assert sheerka.isinstance(res[0].body, "twenties") res = sheerka.evaluate_user_input("eval twenty two") assert len(res) == 1 assert res[0].status assert res[0].body == 22 res = sheerka.evaluate_user_input("twenty three") assert len(res) == 1 assert not res[0].status assert sheerka.isinstance(res[0].body, BuiltinConcepts.MULTIPLE_ERRORS) assert str(BuiltinConcepts.WHERE_CLAUSE_FAILED) in [error.key for error in sheerka.get_error(res[0].body.body)] res = sheerka.evaluate_user_input("eval twenty three") assert len(res) == 1 assert not res[0].status assert str(BuiltinConcepts.WHERE_CLAUSE_FAILED) in [error.key for error in sheerka.get_error(res[0].body.body)] def test_i_can_manage_some_type_of_infinite_recursion(self): sheerka = self.get_sheerka() sheerka.evaluate_user_input("def concept one as 1") sheerka.evaluate_user_input("def concept 1 as one") res = sheerka.evaluate_user_input("one + 1") assert len(res) == 1 assert res[0].status assert res[0].body == 2 res = sheerka.evaluate_user_input("1 + 1") assert len(res) == 1 assert res[0].status assert res[0].body == 2 def test_i_can_evaluate_bnf_concept_with_where_clause(self): sheerka = self.get_sheerka() sheerka.evaluate_user_input("def concept a from bnf 'bar' | 'baz'") sheerka.evaluate_user_input("def concept b as 'hello world'") sheerka.evaluate_user_input("def concept foobar from bnf 'foo' a where a=='bar' as b") res = sheerka.evaluate_user_input("foo bar") assert len(res) == 1 assert res[0].status assert sheerka.isinstance(res[0].body, "foobar") assert res[0].body.body is None res = sheerka.evaluate_user_input("eval foo bar") assert len(res) == 1 assert res[0].status assert res[0].body == "hello world" res = sheerka.evaluate_user_input("foo baz") assert len(res) == 1 assert not res[0].status assert sheerka.isinstance(res[0].body, BuiltinConcepts.WHERE_CLAUSE_FAILED) res = sheerka.evaluate_user_input("eval foo baz") assert len(res) == 1 assert not res[0].status assert sheerka.isinstance(res[0].body, BuiltinConcepts.WHERE_CLAUSE_FAILED) res = sheerka.evaluate_user_input("foobar") assert len(res) == 1 assert res[0].status res = sheerka.evaluate_user_input("eval foobar") assert len(res) == 1 # error assert not res[0].status assert sheerka.isinstance(res[0].body, BuiltinConcepts.WHERE_CLAUSE_FAILED) @pytest.mark.skip("Not ready for that") def test_i_can_manage_missing_variables_from_bnf_parsing(self): definitions = [ "def concept one as 1", "def concept number", "one isa number", "def concept hundreds from bnf number=n1 'hundred' ('and' number=n2)? where n1<10 and n2<100 as n1 * 100 + n2", ] sheerka = self.init_scenario(definitions) res = sheerka.evaluate_user_input("one hundred") assert len(res) == 1 assert res[0].status assert sheerka.isinstance(res[0].body, "hundreds") res = sheerka.evaluate_user_input("eval one hundred") assert len(res) == 1 assert res[0].status assert res[0].body == "100" def test_i_can_say_than_bnf_concept_isa_another_concept(self): sheerka = self.get_sheerka() sheerka.evaluate_user_input("def concept number") sheerka.evaluate_user_input("def concept one as 1") sheerka.evaluate_user_input("def concept two as 2") sheerka.evaluate_user_input("def concept twenties from bnf 'twenty' (one|two)=unit as 20 + unit") res = sheerka.evaluate_user_input("twenties isa number") assert len(res) == 1 assert res[0].status twenties = sheerka.get_by_key("twenties") number = sheerka.get_by_key("number") assert sheerka.isa(twenties, number) def test_i_can_mix_sya_concepts_and_bnf_concept(self): definitions = [ "def concept one as 1", "def concept two as 2", "def concept three as 3", "def concept plus from a plus b as a + b", "def concept mult from a mult b as a * b", "def concept twenties from bnf 'twenty' (one|two)=unit as 20 + unit", ] sheerka = self.init_scenario(definitions) context = self.get_context(sheerka) sheerka.force_sya_def(context, [ (sheerka.get_by_name("mult").id, 20, SyaAssociativity.Right), (sheerka.get_by_name("plus").id, 10, SyaAssociativity.Right), ]) res = sheerka.evaluate_user_input("eval one plus two mult three") assert len(res) == 1 assert res[0].status assert res[0].body == 7 res = sheerka.evaluate_user_input("eval two mult three plus one") assert len(res) == 1 assert res[0].status assert res[0].body == 7 res = sheerka.evaluate_user_input("eval 1 plus two mult 3") assert len(res) == 1 assert res[0].status assert res[0].body == 7 res = sheerka.evaluate_user_input("eval 2 mult 3 plus one") assert len(res) == 1 assert res[0].status assert res[0].body == 7 res = sheerka.evaluate_user_input("eval twenty two plus 1") assert len(res) == 1 assert res[0].status assert res[0].body == 23 res = sheerka.evaluate_user_input("eval 1 plus twenty two") assert len(res) == 1 assert res[0].status assert res[0].body == 23 res = sheerka.evaluate_user_input("eval twenty one plus twenty two") assert len(res) == 1 assert res[0].status assert res[0].body == 43 res = sheerka.evaluate_user_input("eval twenty two plus twenty one mult two") assert len(res) == 1 assert res[0].status assert res[0].body == 64 def test_concepts_parsed_by_atom_parser_must_not_be_evaluated(self): definitions = [ "def concept mult from a mult b as a * b", "def concept a mult b as a * b", ] sheerka = self.init_scenario(definitions) res = sheerka.evaluate_user_input("eval mult") assert res[0].status assert isinstance(res[0].body, Concept) # res = sheerka.evaluate_user_input("eval a mult b") # assert res[0].status # assert isinstance(res[0].body, Concept) def test_i_can_express_comparison(self): definitions = [ "def concept one", "def concept two", "def concept three", "def concept four", ] sheerka = self.init_scenario(definitions) res = sheerka.evaluate_user_input("is_greater_than('some_prop', two, one)") assert res[0].status res = sheerka.evaluate_user_input("is_less_than('some_prop', two, three)") assert res[0].status res = sheerka.evaluate_user_input("get_concepts_weights('some_prop')") assert res[0].status assert res[0].body == {'1001': 1, '1002': 2, '1003': 3} # test i use a concept to define relation sheerka.evaluate_user_input("def concept a > b as is_greater_than('some_prop', a, b)") res = sheerka.evaluate_user_input("eval four > three") assert res[0].status res = sheerka.evaluate_user_input("get_concepts_weights('some_prop')") assert res[0].status assert res[0].body == {'1001': 1, '1002': 2, '1003': 3, '1004': 4} class TestSheerkaNonRegFile(TestUsingFileBasedSheerka): def test_i_can_def_several_concepts(self): sheerka = self.get_sheerka() sheerka.evaluate_user_input("def concept foo") sheerka = self.get_sheerka() res = sheerka.evaluate_user_input("def concept bar") assert len(res) == 1 assert res[0].status assert res[0].body.body.id == "1002" def test_i_can_create_concept_with_bnf_definition(self): sheerka = self.get_sheerka() concept_a = self.bnf_concept("a", expression=OrderedChoice(StrMatch("one"), StrMatch("two"))) sheerka.create_new_concept(self.get_context(sheerka), concept_a) res = sheerka.evaluate_user_input("def concept plus from bnf a ('plus' plus)?") assert len(res) == 1 assert res[0].status assert sheerka.isinstance(res[0].value, BuiltinConcepts.NEW_CONCEPT) saved_concept = sheerka.sdp.get(sheerka.CONCEPTS_BY_KEY_ENTRY, "plus") assert saved_concept.key == "plus" assert saved_concept.metadata.definition == "a ('plus' plus)?" assert "a" in saved_concept.values assert "plus" in saved_concept.values expected_bnf = Sequence( ConceptExpression(concept_a, rule_name="a"), Optional(Sequence(StrMatch("plus"), ConceptExpression("plus")))) new_concept = res[0].value.body assert new_concept.metadata.name == "plus" assert new_concept.metadata.definition == "a ('plus' plus)?" assert new_concept.bnf == expected_bnf assert "a" in new_concept.values assert "plus" in new_concept.values def test_i_can_recognize_bnf_definitions_from_separate_instances(self): sheerka = self.get_sheerka() concept_a = sheerka.evaluate_user_input("def concept a from bnf 'one' 'two'")[0].body.body sheerka = self.get_sheerka() res = sheerka.evaluate_user_input("one two") assert len(res) == 1 assert res[0].status assert sheerka.isinstance(res[0].value, concept_a) # add another bnf definition concept_b = sheerka.evaluate_user_input("def concept b from bnf a 'three'")[0].body.body sheerka = self.get_sheerka() res = sheerka.evaluate_user_input("one two") # previous one still works assert len(res) == 1 assert res[0].status assert sheerka.isinstance(res[0].value, concept_a) res = self.get_sheerka().evaluate_user_input("one two three") # new one works assert len(res) == 1 assert res[0].status assert sheerka.isinstance(res[0].value, concept_b) evaluated = sheerka.evaluate_concept(self.get_context(eval_body=True), res[0].value) assert evaluated.body == "one two three" assert evaluated.get_value("a") == sheerka.new(concept_a.key, body="one two").init_key()