Added RET keyword
This commit is contained in:
@@ -69,6 +69,7 @@ def test_i_can_serialize():
|
||||
where="definition of the where",
|
||||
pre="definition of the pre",
|
||||
post="definition of the post",
|
||||
ret="concept to return",
|
||||
definition="bnf definition",
|
||||
definition_type="def type",
|
||||
desc="this this the desc",
|
||||
@@ -88,6 +89,7 @@ def test_i_can_serialize():
|
||||
'name': 'concept_name',
|
||||
'post': 'definition of the post',
|
||||
'pre': 'definition of the pre',
|
||||
'ret': "concept to return",
|
||||
'props': {},
|
||||
'variables': [('a', "10"), ('b', None)],
|
||||
'where': 'definition of the where'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import ast
|
||||
import pytest
|
||||
|
||||
import pytest
|
||||
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept, BuiltinConcepts
|
||||
from core.concept import VARIABLE_PREFIX, Concept, DEFINITION_TYPE_BNF, DEFINITION_TYPE_DEF
|
||||
from core.tokenizer import Tokenizer
|
||||
@@ -52,7 +52,8 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
|
||||
)
|
||||
)
|
||||
|
||||
def get_def_concept(self, name, where=None, pre=None, post=None, body=None, definition=None, bnf_def=None):
|
||||
def get_def_concept(self, name, where=None, pre=None, post=None, body=None, ret=None,
|
||||
definition=None, bnf_def=None):
|
||||
def_concept = DefConceptNode([], name=NameNode(list(Tokenizer(name))))
|
||||
|
||||
if body:
|
||||
@@ -63,6 +64,8 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
|
||||
def_concept.pre = self.get_concept_part(pre)
|
||||
if post:
|
||||
def_concept.post = self.get_concept_part(post)
|
||||
if ret:
|
||||
def_concept.ret = self.get_concept_part(ret)
|
||||
if bnf_def:
|
||||
def_concept.definition = bnf_def
|
||||
def_concept.definition_type = DEFINITION_TYPE_BNF
|
||||
@@ -91,7 +94,8 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
|
||||
bnf_def=self.get_return_value("hello a", Sequence(StrMatch("hello"), StrMatch("a"))),
|
||||
where="isinstance(a, str )",
|
||||
pre="a is not None",
|
||||
body="print('hello' + a)")
|
||||
body="print('hello' + a)",
|
||||
ret="a")
|
||||
|
||||
evaluated = AddConceptEvaluator().eval(context, def_concept_return_value)
|
||||
|
||||
@@ -103,8 +107,9 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
|
||||
assert created_concept.metadata.key == "hello __var__0"
|
||||
assert created_concept.metadata.where == "isinstance(a, str )"
|
||||
assert created_concept.metadata.pre == "a is not None"
|
||||
assert created_concept.metadata.post is None
|
||||
assert created_concept.metadata.post is None # test that NotInitialized is mapped into None
|
||||
assert created_concept.metadata.body == "print('hello' + a)"
|
||||
assert created_concept.metadata.ret == "a"
|
||||
assert created_concept.metadata.definition == "hello a"
|
||||
assert created_concept.metadata.definition_type == "bnf"
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ class TestPythonEvaluator(TestUsingMemoryBasedSheerka):
|
||||
evaluated = PythonEvaluator().eval(context, parsed)
|
||||
|
||||
assert evaluated.status
|
||||
assert evaluated.value == 2
|
||||
assert evaluated.value == CB("foo", 2)
|
||||
|
||||
def test_i_can_eval_concept_token(self):
|
||||
context = self.get_context()
|
||||
@@ -126,13 +126,35 @@ class TestPythonEvaluator(TestUsingMemoryBasedSheerka):
|
||||
assert evaluated.status
|
||||
assert evaluated.value == "foo"
|
||||
|
||||
def test_i_can_eval_when_expect_success(self):
|
||||
context = self.get_context()
|
||||
context.sheerka.add_in_cache(Concept("foo", body="2"))
|
||||
|
||||
parsed = PythonParser().parse(context, ParserInput("foo==2"))
|
||||
python_evaluator = PythonEvaluator()
|
||||
|
||||
evaluated = python_evaluator.eval(context, parsed)
|
||||
assert evaluated.status
|
||||
assert not evaluated.value # the first test is between Concept(foo) and int(2)
|
||||
|
||||
context.local_hints.add(BuiltinConcepts.EVAL_SUCCESS_REQUESTED)
|
||||
evaluated = python_evaluator.eval(context, parsed)
|
||||
assert evaluated.status
|
||||
assert evaluated.value # we test until we compare foo.body and 2
|
||||
|
||||
parsed = PythonParser().parse(context, ParserInput("foo==3"))
|
||||
evaluated = python_evaluator.eval(context, parsed)
|
||||
assert evaluated.status
|
||||
assert not evaluated.value # neither foo or foo.body ==3
|
||||
|
||||
def test_i_can_call_function_with_complex_concepts(self):
|
||||
sheerka, context, plus, mult = self.init_concepts(
|
||||
self.from_def_concept("plus", "a plus b", ["a", "b"]),
|
||||
self.from_def_concept("mult", "a mult b", ["a", "b"]),
|
||||
)
|
||||
|
||||
parsed = PythonParser().parse(context, ParserInput("set_is_greater_than(BuiltinConcepts.PRECEDENCE, mult, plus)"))
|
||||
parsed = PythonParser().parse(context,
|
||||
ParserInput("set_is_greater_than(BuiltinConcepts.PRECEDENCE, mult, plus)"))
|
||||
python_evaluator = PythonEvaluator()
|
||||
|
||||
evaluated = python_evaluator.eval(context, parsed)
|
||||
@@ -164,8 +186,8 @@ class TestPythonEvaluator(TestUsingMemoryBasedSheerka):
|
||||
|
||||
all_globals = python_evaluator.get_all_possible_globals(context, my_globals)
|
||||
assert len(all_globals) == 2
|
||||
assert all_globals[0]["foo"] == 'foo'
|
||||
assert all_globals[1]["foo"] == CB(foo, "foo") # body is evaluated
|
||||
assert all_globals[0]["foo"] == CB(foo, "foo")
|
||||
assert all_globals[1]["foo"] == 'foo' # body is evaluated
|
||||
|
||||
def test_i_can_detect_one_error(self):
|
||||
sheerka, context, foo = self.init_concepts("foo")
|
||||
@@ -194,11 +216,11 @@ class TestPythonEvaluator(TestUsingMemoryBasedSheerka):
|
||||
error0 = evaluated.body.body[0]
|
||||
assert isinstance(error0, PythonEvalError)
|
||||
assert isinstance(error0.error, TypeError)
|
||||
assert error0.error.args[0] == 'can only concatenate str (not "int") to str'
|
||||
assert error0.concepts == {'foo': 'string'}
|
||||
assert error0.error.args[0] == "unsupported operand type(s) for +: 'Concept' and 'int'"
|
||||
assert error0.concepts == {'foo': CB(foo, 'string')}
|
||||
|
||||
error1 = evaluated.body.body[1]
|
||||
assert isinstance(error1, PythonEvalError)
|
||||
assert isinstance(error1.error, TypeError)
|
||||
assert error1.error.args[0] == "unsupported operand type(s) for +: 'Concept' and 'int'"
|
||||
assert error1.concepts == {'foo': CB(foo, 'string')}
|
||||
assert error1.error.args[0] == 'can only concatenate str (not "int") to str'
|
||||
assert error1.concepts == {'foo': 'string'}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import pytest
|
||||
from core.builtin_concepts import ReturnValueConcept
|
||||
from core.concept import Concept
|
||||
from evaluators.RetEvaluator import RetEvaluator
|
||||
|
||||
from tests.BaseTest import BaseTest
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
class TestRetEvaluator(TestUsingMemoryBasedSheerka):
|
||||
|
||||
@pytest.mark.parametrize("ret_val, expected", [
|
||||
(ReturnValueConcept("who", True, Concept("foo", ret="bar")), True),
|
||||
(ReturnValueConcept("who", False, Concept("foo", ret="bar")), False),
|
||||
(ReturnValueConcept("who", True, Concept("foo")), False),
|
||||
(BaseTest.pretval(Concept("foo", ret="bar")), False),
|
||||
(ReturnValueConcept("who", True, "not even a concept"), False),
|
||||
])
|
||||
def test_i_can_match(self, ret_val, expected):
|
||||
context = self.get_context()
|
||||
assert RetEvaluator().matches(context, ret_val) == expected
|
||||
|
||||
def test_i_can_evaluate_fully_initialized(self):
|
||||
sheerka, context, foo, the_concept = self.init_concepts("foo", Concept("the concept", ret="a").def_var("a"))
|
||||
|
||||
instance = sheerka.new("the concept")
|
||||
instance.set_value("a", sheerka.new("foo"))
|
||||
ret_value = self.tretval(sheerka, instance)
|
||||
|
||||
res = RetEvaluator().eval(context, ret_value)
|
||||
assert res.status
|
||||
assert sheerka.isinstance(res.body, "foo")
|
||||
|
||||
@pytest.mark.parametrize("instance, expected", [
|
||||
(Concept("with ret", ret="a").def_var("a", "foo"), "foo"),
|
||||
(Concept("with ret", ret="a", body="10").def_var("a", "foo"), "foo"),
|
||||
(Concept("with ret", ret="a").def_var("a", "bar"), "bar"),
|
||||
])
|
||||
def test_i_can_evaluate(self, instance, expected):
|
||||
sheerka, context, foo, bar = self.init_concepts("foo", Concept("bar", body="10"))
|
||||
|
||||
ret_value = self.tretval(sheerka, instance)
|
||||
|
||||
res = RetEvaluator().eval(context, ret_value)
|
||||
assert res.status
|
||||
assert sheerka.isinstance(res.body, expected)
|
||||
@@ -929,12 +929,12 @@ as:
|
||||
error0 = res[0].body.body.body[0]
|
||||
assert isinstance(error0, PythonEvalError)
|
||||
assert isinstance(error0.error, TypeError)
|
||||
assert error0.error.args[0] == 'can only concatenate str (not "int") to str'
|
||||
assert error0.error.args[0] == "unsupported operand type(s) for +: 'Concept' and 'int'"
|
||||
|
||||
error1 = res[0].body.body.body[1]
|
||||
assert isinstance(error1, PythonEvalError)
|
||||
assert isinstance(error1.error, TypeError)
|
||||
assert error1.error.args[0] == "unsupported operand type(s) for +: 'Concept' and 'int'"
|
||||
assert error1.error.args[0] == 'can only concatenate str (not "int") to str'
|
||||
|
||||
def test_i_can_evaluate_bnf_concept_defined_with_group_after_restart(self):
|
||||
"""
|
||||
|
||||
@@ -15,7 +15,7 @@ from parsers.PythonParser import PythonParser, PythonNode
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
def get_def_concept(name, where=None, pre=None, post=None, body=None, definition=None, bnf_def=None):
|
||||
def get_def_concept(name, where=None, pre=None, post=None, body=None, definition=None, bnf_def=None, ret=None):
|
||||
def_concept = DefConceptNode([], name=NameNode(list(Tokenizer(name))))
|
||||
|
||||
if body:
|
||||
@@ -26,6 +26,8 @@ def get_def_concept(name, where=None, pre=None, post=None, body=None, definition
|
||||
def_concept.pre = get_concept_part(pre)
|
||||
if post:
|
||||
def_concept.post = get_concept_part(post)
|
||||
if ret:
|
||||
def_concept.ret = get_concept_part(ret)
|
||||
if bnf_def:
|
||||
def_concept.definition = ReturnValueConcept(
|
||||
"parsers.Bnf",
|
||||
@@ -75,6 +77,9 @@ def get_concept_part(part):
|
||||
|
||||
@dataclass
|
||||
class PN:
|
||||
"""
|
||||
Python Node
|
||||
"""
|
||||
source: str # parser result source
|
||||
mode: str # compilation mode
|
||||
|
||||
@@ -110,21 +115,23 @@ class TestDefaultParser(TestUsingMemoryBasedSheerka):
|
||||
assert node == expected
|
||||
|
||||
def test_i_can_parse_complex_def_concept_statement(self):
|
||||
text = """def concept a plus b
|
||||
text = """def concept a mult b
|
||||
where a,b
|
||||
pre isinstance(a, int) and isinstance(b, float)
|
||||
post isinstance(res, int)
|
||||
as res = a + b
|
||||
"""
|
||||
pre isinstance(b, int)
|
||||
post isinstance(res, a)
|
||||
as res = a * b
|
||||
ret a if isinstance(a, Concept) else self
|
||||
"""
|
||||
sheerka, context, parser = self.init_parser()
|
||||
res = parser.parse(context, ParserInput(text))
|
||||
return_value = res.value
|
||||
expected_concept = get_def_concept(
|
||||
name="a plus b",
|
||||
name="a mult b",
|
||||
where="a,b\n",
|
||||
pre="isinstance(a, int) and isinstance(b, float)\n",
|
||||
post="isinstance(res, int)\n",
|
||||
body=PN("res = a + b\n ", "exec")
|
||||
pre="isinstance(b, int)\n",
|
||||
post="isinstance(res, a)\n",
|
||||
body=PN("res = a * b\n", "exec"),
|
||||
ret="a if isinstance(a, Concept) else self\n"
|
||||
)
|
||||
|
||||
assert res.status
|
||||
|
||||
Reference in New Issue
Block a user