Fixed #100 : SheerkaAdmin: Add builtins() command
Fixed #99 : SheerkaQueryManager: I can manage contains predicate when filtering objects Fixed #97 : ERROR: list indices must be integers or slices, not Concept Fixed #96 : SequenceNodeParser: SequenceNodeParser must correctly handle concept definition Fixed #95 : ResolveAmbiguity must not remove concepts that do not require evaluation Fixed #94 : Concepts with the same key are lost when new ontology Fixed #93 : Introduce BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED Fixed #92 : ExpressionParser: Implement compile_disjunctions() Fixed #91 : Implement get_concepts_complexity(context, concepts, concept_parts) Fixed #90 : ResolveAmbiguity : where predicate is not used to resolve ambiguity Fixed #89 : ResolveAmbiguityEvaluator: Concepts embedded in ConceptNode are not resolved Fixed #88: SyaNodeParser: Parse multiple parameters when some of the are not recognized Fixed #87: SyaNodeParser : Parse the multiple parameters
This commit is contained in:
@@ -4,3 +4,5 @@ def concept x is a integer pre is_question() as isinstance(x, int)
|
|||||||
def concept x starts with y pre is_question() where x is a string as x.startswith(y)
|
def concept x starts with y pre is_question() where x is a string as x.startswith(y)
|
||||||
def concept sha256 from bnf r'[a-f0-9]{64}'
|
def concept sha256 from bnf r'[a-f0-9]{64}'
|
||||||
def concept sha512 from bnf r'[a-f0-9]{128}'
|
def concept sha512 from bnf r'[a-f0-9]{128}'
|
||||||
|
|
||||||
|
def concept explain x where isinstance(x, sha256) as get_results_by_digest(x, id=0, depth=2) auto_eval True
|
||||||
Vendored
+3
-2
@@ -83,18 +83,19 @@ class CacheManager:
|
|||||||
|
|
||||||
self.caches[name] = CacheDefinition(cache, use_ref, None, persist)
|
self.caches[name] = CacheDefinition(cache, use_ref, None, persist)
|
||||||
|
|
||||||
def add_concept(self, concept):
|
def add_concept(self, concept, alt_sdp=None):
|
||||||
"""
|
"""
|
||||||
We need multiple indexes to retrieve a concept
|
We need multiple indexes to retrieve a concept
|
||||||
So the new concept is dispatched into multiple caches
|
So the new concept is dispatched into multiple caches
|
||||||
:param concept:
|
:param concept:
|
||||||
|
:param alt_sdp: if not found in self.sdp, look in other repositories
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
with self._lock:
|
with self._lock:
|
||||||
for name in self.concept_caches:
|
for name in self.concept_caches:
|
||||||
cache_def = self.caches[name]
|
cache_def = self.caches[name]
|
||||||
key = cache_def.get_key(concept)
|
key = cache_def.get_key(concept)
|
||||||
cache_def.cache.put(key, concept)
|
cache_def.cache.put(key, concept, alt_sdp)
|
||||||
|
|
||||||
self.is_dirty = True
|
self.is_dirty = True
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ class BuiltinConcepts:
|
|||||||
REDUCE_REQUESTED = "__REDUCE_REQUESTED" # remove meaningless error when possible
|
REDUCE_REQUESTED = "__REDUCE_REQUESTED" # remove meaningless error when possible
|
||||||
EVAL_UNTIL_SUCCESS_REQUESTED = "__EVAL_UNTIL_SUCCESS_REQUESTED" # PythonEvaluator tries combination until True is found
|
EVAL_UNTIL_SUCCESS_REQUESTED = "__EVAL_UNTIL_SUCCESS_REQUESTED" # PythonEvaluator tries combination until True is found
|
||||||
EVAL_QUESTION_REQUESTED = "__EVAL_QUESTION_REQUESTED" # the user input must be treated as question
|
EVAL_QUESTION_REQUESTED = "__EVAL_QUESTION_REQUESTED" # the user input must be treated as question
|
||||||
|
EVAL_GLOBAL_TRUTH_REQUESTED = "__EVAL_GLOBAL_TRUTH_REQUESTED" # the user input is a global truth
|
||||||
VALIDATION_ONLY_REQUESTED = "__VALIDATION_ONLY_REQUESTED" # Validation mode activated. Never evaluate the body
|
VALIDATION_ONLY_REQUESTED = "__VALIDATION_ONLY_REQUESTED" # Validation mode activated. Never evaluate the body
|
||||||
|
|
||||||
# possible actions during sheerka.execute() or sheerka.evaluate_rules()
|
# possible actions during sheerka.execute() or sheerka.evaluate_rules()
|
||||||
@@ -47,6 +48,7 @@ class BuiltinConcepts:
|
|||||||
EXEC_CODE = "__EXEC_CODE" # to use when executing Python or other language compiled code
|
EXEC_CODE = "__EXEC_CODE" # to use when executing Python or other language compiled code
|
||||||
TESTING = "__TESTING"
|
TESTING = "__TESTING"
|
||||||
EVALUATOR_PRE_PROCESS = "__EVALUATOR_PRE_PROCESS" # used modify / tweak behaviour of evaluators
|
EVALUATOR_PRE_PROCESS = "__EVALUATOR_PRE_PROCESS" # used modify / tweak behaviour of evaluators
|
||||||
|
EVALUATING_PRE_OR_WHERE_CLAUSE = "EVALUATING_PRE_OR_WHERE_CLAUSE" # use in is_question()
|
||||||
|
|
||||||
# builtin attributes
|
# builtin attributes
|
||||||
ISA = "__ISA" # when a concept is an instance of another one
|
ISA = "__ISA" # when a concept is an instance of another one
|
||||||
|
|||||||
+73
-10
@@ -7,8 +7,10 @@ from core.builtin_concepts import BuiltinConcepts
|
|||||||
from core.concept import Concept, ConceptParts, DEFINITION_TYPE_BNF, concept_part_value
|
from core.concept import Concept, ConceptParts, DEFINITION_TYPE_BNF, concept_part_value
|
||||||
from core.global_symbols import NotInit, NotFound, INIT_AST_PARSERS, DEFAULT_EVALUATORS
|
from core.global_symbols import NotInit, NotFound, INIT_AST_PARSERS, DEFAULT_EVALUATORS
|
||||||
from core.rule import Rule
|
from core.rule import Rule
|
||||||
|
from core.sheerka.services.SheerkaExecute import ParserInput
|
||||||
from core.tokenizer import Tokenizer, TokenKind
|
from core.tokenizer import Tokenizer, TokenKind
|
||||||
from core.utils import as_bag
|
from core.utils import as_bag
|
||||||
|
from parsers.BaseExpressionParser import compile_disjunctions, AndNode
|
||||||
from parsers.BaseNodeParser import SourceCodeNode, ConceptNode, UnrecognizedTokensNode, SourceCodeWithConceptNode, \
|
from parsers.BaseNodeParser import SourceCodeNode, ConceptNode, UnrecognizedTokensNode, SourceCodeWithConceptNode, \
|
||||||
RuleNode, LexerNode
|
RuleNode, LexerNode
|
||||||
from parsers.BaseParser import ParsingError
|
from parsers.BaseParser import ParsingError
|
||||||
@@ -205,7 +207,7 @@ def only_successful(context, return_values):
|
|||||||
def resolve_ambiguity(context, concepts):
|
def resolve_ambiguity(context, concepts):
|
||||||
"""
|
"""
|
||||||
From the list of concepts, elect the one(s) that best suit(s) the context
|
From the list of concepts, elect the one(s) that best suit(s) the context
|
||||||
Use the PRE metadata to choose the correct concepts
|
Use the PRE and WHERE metadata to choose the correct concepts
|
||||||
:param context:
|
:param context:
|
||||||
:param concepts:
|
:param concepts:
|
||||||
:return:
|
:return:
|
||||||
@@ -214,8 +216,9 @@ def resolve_ambiguity(context, concepts):
|
|||||||
# we first sort by condition complexity. The more complex is the PRE condition, the more likely
|
# we first sort by condition complexity. The more complex is the PRE condition, the more likely
|
||||||
# the concept matches the context
|
# the concept matches the context
|
||||||
by_complexity = {}
|
by_complexity = {}
|
||||||
|
parts = [concept_part_value(ConceptParts.PRE), concept_part_value(ConceptParts.WHERE)]
|
||||||
for c in concepts:
|
for c in concepts:
|
||||||
by_complexity.setdefault(get_condition_complexity(c, concept_part_value(ConceptParts.PRE)), []).append(c)
|
by_complexity.setdefault(get_concept_complexity(context, c, parts), []).append(c)
|
||||||
|
|
||||||
remaining_concepts = []
|
remaining_concepts = []
|
||||||
for complexity in sorted(by_complexity.keys(), reverse=True):
|
for complexity in sorted(by_complexity.keys(), reverse=True):
|
||||||
@@ -226,14 +229,14 @@ def resolve_ambiguity(context, concepts):
|
|||||||
evaluated = context.sheerka.evaluate_concept(context, c,
|
evaluated = context.sheerka.evaluate_concept(context, c,
|
||||||
eval_body=False,
|
eval_body=False,
|
||||||
validation_only=True,
|
validation_only=True,
|
||||||
metadata=[ConceptParts.PRE])
|
metadata=[ConceptParts.PRE, ConceptParts.WHERE])
|
||||||
if context.sheerka.is_success(evaluated) or evaluated.key == c.key:
|
if context.sheerka.is_success(evaluated) or evaluated.key == c.key:
|
||||||
remaining_concepts.append(c)
|
remaining_concepts.append(c)
|
||||||
|
|
||||||
if len(remaining_concepts) > 0:
|
if len(remaining_concepts) > 0:
|
||||||
break # no need to check concept with lower complexity
|
break # no need to check concept with lower complexity
|
||||||
|
|
||||||
if len(remaining_concepts) in (0, 1):
|
if len(remaining_concepts) < 2:
|
||||||
return remaining_concepts # they all failed the pre conditions or one champ is found
|
return remaining_concepts # they all failed the pre conditions or one champ is found
|
||||||
|
|
||||||
# for concepts with the same condition complexity, we choose the one that has the less number of variables
|
# for concepts with the same condition complexity, we choose the one that has the less number of variables
|
||||||
@@ -246,19 +249,58 @@ def resolve_ambiguity(context, concepts):
|
|||||||
return by_number_of_vars[min(by_number_of_vars.keys())]
|
return by_number_of_vars[min(by_number_of_vars.keys())]
|
||||||
|
|
||||||
|
|
||||||
def get_condition_complexity(concept, concept_part_str):
|
def get_condition_complexity(context, condition):
|
||||||
|
if condition is None or condition.strip() == "":
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# # count the number of conjunctions
|
||||||
|
from parsers.LogicalOperatorParser import LogicalOperatorParser
|
||||||
|
parser = LogicalOperatorParser()
|
||||||
|
res = parser.parse(context, ParserInput(condition))
|
||||||
|
if not res.status:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
disjunctions = compile_disjunctions(res.body.body)
|
||||||
|
complexity = 0
|
||||||
|
for conjunction in disjunctions:
|
||||||
|
node_complexity = len(conjunction.parts) if isinstance(conjunction, AndNode) else 1
|
||||||
|
if node_complexity > complexity:
|
||||||
|
complexity = node_complexity
|
||||||
|
|
||||||
|
return complexity
|
||||||
|
|
||||||
|
|
||||||
|
def get_concept_complexity(context, concept, concepts_parts):
|
||||||
"""
|
"""
|
||||||
Need to find a proper algorithm to compute the complexity of a concept metadata
|
Need to find a proper algorithm to compute the complexity of a concept metadata
|
||||||
So far, the concept is considered as complex if it has concept_part_str (so far with concept_part_str='pre')
|
So far, the concept is considered as complex if it has concept_part_str (so far with concept_part_str='pre')
|
||||||
|
:param context:
|
||||||
:param concept:
|
:param concept:
|
||||||
:param concept_part_str:
|
:param concepts_parts:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
value = getattr(concept.get_metadata(), concept_part_str)
|
complexity = 0
|
||||||
if value is None or value.strip() == 0:
|
for i, parts in enumerate(reversed(concepts_parts)):
|
||||||
return 0
|
|
||||||
|
|
||||||
return 1 # no real computing as of now
|
for part in parts.split("|"):
|
||||||
|
value = getattr(concept.get_metadata(), part)
|
||||||
|
part_complexity = get_condition_complexity(context, value)
|
||||||
|
|
||||||
|
if part_complexity > 0:
|
||||||
|
complexity += part_complexity + (i * 100)
|
||||||
|
|
||||||
|
return complexity
|
||||||
|
|
||||||
|
|
||||||
|
def get_concepts_complexity(context, concepts, concepts_parts):
|
||||||
|
"""
|
||||||
|
compute the complexity of the concepts, relatively to each others
|
||||||
|
:param context:
|
||||||
|
:param concepts: concepts
|
||||||
|
:param concepts_parts: metadata to use to compute the complexity
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
return {c.id or c.name: get_concept_complexity(context, c, concepts_parts) for c in concepts}
|
||||||
|
|
||||||
|
|
||||||
def only_parsers_results(context, return_values):
|
def only_parsers_results(context, return_values):
|
||||||
@@ -723,6 +765,27 @@ def set_is_evaluated(concepts, check_nb_variables=False):
|
|||||||
concepts.get_hints().is_evaluated = True
|
concepts.get_hints().is_evaluated = True
|
||||||
|
|
||||||
|
|
||||||
|
def update_concepts_hints(concepts, is_evaluated=None, recognized_by=None, is_instance=None):
|
||||||
|
if concepts is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
def update_concept_hints(c, _is_evaluated, _recognized_by, _is_instance):
|
||||||
|
if _is_evaluated is not None:
|
||||||
|
c.get_hints().is_evaluated = _is_evaluated
|
||||||
|
|
||||||
|
if _recognized_by is not None:
|
||||||
|
c.get_hints().recognized_by = _recognized_by
|
||||||
|
|
||||||
|
if _is_instance is not None:
|
||||||
|
c.get_hints().is_instance = _is_instance
|
||||||
|
|
||||||
|
if hasattr(concepts, "__iter__"):
|
||||||
|
for concept in concepts:
|
||||||
|
update_concept_hints(concept, is_evaluated, recognized_by, is_instance)
|
||||||
|
else:
|
||||||
|
update_concept_hints(concepts, is_evaluated, recognized_by, is_instance)
|
||||||
|
|
||||||
|
|
||||||
def ensure_concept(*concepts):
|
def ensure_concept(*concepts):
|
||||||
if hasattr(concepts, "__iter__"):
|
if hasattr(concepts, "__iter__"):
|
||||||
for concept in concepts:
|
for concept in concepts:
|
||||||
|
|||||||
+10
-3
@@ -44,14 +44,16 @@ def concept_part_value(c):
|
|||||||
class ConceptHints:
|
class ConceptHints:
|
||||||
is_evaluated: bool = False # True is the concept is evaluated by sheerka.eval_concept()
|
is_evaluated: bool = False # True is the concept is evaluated by sheerka.eval_concept()
|
||||||
need_validation: bool = False # True if the properties of the concept need to be validated
|
need_validation: bool = False # True if the properties of the concept need to be validated
|
||||||
recognized_by: str = None
|
recognized_by: str = None # recognized by its name, by its id or its key
|
||||||
use_copy: bool = False
|
use_copy: bool = False # Do not modify, make a copy first
|
||||||
|
is_instance: bool = True # False if we think we recognize the definition of a concept, not its usage
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
return ConceptHints(self.is_evaluated,
|
return ConceptHints(self.is_evaluated,
|
||||||
self.need_validation,
|
self.need_validation,
|
||||||
self.recognized_by,
|
self.recognized_by,
|
||||||
self.use_copy)
|
self.use_copy,
|
||||||
|
self.is_instance)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -624,6 +626,11 @@ class Concept:
|
|||||||
return Concept().update_from(self, update_hint=True, update_compiled=True)
|
return Concept().update_from(self, update_hint=True, update_compiled=True)
|
||||||
|
|
||||||
def get_concept(self):
|
def get_concept(self):
|
||||||
|
"""
|
||||||
|
Used when there is a mix of Concept and ConceptNode
|
||||||
|
To quickly get the inner concept
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -96,4 +96,4 @@ INIT_AST_PARSERS = ["ExactConcept",
|
|||||||
|
|
||||||
INIT_AST_QUESTION_PARSERS = ["Expression"]
|
INIT_AST_QUESTION_PARSERS = ["Expression"]
|
||||||
|
|
||||||
DEFAULT_EVALUATORS = ["Python", "Concept", "LexerNode", "ValidateConcept", "ResolveAmbiguity"]
|
DEFAULT_EVALUATORS = ["Python", "Concept", "LexerNode", "Expression", "ValidateConcept", "ResolveAmbiguity"]
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ class ExecutionContext:
|
|||||||
self.private_hints = set()
|
self.private_hints = set()
|
||||||
self.protected_hints = set()
|
self.protected_hints = set()
|
||||||
self.global_hints = set() if global_hints is None else global_hints
|
self.global_hints = set() if global_hints is None else global_hints
|
||||||
self.errors = [] if errors is None else errors # error are global
|
self.errors = [] if errors is None else errors # errors are global
|
||||||
|
|
||||||
self.inputs = {} # what were the parameters of the execution context
|
self.inputs = {} # what were the parameters of the execution context
|
||||||
self.values = {} # what was produced by the execution context
|
self.values = {} # what was produced by the execution context
|
||||||
|
|||||||
+66
-15
@@ -46,6 +46,7 @@ RULES_EXECUTE_STEPS = [
|
|||||||
# It indicate which parameter was used to recognize the concept
|
# It indicate which parameter was used to recognize the concept
|
||||||
RECOGNIZED_BY_ID = "by_id"
|
RECOGNIZED_BY_ID = "by_id"
|
||||||
RECOGNIZED_BY_NAME = "by_name"
|
RECOGNIZED_BY_NAME = "by_name"
|
||||||
|
RECOGNIZED_BY_KEY = "by_key"
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -53,9 +54,17 @@ class SheerkaMethod:
|
|||||||
"""
|
"""
|
||||||
Wrapper to sheerka method, to indicate if it's safe to call
|
Wrapper to sheerka method, to indicate if it's safe to call
|
||||||
"""
|
"""
|
||||||
|
name: str
|
||||||
|
service: str
|
||||||
method: object
|
method: object
|
||||||
has_side_effect: bool
|
has_side_effect: bool
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def __hash__(self):
|
||||||
|
return hash((self.name, self.service))
|
||||||
|
|
||||||
|
|
||||||
class Sheerka(Concept):
|
class Sheerka(Concept):
|
||||||
"""
|
"""
|
||||||
@@ -111,16 +120,18 @@ class Sheerka(Concept):
|
|||||||
self.methods_with_context = {"test_using_context"} # only the names, the method is defined in sheerka_methods
|
self.methods_with_context = {"test_using_context"} # only the names, the method is defined in sheerka_methods
|
||||||
self.pipe_functions = set()
|
self.pipe_functions = set()
|
||||||
self.sheerka_methods = {
|
self.sheerka_methods = {
|
||||||
"test": SheerkaMethod(self.test, False),
|
"test": SheerkaMethod("test", self.name, self.test, False),
|
||||||
"test_using_context": SheerkaMethod(self.test_using_context, False),
|
"test_using_context": SheerkaMethod("test_using_context", self.name, self.test_using_context, False),
|
||||||
"test_dict": SheerkaMethod(self.test_dict, False),
|
"test_dict": SheerkaMethod("test_dict", self.name, self.test_dict, False),
|
||||||
"test_error": SheerkaMethod(self.test_error, False),
|
"test_error": SheerkaMethod("test_error", self.name, self.test_error, False),
|
||||||
"is_sheerka": SheerkaMethod(self.is_sheerka, False),
|
"is_sheerka": SheerkaMethod("is_sheerka", self.name, self.is_sheerka, False),
|
||||||
"objvalue": SheerkaMethod(self.objvalue, False),
|
"objvalue": SheerkaMethod("objvalue", self.name, self.objvalue, False),
|
||||||
}
|
}
|
||||||
|
|
||||||
self.concepts_ids = None
|
self.concepts_ids = None
|
||||||
|
|
||||||
|
self._global_context_hints = set() # hints to add to every execution contexts before every execution
|
||||||
|
|
||||||
def __copy__(self):
|
def __copy__(self):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@@ -135,9 +146,10 @@ class Sheerka(Concept):
|
|||||||
def root_folder(self):
|
def root_folder(self):
|
||||||
return self.om.root_folder
|
return self.om.root_folder
|
||||||
|
|
||||||
def bind_service_method(self, bound_method, has_side_effect, as_name=None, visible=True):
|
def bind_service_method(self, service_name, bound_method, has_side_effect, as_name=None, visible=True):
|
||||||
"""
|
"""
|
||||||
Bind service method to sheerka instance for ease of use ?
|
Bind service method to sheerka instance for ease of use ?
|
||||||
|
:param service_name:
|
||||||
:param bound_method:
|
:param bound_method:
|
||||||
:param has_side_effect: False if the method is safe
|
:param has_side_effect: False if the method is safe
|
||||||
:param as_name: give another name to the method
|
:param as_name: give another name to the method
|
||||||
@@ -157,7 +169,7 @@ class Sheerka(Concept):
|
|||||||
signature = inspect.signature(bound_method)
|
signature = inspect.signature(bound_method)
|
||||||
if len(signature.parameters) > 0 and list(signature.parameters.keys())[0] == "context":
|
if len(signature.parameters) > 0 and list(signature.parameters.keys())[0] == "context":
|
||||||
self.methods_with_context.add(as_name)
|
self.methods_with_context.add(as_name)
|
||||||
self.sheerka_methods[as_name] = SheerkaMethod(bound_method, has_side_effect)
|
self.sheerka_methods[as_name] = SheerkaMethod(as_name, service_name, bound_method, has_side_effect)
|
||||||
if is_pipe_function:
|
if is_pipe_function:
|
||||||
self.pipe_functions.add(as_name)
|
self.pipe_functions.add(as_name)
|
||||||
|
|
||||||
@@ -368,6 +380,9 @@ class Sheerka(Concept):
|
|||||||
text,
|
text,
|
||||||
desc=f"Evaluating '{text}'") as execution_context:
|
desc=f"Evaluating '{text}'") as execution_context:
|
||||||
|
|
||||||
|
# adds the global context hints if any
|
||||||
|
execution_context.global_hints = self._global_context_hints.copy()
|
||||||
|
|
||||||
user_input = self.ret(self.name, True, self.new(BuiltinConcepts.USER_INPUT, body=text, user_name=user_name))
|
user_input = self.ret(self.name, True, self.new(BuiltinConcepts.USER_INPUT, body=text, user_name=user_name))
|
||||||
execution_context.add_inputs(user_input=user_input)
|
execution_context.add_inputs(user_input=user_input)
|
||||||
|
|
||||||
@@ -465,17 +480,35 @@ class Sheerka(Concept):
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def fast_resolve(self, key, return_new=True):
|
def fast_resolve(self, key, return_new=True, force_instance=False):
|
||||||
def add_recognized_by(c, _recognized_by):
|
"""
|
||||||
c.get_hints().recognized_by = _recognized_by
|
Resolve a concept, but do not use get_by_name() or get_by_id()
|
||||||
|
:param key:
|
||||||
|
:param return_new:
|
||||||
|
:param force_instance: When set, return an concept instance, not a concept definition
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
def update_hints(c, rec_by, is_inst, is_eval):
|
||||||
|
c.get_hints().recognized_by = rec_by
|
||||||
|
c.get_hints().is_instance = is_inst
|
||||||
|
if is_eval is None:
|
||||||
|
c.get_hints().is_evaluated = len(c.get_metadata().variables) > 0
|
||||||
|
else:
|
||||||
|
c.get_hints().is_evaluated = is_eval
|
||||||
return c
|
return c
|
||||||
|
|
||||||
def new_instances(concepts, _recognized_by):
|
def new_instances(concepts, rec_by, is_inst, is_eval):
|
||||||
if hasattr(concepts, "__iter__"):
|
if hasattr(concepts, "__iter__"):
|
||||||
return [add_recognized_by(self.new_from_template(c, c.key), _recognized_by) for c in concepts]
|
return [update_hints(self.new_from_template(c, c.key), rec_by, is_inst, is_eval) for c in
|
||||||
|
concepts]
|
||||||
|
|
||||||
return add_recognized_by(self.new_from_template(concepts, concepts.key), _recognized_by)
|
return update_hints(self.new_from_template(concepts, concepts.key), rec_by, is_inst, is_eval)
|
||||||
|
|
||||||
|
# ##############
|
||||||
|
# PREPROCESS
|
||||||
|
# ##############
|
||||||
|
# if the entry is a concept token, use its values.
|
||||||
if isinstance(key, Token):
|
if isinstance(key, Token):
|
||||||
if key.type == TokenKind.RULE: # do not recognize rules !!!
|
if key.type == TokenKind.RULE: # do not recognize rules !!!
|
||||||
return None
|
return None
|
||||||
@@ -484,10 +517,15 @@ class Sheerka(Concept):
|
|||||||
elif isinstance(key, str) and key.startswith("c:"):
|
elif isinstance(key, str) and key.startswith("c:"):
|
||||||
key = core.utils.unstr_concept(key)
|
key = core.utils.unstr_concept(key)
|
||||||
|
|
||||||
|
# ##############
|
||||||
|
# Get the concept(s)
|
||||||
|
# ##############
|
||||||
if isinstance(key, tuple):
|
if isinstance(key, tuple):
|
||||||
if key == (None, None):
|
if key == (None, None):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
is_instance = force_instance
|
||||||
|
is_evaluated = not force_instance
|
||||||
if key[1]:
|
if key[1]:
|
||||||
concept = self.om.get(self.CONCEPTS_BY_ID_ENTRY, key[1])
|
concept = self.om.get(self.CONCEPTS_BY_ID_ENTRY, key[1])
|
||||||
recognized_by = RECOGNIZED_BY_ID
|
recognized_by = RECOGNIZED_BY_ID
|
||||||
@@ -495,12 +533,15 @@ class Sheerka(Concept):
|
|||||||
concept = self.om.get(self.CONCEPTS_BY_NAME_ENTRY, key[0])
|
concept = self.om.get(self.CONCEPTS_BY_NAME_ENTRY, key[0])
|
||||||
recognized_by = RECOGNIZED_BY_NAME
|
recognized_by = RECOGNIZED_BY_NAME
|
||||||
else:
|
else:
|
||||||
|
is_instance = True
|
||||||
|
is_evaluated = None
|
||||||
concept = self.om.get(self.CONCEPTS_BY_NAME_ENTRY, key)
|
concept = self.om.get(self.CONCEPTS_BY_NAME_ENTRY, key)
|
||||||
recognized_by = RECOGNIZED_BY_NAME
|
recognized_by = RECOGNIZED_BY_NAME
|
||||||
|
|
||||||
if concept is NotFound:
|
if concept is NotFound:
|
||||||
return None
|
return None
|
||||||
return new_instances(concept, recognized_by) if return_new else concept
|
|
||||||
|
return new_instances(concept, recognized_by, is_instance, is_evaluated) if return_new else concept
|
||||||
|
|
||||||
def new(self, concept_key, **kwargs):
|
def new(self, concept_key, **kwargs):
|
||||||
"""
|
"""
|
||||||
@@ -632,6 +673,16 @@ class Sheerka(Concept):
|
|||||||
if hasattr(service, "reset_state"):
|
if hasattr(service, "reset_state"):
|
||||||
service.reset_state()
|
service.reset_state()
|
||||||
|
|
||||||
|
def add_to_context(self, concept_key):
|
||||||
|
concept_key = concept_key.name if isinstance(concept_key, Concept) else concept_key
|
||||||
|
self._global_context_hints.add(concept_key)
|
||||||
|
return self.ret(self.name, True, self.new(BuiltinConcepts.SUCCESS))
|
||||||
|
|
||||||
|
def remove_fom_context(self, concept_key):
|
||||||
|
concept_key = concept_key.name if isinstance(concept_key, Concept) else concept_key
|
||||||
|
self._global_context_hints.remove(concept_key)
|
||||||
|
return self.ret(self.name, True, self.new(BuiltinConcepts.SUCCESS))
|
||||||
|
|
||||||
def ret(self, who: str, status: bool, value, parents=None):
|
def ret(self, who: str, status: bool, value, parents=None):
|
||||||
"""
|
"""
|
||||||
Creates and returns a ReturnValue concept
|
Creates and returns a ReturnValue concept
|
||||||
|
|||||||
@@ -300,7 +300,7 @@ class SheerkaOntologyManager:
|
|||||||
:param concept:
|
:param concept:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
return self.current_cache_manager().add_concept(concept)
|
return self.current_cache_manager().add_concept(concept, self.ontologies[0].alt_sdp)
|
||||||
|
|
||||||
def update_concept(self, old, new):
|
def update_concept(self, old, new):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from core.sheerka.services.SheerkaHistoryManager import SheerkaHistoryManager
|
|||||||
from core.sheerka.services.SheerkaMemory import SheerkaMemory
|
from core.sheerka.services.SheerkaMemory import SheerkaMemory
|
||||||
from core.sheerka.services.sheerka_service import BaseService
|
from core.sheerka.services.sheerka_service import BaseService
|
||||||
|
|
||||||
CONCEPTS_FILE_FULL = "full.sb"
|
CONCEPTS_FILE_FULL = "full.sb" # .sb for sheerka backup
|
||||||
CONCEPTS_FILE_TO_USE = CONCEPTS_FILE_FULL
|
CONCEPTS_FILE_TO_USE = CONCEPTS_FILE_FULL
|
||||||
|
|
||||||
|
|
||||||
@@ -22,24 +22,24 @@ class SheerkaAdmin(BaseService):
|
|||||||
super().__init__(sheerka)
|
super().__init__(sheerka)
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
self.sheerka.bind_service_method(self.caches_names, False)
|
self.sheerka.bind_service_method(self.NAME, self.caches_names, False)
|
||||||
self.sheerka.bind_service_method(self.cache, False)
|
self.sheerka.bind_service_method(self.NAME, self.cache, False)
|
||||||
self.sheerka.bind_service_method(self.restore, True)
|
self.sheerka.bind_service_method(self.NAME, self.restore, True)
|
||||||
self.sheerka.bind_service_method(self.concepts, False)
|
self.sheerka.bind_service_method(self.NAME, self.concepts, False)
|
||||||
self.sheerka.bind_service_method(self.desc, False)
|
self.sheerka.bind_service_method(self.NAME, self.builtins, False)
|
||||||
self.sheerka.bind_service_method(self.desc_evaluators, False)
|
self.sheerka.bind_service_method(self.NAME, self.desc, False)
|
||||||
self.sheerka.bind_service_method(self.desc_parsers, False)
|
self.sheerka.bind_service_method(self.NAME, self.desc_evaluators, False)
|
||||||
self.sheerka.bind_service_method(self.extended_isinstance, False)
|
self.sheerka.bind_service_method(self.NAME, self.desc_parsers, False)
|
||||||
self.sheerka.bind_service_method(self.is_container, False)
|
self.sheerka.bind_service_method(self.NAME, self.extended_isinstance, False)
|
||||||
self.sheerka.bind_service_method(self.format_rules, False)
|
self.sheerka.bind_service_method(self.NAME, self.is_container, False)
|
||||||
self.sheerka.bind_service_method(self.exec_rules, False)
|
self.sheerka.bind_service_method(self.NAME, self.format_rules, False)
|
||||||
self.sheerka.bind_service_method(self.admin_push_ontology, True, as_name="push_ontology")
|
self.sheerka.bind_service_method(self.NAME, self.exec_rules, False)
|
||||||
self.sheerka.bind_service_method(self.admin_pop_ontology, True, as_name="pop_ontology")
|
self.sheerka.bind_service_method(self.NAME, self.admin_push_ontology, True, as_name="push_ontology")
|
||||||
self.sheerka.bind_service_method(self.ontologies, False)
|
self.sheerka.bind_service_method(self.NAME, self.admin_pop_ontology, True, as_name="pop_ontology")
|
||||||
self.sheerka.bind_service_method(self.in_memory, False)
|
self.sheerka.bind_service_method(self.NAME, self.ontologies, False)
|
||||||
self.sheerka.bind_service_method(self.admin_history, False, as_name="history")
|
self.sheerka.bind_service_method(self.NAME, self.in_memory, False)
|
||||||
self.sheerka.bind_service_method(self.sdp, False)
|
self.sheerka.bind_service_method(self.NAME, self.admin_history, False, as_name="history")
|
||||||
self.sheerka.bind_service_method(self.atomic_def, False)
|
self.sheerka.bind_service_method(self.NAME, self.sdp, False)
|
||||||
|
|
||||||
def caches_names(self):
|
def caches_names(self):
|
||||||
"""
|
"""
|
||||||
@@ -138,9 +138,11 @@ class SheerkaAdmin(BaseService):
|
|||||||
self.sheerka.save_execution_context = False
|
self.sheerka.save_execution_context = False
|
||||||
enable_process_return_values_previous_value = self.sheerka.enable_process_return_values
|
enable_process_return_values_previous_value = self.sheerka.enable_process_return_values
|
||||||
self.sheerka.enable_process_return_values = False
|
self.sheerka.enable_process_return_values = False
|
||||||
|
self.sheerka.add_to_context(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED)
|
||||||
|
|
||||||
nb_lines, nb_instructions, nb_lines_in_error, min_time, max_time = restore_from_file(backup_file)
|
nb_lines, nb_instructions, nb_lines_in_error, min_time, max_time = restore_from_file(backup_file)
|
||||||
|
|
||||||
|
self.sheerka.remove_fom_context(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED)
|
||||||
self.sheerka.enable_process_return_values = enable_process_return_values_previous_value
|
self.sheerka.enable_process_return_values = enable_process_return_values_previous_value
|
||||||
self.sheerka.save_execution_context = True
|
self.sheerka.save_execution_context = True
|
||||||
self.sheerka.during_restore = False
|
self.sheerka.during_restore = False
|
||||||
@@ -167,6 +169,10 @@ class SheerkaAdmin(BaseService):
|
|||||||
concepts = sorted(self.sheerka.om.list(self.sheerka.CONCEPTS_BY_ID_ENTRY), key=lambda item: int(item.id))
|
concepts = sorted(self.sheerka.om.list(self.sheerka.CONCEPTS_BY_ID_ENTRY), key=lambda item: int(item.id))
|
||||||
return self.sheerka.new(BuiltinConcepts.TO_LIST, body=concepts)
|
return self.sheerka.new(BuiltinConcepts.TO_LIST, body=concepts)
|
||||||
|
|
||||||
|
def builtins(self):
|
||||||
|
builtins = sorted(self.sheerka.sheerka_methods.values(), key=lambda builtin_method: builtin_method.name)
|
||||||
|
return self.sheerka.new(BuiltinConcepts.TO_LIST, body=builtins)
|
||||||
|
|
||||||
def desc_evaluators(self):
|
def desc_evaluators(self):
|
||||||
evaluators = {k: sorted(v[0].items(), reverse=True)
|
evaluators = {k: sorted(v[0].items(), reverse=True)
|
||||||
for k, v in self.sheerka.services[SheerkaExecute.NAME].grouped_evaluators_cache.items()}
|
for k, v in self.sheerka.services[SheerkaExecute.NAME].grouped_evaluators_cache.items()}
|
||||||
@@ -241,20 +247,6 @@ class SheerkaAdmin(BaseService):
|
|||||||
|
|
||||||
return self.sheerka.isinstance(a, b)
|
return self.sheerka.isinstance(a, b)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def atomic_def(a):
|
|
||||||
"""
|
|
||||||
Return the 'atomic definition' of a concept
|
|
||||||
a concept key stripped from its 'var' tokens
|
|
||||||
>>> assert atomic_def(Concept('a plus b').def_var("a").def_var("b")) == "plus"
|
|
||||||
>>> assert atomic_def(Concept('x is a y').def_var("x").def_var("y")) == "is a"
|
|
||||||
:param a:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
ensure_concept(a)
|
|
||||||
|
|
||||||
return a.get_atomic_def()
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_container(obj):
|
def is_container(obj):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -47,12 +47,12 @@ class SheerkaComparisonManager(BaseService):
|
|||||||
cache = Cache().auto_configure(self.RESOLVED_COMPARISON_ENTRY)
|
cache = Cache().auto_configure(self.RESOLVED_COMPARISON_ENTRY)
|
||||||
self.sheerka.om.register_cache(self.RESOLVED_COMPARISON_ENTRY, cache, persist=False)
|
self.sheerka.om.register_cache(self.RESOLVED_COMPARISON_ENTRY, cache, persist=False)
|
||||||
|
|
||||||
self.sheerka.bind_service_method(self.set_is_greater_than, True)
|
self.sheerka.bind_service_method(self.NAME, self.set_is_greater_than, True)
|
||||||
self.sheerka.bind_service_method(self.set_is_less_than, True)
|
self.sheerka.bind_service_method(self.NAME, self.set_is_less_than, True)
|
||||||
self.sheerka.bind_service_method(self.set_is_lesser, True)
|
self.sheerka.bind_service_method(self.NAME, self.set_is_lesser, True)
|
||||||
self.sheerka.bind_service_method(self.set_is_greatest, True)
|
self.sheerka.bind_service_method(self.NAME, self.set_is_greatest, True)
|
||||||
self.sheerka.bind_service_method(self.get_partition, False)
|
self.sheerka.bind_service_method(self.NAME, self.get_partition, False)
|
||||||
self.sheerka.bind_service_method(self.get_weights, False)
|
self.sheerka.bind_service_method(self.NAME, self.get_weights, False)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _compute_key(prop_name, comparison_context):
|
def _compute_key(prop_name, comparison_context):
|
||||||
|
|||||||
@@ -113,26 +113,26 @@ class SheerkaConceptManager(BaseService):
|
|||||||
self.compiled_concepts_by_regex = []
|
self.compiled_concepts_by_regex = []
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
self.sheerka.bind_service_method(self.create_new_concept, True)
|
self.sheerka.bind_service_method(self.NAME, self.create_new_concept, True)
|
||||||
self.sheerka.bind_service_method(self.modify_concept, True)
|
self.sheerka.bind_service_method(self.NAME, self.modify_concept, True)
|
||||||
self.sheerka.bind_service_method(self.remove_concept, True)
|
self.sheerka.bind_service_method(self.NAME, self.remove_concept, True)
|
||||||
self.sheerka.bind_service_method(self.set_id_if_needed, True)
|
self.sheerka.bind_service_method(self.NAME, self.set_id_if_needed, True)
|
||||||
self.sheerka.bind_service_method(self.set_attr, True)
|
self.sheerka.bind_service_method(self.NAME, self.set_attr, True)
|
||||||
self.sheerka.bind_service_method(self.get_attr, False)
|
self.sheerka.bind_service_method(self.NAME, self.get_attr, False)
|
||||||
self.sheerka.bind_service_method(self.smart_get_attr, False)
|
self.sheerka.bind_service_method(self.NAME, self.smart_get_attr, False)
|
||||||
self.sheerka.bind_service_method(self.set_property, True, as_name="set_prop")
|
self.sheerka.bind_service_method(self.NAME, self.set_property, True, as_name="set_prop")
|
||||||
self.sheerka.bind_service_method(self.get_property, False, as_name="get_prop")
|
self.sheerka.bind_service_method(self.NAME, self.get_property, False, as_name="get_prop")
|
||||||
self.sheerka.bind_service_method(self.get_by_key, False, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.get_by_key, False, visible=False)
|
||||||
self.sheerka.bind_service_method(self.get_by_name, False, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.get_by_name, False, visible=False)
|
||||||
self.sheerka.bind_service_method(self.get_by_hash, False, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.get_by_hash, False, visible=False)
|
||||||
self.sheerka.bind_service_method(self.get_by_id, False, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.get_by_id, False, visible=False)
|
||||||
self.sheerka.bind_service_method(self.is_not_a_concept_name, False, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.is_not_a_concept_name, False, visible=False)
|
||||||
self.sheerka.bind_service_method(self.is_a_concept_name, False, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.is_a_concept_name, False, visible=False)
|
||||||
self.sheerka.bind_service_method(self.get_concepts_by_first_token, False, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.get_concepts_by_first_token, False, visible=False)
|
||||||
self.sheerka.bind_service_method(self.get_concepts_by_first_regex, False, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.get_concepts_by_first_regex, False, visible=False)
|
||||||
self.sheerka.bind_service_method(self.get_concepts_bnf_definitions, False, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.get_concepts_bnf_definitions, False, visible=False)
|
||||||
self.sheerka.bind_service_method(self.clear_bnf_definition, True, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.clear_bnf_definition, True, visible=False)
|
||||||
self.sheerka.bind_service_method(self.set_precedence, True)
|
self.sheerka.bind_service_method(self.NAME, self.set_precedence, True)
|
||||||
|
|
||||||
register_concept_cache = self.sheerka.om.register_concept_cache
|
register_concept_cache = self.sheerka.om.register_concept_cache
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ from operator import attrgetter
|
|||||||
from core.builtin_concepts import BuiltinConcepts
|
from core.builtin_concepts import BuiltinConcepts
|
||||||
from core.builtin_helpers import ensure_concept
|
from core.builtin_helpers import ensure_concept
|
||||||
from core.concept import Concept
|
from core.concept import Concept
|
||||||
from core.sheerka.Sheerka import Sheerka
|
|
||||||
from core.sheerka.services.SheerkaConceptManager import SheerkaConceptManager
|
from core.sheerka.services.SheerkaConceptManager import SheerkaConceptManager
|
||||||
from core.sheerka.services.sheerka_service import BaseService
|
from core.sheerka.services.sheerka_service import BaseService
|
||||||
|
|
||||||
@@ -28,9 +27,9 @@ class SheerkaConceptsAlgebra(BaseService):
|
|||||||
super().__init__(sheerka)
|
super().__init__(sheerka)
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
self.sheerka.bind_service_method(self.cadd, False)
|
self.sheerka.bind_service_method(self.NAME, self.cadd, False)
|
||||||
self.sheerka.bind_service_method(self.csub, False)
|
self.sheerka.bind_service_method(self.NAME, self.csub, False)
|
||||||
self.sheerka.bind_service_method(self.recognize, False)
|
self.sheerka.bind_service_method(self.NAME, self.recognize, False)
|
||||||
|
|
||||||
def cadd(self, context, *concepts):
|
def cadd(self, context, *concepts):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -320,22 +320,22 @@ class SheerkaDebugManager(BaseService):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
self.sheerka.bind_service_method(self.set_debug, True)
|
self.sheerka.bind_service_method(self.NAME, self.set_debug, True)
|
||||||
self.sheerka.bind_service_method(self.inspect, False)
|
self.sheerka.bind_service_method(self.NAME, self.inspect, False)
|
||||||
self.sheerka.bind_service_method(self.get_value, False)
|
self.sheerka.bind_service_method(self.NAME, self.get_value, False)
|
||||||
self.sheerka.bind_service_method(self.get_debugger, False)
|
self.sheerka.bind_service_method(self.NAME, self.get_debugger, False)
|
||||||
self.sheerka.bind_service_method(self.reset_debug, False)
|
self.sheerka.bind_service_method(self.NAME, self.reset_debug, False)
|
||||||
self.sheerka.bind_service_method(self.set_debug_var, True)
|
self.sheerka.bind_service_method(self.NAME, self.set_debug_var, True)
|
||||||
self.sheerka.bind_service_method(self.set_debug_rule, True)
|
self.sheerka.bind_service_method(self.NAME, self.set_debug_rule, True)
|
||||||
self.sheerka.bind_service_method(self.set_debug_concept, True)
|
self.sheerka.bind_service_method(self.NAME, self.set_debug_concept, True)
|
||||||
self.sheerka.bind_service_method(self.list_debug_vars, True)
|
self.sheerka.bind_service_method(self.NAME, self.list_debug_vars, True)
|
||||||
self.sheerka.bind_service_method(self.list_debug_rules, True)
|
self.sheerka.bind_service_method(self.NAME, self.list_debug_rules, True)
|
||||||
self.sheerka.bind_service_method(self.list_debug_concepts, True)
|
self.sheerka.bind_service_method(self.NAME, self.list_debug_concepts, True)
|
||||||
self.sheerka.bind_service_method(self.register_debug_vars, True, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.register_debug_vars, True, visible=False)
|
||||||
self.sheerka.bind_service_method(self.register_debug_rules, True, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.register_debug_rules, True, visible=False)
|
||||||
self.sheerka.bind_service_method(self.register_debug_concepts, True, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.register_debug_concepts, True, visible=False)
|
||||||
|
|
||||||
# self.sheerka.bind_service_method(self.get_debug_settings, False, as_name="debug_settings")
|
# self.sheerka.bind_service_method(self.NAME,self.get_debug_settings, False, as_name="debug_settings")
|
||||||
# register what can be registered
|
# register what can be registered
|
||||||
from parsers.BnfNodeParser import BnfNodeParser
|
from parsers.BnfNodeParser import BnfNodeParser
|
||||||
from evaluators.DefConceptEvaluator import DefConceptEvaluator
|
from evaluators.DefConceptEvaluator import DefConceptEvaluator
|
||||||
@@ -349,8 +349,8 @@ class SheerkaDebugManager(BaseService):
|
|||||||
self.register_debug_vars(DefConceptEvaluator.NAME, "get_variables", "possible_vars")
|
self.register_debug_vars(DefConceptEvaluator.NAME, "get_variables", "possible_vars")
|
||||||
self.register_debug_vars(PythonEvaluator.NAME, "eval", "globals")
|
self.register_debug_vars(PythonEvaluator.NAME, "eval", "globals")
|
||||||
self.register_debug_vars(PythonEvaluator.NAME, "eval", "ret")
|
self.register_debug_vars(PythonEvaluator.NAME, "eval", "ret")
|
||||||
self.register_debug_vars("Exceptions", PythonEvaluator.NAME+"-eval", "exception")
|
self.register_debug_vars("Exceptions", PythonEvaluator.NAME + "-eval", "exception")
|
||||||
self.register_debug_vars("Exceptions", PythonEvaluator.NAME+"-eval", "trace")
|
self.register_debug_vars("Exceptions", PythonEvaluator.NAME + "-eval", "trace")
|
||||||
self.register_debug_vars(SyaNodeParser.NAME, "parse", "*")
|
self.register_debug_vars(SyaNodeParser.NAME, "parse", "*")
|
||||||
self.register_debug_vars(MultipleSuccessEvaluator.NAME, "matches", "return_values")
|
self.register_debug_vars(MultipleSuccessEvaluator.NAME, "matches", "return_values")
|
||||||
|
|
||||||
@@ -919,4 +919,3 @@ class SheerkaDebugManager(BaseService):
|
|||||||
del res["self"]
|
del res["self"]
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,11 @@ class SheerkaDump(BaseService):
|
|||||||
super().__init__(sheerka)
|
super().__init__(sheerka)
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
self.sheerka.bind_service_method(self.dump_desc, True, "old_desc") # has_side_effect 'cause concept is evaluated
|
self.sheerka.bind_service_method(self.NAME,
|
||||||
self.sheerka.bind_service_method(self.dump_sdp, False, "dump_sdp")
|
self.dump_desc,
|
||||||
|
True,
|
||||||
|
"old_desc") # has_side_effect 'cause concept is evaluated
|
||||||
|
self.sheerka.bind_service_method(self.NAME, self.dump_sdp, False, "dump_sdp")
|
||||||
|
|
||||||
def dump_desc(self, *concept_names, eval=False):
|
def dump_desc(self, *concept_names, eval=False):
|
||||||
first = True
|
first = True
|
||||||
|
|||||||
@@ -46,10 +46,10 @@ class SheerkaEvaluateConcept(BaseService):
|
|||||||
self.rule_evaluator = None
|
self.rule_evaluator = None
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
self.sheerka.bind_service_method(self.evaluate_concept, True)
|
self.sheerka.bind_service_method(self.NAME, self.evaluate_concept, True)
|
||||||
self.sheerka.bind_service_method(self.call_concept, True)
|
self.sheerka.bind_service_method(self.NAME, self.call_concept, True)
|
||||||
self.sheerka.bind_service_method(self.call_concept, False, as_name="evaluate_question")
|
self.sheerka.bind_service_method(self.NAME, self.call_concept, False, as_name="evaluate_question")
|
||||||
self.sheerka.bind_service_method(self.set_auto_eval, True)
|
self.sheerka.bind_service_method(self.NAME, self.set_auto_eval, True)
|
||||||
|
|
||||||
def initialize_deferred(self, context, is_first_time):
|
def initialize_deferred(self, context, is_first_time):
|
||||||
self.rule_evaluator = self.sheerka.services[SheerkaEvaluateRules.NAME]
|
self.rule_evaluator = self.sheerka.services[SheerkaEvaluateRules.NAME]
|
||||||
@@ -499,9 +499,7 @@ class SheerkaEvaluateConcept(BaseService):
|
|||||||
|
|
||||||
if current_prop in (ConceptParts.WHERE, ConceptParts.PRE):
|
if current_prop in (ConceptParts.WHERE, ConceptParts.PRE):
|
||||||
sub_context.protected_hints.add(BuiltinConcepts.EVAL_UNTIL_SUCCESS_REQUESTED)
|
sub_context.protected_hints.add(BuiltinConcepts.EVAL_UNTIL_SUCCESS_REQUESTED)
|
||||||
|
sub_context.protected_hints.add(BuiltinConcepts.EVALUATING_PRE_OR_WHERE_CLAUSE)
|
||||||
if current_prop == ConceptParts.WHERE:
|
|
||||||
sub_context.protected_hints.add(BuiltinConcepts.EVAL_QUESTION_REQUESTED)
|
|
||||||
|
|
||||||
# when it's a concept, evaluate it
|
# when it's a concept, evaluate it
|
||||||
if isinstance(to_resolve, Concept) and \
|
if isinstance(to_resolve, Concept) and \
|
||||||
@@ -642,6 +640,9 @@ class SheerkaEvaluateConcept(BaseService):
|
|||||||
if context.sheerka.isa(concept, context.sheerka.new(BuiltinConcepts.AUTO_EVAL)):
|
if context.sheerka.isa(concept, context.sheerka.new(BuiltinConcepts.AUTO_EVAL)):
|
||||||
sub_context.protected_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
sub_context.protected_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||||
|
|
||||||
|
if context.in_context(BuiltinConcepts.EVALUATING_PRE_OR_WHERE_CLAUSE):
|
||||||
|
sub_context.protected_hints.add(BuiltinConcepts.EVAL_QUESTION_REQUESTED)
|
||||||
|
|
||||||
sub_context.add_to_short_term_memory(CURRENT_OBJ, concept)
|
sub_context.add_to_short_term_memory(CURRENT_OBJ, concept)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -764,6 +765,13 @@ class SheerkaEvaluateConcept(BaseService):
|
|||||||
:param kwargs:
|
:param kwargs:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
if concept.get_hints().use_copy or not concept.get_hints().is_instance:
|
||||||
|
concept = concept.copy()
|
||||||
|
concept.get_hints().use_copy = False
|
||||||
|
concept.get_hints().is_instance = True
|
||||||
|
concept.get_hints().is_evaluated = False # force evaluation
|
||||||
|
|
||||||
|
# TODO : update the variables before calling the concept
|
||||||
|
|
||||||
evaluated = self.evaluate_concept(context, concept)
|
evaluated = self.evaluate_concept(context, concept)
|
||||||
if self.sheerka.has_error(context, evaluated):
|
if self.sheerka.has_error(context, evaluated):
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ class SheerkaEvaluateRules(BaseService):
|
|||||||
self.network = ReteNetwork()
|
self.network = ReteNetwork()
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
self.sheerka.bind_service_method(self.evaluate_format_rules, False, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.evaluate_format_rules, False, visible=False)
|
||||||
self.sheerka.bind_service_method(self.evaluate_exec_rules, False, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.evaluate_exec_rules, False, visible=False)
|
||||||
self.reset_evaluators()
|
self.reset_evaluators()
|
||||||
self.sheerka.subscribe(EVENT_RULE_CREATED, self.on_rule_created)
|
self.sheerka.subscribe(EVENT_RULE_CREATED, self.on_rule_created)
|
||||||
self.sheerka.subscribe(EVENT_RULE_DELETED, self.on_rule_deleted)
|
self.sheerka.subscribe(EVENT_RULE_DELETED, self.on_rule_deleted)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from threading import RLock
|
from threading import RLock
|
||||||
|
|
||||||
from core.global_symbols import NotFound
|
from core.global_symbols import NotFound
|
||||||
from core.sheerka.services.sheerka_service import BaseService
|
from core.sheerka.services.sheerka_service import BaseService
|
||||||
|
|
||||||
@@ -16,8 +17,8 @@ class SheerkaEventManager(BaseService):
|
|||||||
self.subscribers = {}
|
self.subscribers = {}
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
self.sheerka.bind_service_method(self.subscribe, True, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.subscribe, True, visible=False)
|
||||||
self.sheerka.bind_service_method(self.publish, True, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.publish, True, visible=False)
|
||||||
|
|
||||||
def save_state(self, context):
|
def save_state(self, context):
|
||||||
with self._lock:
|
with self._lock:
|
||||||
|
|||||||
@@ -221,12 +221,12 @@ class SheerkaExecute(BaseService):
|
|||||||
self.rules_eval_service = None
|
self.rules_eval_service = None
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
self.sheerka.bind_service_method(self.execute, True, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.execute, True, visible=False)
|
||||||
self.sheerka.bind_service_method(self.execute_rules, True, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.execute_rules, True, visible=False)
|
||||||
self.sheerka.bind_service_method(self.parse_unrecognized, False, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.parse_unrecognized, False, visible=False)
|
||||||
self.sheerka.bind_service_method(self.parse_function, False, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.parse_function, False, visible=False)
|
||||||
self.sheerka.bind_service_method(self.parse_python, False, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.parse_python, False, visible=False)
|
||||||
self.sheerka.bind_service_method(self.parse_expression, False, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.parse_expression, False, visible=False)
|
||||||
|
|
||||||
self.reset_registered_evaluators()
|
self.reset_registered_evaluators()
|
||||||
self.reset_registered_parsers()
|
self.reset_registered_parsers()
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ class SheerkaHasAManager(BaseService):
|
|||||||
super().__init__(sheerka, order=22)
|
super().__init__(sheerka, order=22)
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
self.sheerka.bind_service_method(self.set_hasa, True)
|
self.sheerka.bind_service_method(self.NAME, self.set_hasa, True)
|
||||||
self.sheerka.bind_service_method(self.hasa, True)
|
self.sheerka.bind_service_method(self.NAME, self.hasa, True)
|
||||||
|
|
||||||
def set_hasa(self, context, concept_a, concept_b):
|
def set_hasa(self, context, concept_a, concept_b):
|
||||||
"""
|
"""
|
||||||
@@ -37,8 +37,13 @@ class SheerkaHasAManager(BaseService):
|
|||||||
concept=concept_a))
|
concept=concept_a))
|
||||||
|
|
||||||
merged_concepts = merge_sets(concept_a.get_prop(BuiltinConcepts.HASA), {concept_b})
|
merged_concepts = merge_sets(concept_a.get_prop(BuiltinConcepts.HASA), {concept_b})
|
||||||
|
|
||||||
|
if context.in_context(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED):
|
||||||
to_add = {"props": {BuiltinConcepts.HASA: merged_concepts}}
|
to_add = {"props": {BuiltinConcepts.HASA: merged_concepts}}
|
||||||
return self.sheerka.modify_concept(context, concept_a, to_add, modify_source=True)
|
return self.sheerka.modify_concept(context, concept_a, to_add, modify_source=True)
|
||||||
|
else:
|
||||||
|
concept_a.set_prop(BuiltinConcepts.HASA, merged_concepts)
|
||||||
|
return self.sheerka.ret(self.NAME, True, concept_a)
|
||||||
|
|
||||||
def hasa(self, concept_a, concept_b):
|
def hasa(self, concept_a, concept_b):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ class SheerkaIsAManager(BaseService):
|
|||||||
super().__init__(sheerka, order=21)
|
super().__init__(sheerka, order=21)
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
self.sheerka.bind_service_method(self.set_isa, True)
|
self.sheerka.bind_service_method(self.NAME, self.set_isa, True)
|
||||||
self.sheerka.bind_service_method(self.get_set_elements, True) # concepts are evaluated
|
self.sheerka.bind_service_method(self.NAME, self.get_set_elements, True) # concepts are evaluated
|
||||||
self.sheerka.bind_service_method(self.add_concept_to_set, True)
|
self.sheerka.bind_service_method(self.NAME, self.add_concept_to_set, True)
|
||||||
self.sheerka.bind_service_method(self.isinset, False)
|
self.sheerka.bind_service_method(self.NAME, self.isinset, False)
|
||||||
self.sheerka.bind_service_method(self.isa, False)
|
self.sheerka.bind_service_method(self.NAME, self.isa, False)
|
||||||
self.sheerka.bind_service_method(self.isaset, True) # concept is evaluated, need to change the code
|
self.sheerka.bind_service_method(self.NAME, self.isaset, True) # concept is evaluated, need to change the code
|
||||||
|
|
||||||
cache = SetCache().auto_configure(self.CONCEPTS_GROUPS_ENTRY)
|
cache = SetCache().auto_configure(self.CONCEPTS_GROUPS_ENTRY)
|
||||||
self.sheerka.om.register_cache(self.CONCEPTS_GROUPS_ENTRY, cache)
|
self.sheerka.om.register_cache(self.CONCEPTS_GROUPS_ENTRY, cache)
|
||||||
@@ -53,6 +53,8 @@ class SheerkaIsAManager(BaseService):
|
|||||||
# KSI 20200709 add the concept, not its 'id' or 'key'
|
# KSI 20200709 add the concept, not its 'id' or 'key'
|
||||||
# It will allow conditions handling if concept set has its WHERE or PRE set to something
|
# It will allow conditions handling if concept set has its WHERE or PRE set to something
|
||||||
new_concept_set = merge_sets(concept.get_prop(BuiltinConcepts.ISA), {concept_set})
|
new_concept_set = merge_sets(concept.get_prop(BuiltinConcepts.ISA), {concept_set})
|
||||||
|
|
||||||
|
if context.in_context(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED):
|
||||||
to_add = {"props": {BuiltinConcepts.ISA: new_concept_set}}
|
to_add = {"props": {BuiltinConcepts.ISA: new_concept_set}}
|
||||||
res = self.sheerka.modify_concept(context, concept, to_add, modify_source=True)
|
res = self.sheerka.modify_concept(context, concept, to_add, modify_source=True)
|
||||||
if not res.status:
|
if not res.status:
|
||||||
@@ -61,8 +63,10 @@ class SheerkaIsAManager(BaseService):
|
|||||||
concept = res.body.body
|
concept = res.body.body
|
||||||
|
|
||||||
res = self.add_concept_to_set(context, concept, concept_set)
|
res = self.add_concept_to_set(context, concept, concept_set)
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
else:
|
||||||
|
concept.set_prop(BuiltinConcepts.ISA, new_concept_set)
|
||||||
|
return self.sheerka.ret(self.NAME, True, concept)
|
||||||
|
|
||||||
def add_concept_to_set(self, context, concept, concept_set):
|
def add_concept_to_set(self, context, concept, concept_set):
|
||||||
"""
|
"""
|
||||||
@@ -270,7 +274,7 @@ class SheerkaIsAManager(BaseService):
|
|||||||
sub_context.protected_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
sub_context.protected_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||||
errors = []
|
errors = []
|
||||||
for element_id in ids:
|
for element_id in ids:
|
||||||
concept = self.sheerka.fast_resolve((None, element_id))
|
concept = self.sheerka.fast_resolve((None, element_id), force_instance=True)
|
||||||
if concept:
|
if concept:
|
||||||
if len(concept.get_metadata().variables) == 0:
|
if len(concept.get_metadata().variables) == 0:
|
||||||
evaluated = self.sheerka.evaluate_concept(sub_context, concept)
|
evaluated = self.sheerka.evaluate_concept(sub_context, concept)
|
||||||
|
|||||||
@@ -36,21 +36,23 @@ class SheerkaMemory(BaseService):
|
|||||||
super().__init__(sheerka, order=13)
|
super().__init__(sheerka, order=13)
|
||||||
self.short_term_objects = FastCache()
|
self.short_term_objects = FastCache()
|
||||||
self.registration = {}
|
self.registration = {}
|
||||||
|
self.enable_memory_registration = True
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
self.sheerka.bind_service_method(self.get_from_short_term_memory, False, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.get_from_short_term_memory, False, visible=False)
|
||||||
self.sheerka.bind_service_method(self.get_all_short_term_memory, False, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.get_all_short_term_memory, False, visible=False)
|
||||||
self.sheerka.bind_service_method(self.add_to_short_term_memory, True, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.add_to_short_term_memory, True, visible=False)
|
||||||
self.sheerka.bind_service_method(self.remove_context, True, as_name="clear_short_term_memory", visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.remove_context, True, as_name="clear_short_term_memory",
|
||||||
self.sheerka.bind_service_method(self.add_to_memory, True)
|
visible=False)
|
||||||
self.sheerka.bind_service_method(self.add_many_to_short_term_memory, True, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.add_to_memory, True)
|
||||||
self.sheerka.bind_service_method(self.get_from_memory, False)
|
self.sheerka.bind_service_method(self.NAME, self.add_many_to_short_term_memory, True, visible=False)
|
||||||
self.sheerka.bind_service_method(self.get_last_from_memory, False)
|
self.sheerka.bind_service_method(self.NAME, self.get_from_memory, False)
|
||||||
self.sheerka.bind_service_method(self.register_object, True, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.get_last_from_memory, False)
|
||||||
self.sheerka.bind_service_method(self.unregister_object, True, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.register_object, True, visible=False)
|
||||||
self.sheerka.bind_service_method(self.commit_registered_objects, True, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.unregister_object, True, visible=False)
|
||||||
self.sheerka.bind_service_method(self.memory, False)
|
self.sheerka.bind_service_method(self.NAME, self.commit_registered_objects, True, visible=False)
|
||||||
self.sheerka.bind_service_method(self.mem, False)
|
self.sheerka.bind_service_method(self.NAME, self.memory, False)
|
||||||
|
self.sheerka.bind_service_method(self.NAME, self.mem, False)
|
||||||
|
|
||||||
cache = ListIfNeededCache().auto_configure(self.OBJECTS_ENTRY)
|
cache = ListIfNeededCache().auto_configure(self.OBJECTS_ENTRY)
|
||||||
self.sheerka.om.register_cache(self.OBJECTS_ENTRY, cache, persist=True, use_ref=True)
|
self.sheerka.om.register_cache(self.OBJECTS_ENTRY, cache, persist=True, use_ref=True)
|
||||||
@@ -187,7 +189,7 @@ class SheerkaMemory(BaseService):
|
|||||||
:param concept:
|
:param concept:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
if self.sheerka.during_initialisation or self.sheerka.during_restore:
|
if not self.enable_memory_registration or self.sheerka.during_initialisation or self.sheerka.during_restore:
|
||||||
return
|
return
|
||||||
self.registration[key] = concept
|
self.registration[key] = concept
|
||||||
|
|
||||||
@@ -220,6 +222,8 @@ class SheerkaMemory(BaseService):
|
|||||||
:param name:
|
:param name:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
self.enable_memory_registration = False
|
||||||
|
try:
|
||||||
name_to_use = name.name if isinstance(name, Concept) else name
|
name_to_use = name.name if isinstance(name, Concept) else name
|
||||||
self.unregister_object(context, name_to_use)
|
self.unregister_object(context, name_to_use)
|
||||||
|
|
||||||
@@ -228,6 +232,11 @@ class SheerkaMemory(BaseService):
|
|||||||
if obj is not NotFound:
|
if obj is not NotFound:
|
||||||
return obj.obj
|
return obj.obj
|
||||||
|
|
||||||
|
# only filter if it's a valid predicate
|
||||||
|
from parsers.BaseExpressionParser import VariableNode, NameExprNode
|
||||||
|
parsed_ret_val = self.sheerka.parse_expression(context, name_to_use, auto_compile=False)
|
||||||
|
if parsed_ret_val.status and not isinstance(parsed_ret_val.body.body, (VariableNode, NameExprNode)):
|
||||||
|
|
||||||
all_objects = self.sheerka.om.list(SheerkaMemory.OBJECTS_ENTRY) # not always a list of list
|
all_objects = self.sheerka.om.list(SheerkaMemory.OBJECTS_ENTRY) # not always a list of list
|
||||||
all_objects_copy = [] # to transform into list of list
|
all_objects_copy = [] # to transform into list of list
|
||||||
for obj in all_objects:
|
for obj in all_objects:
|
||||||
@@ -253,6 +262,8 @@ class SheerkaMemory(BaseService):
|
|||||||
return res[0] # only the first, as it should have a better timestamp
|
return res[0] # only the first, as it should have a better timestamp
|
||||||
|
|
||||||
return self.sheerka.new(BuiltinConcepts.NOT_FOUND, body={"#name": name_to_use})
|
return self.sheerka.new(BuiltinConcepts.NOT_FOUND, body={"#name": name_to_use})
|
||||||
|
finally:
|
||||||
|
self.enable_memory_registration = True
|
||||||
|
|
||||||
def mem(self):
|
def mem(self):
|
||||||
keys = sorted([k for k in self.sheerka.om.list(SheerkaMemory.OBJECTS_ENTRY)])
|
keys = sorted([k for k in self.sheerka.om.list(SheerkaMemory.OBJECTS_ENTRY)])
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class SheerkaOut(BaseService):
|
|||||||
self.out_visitors = [ConsoleVisitor(expand_mode="all_but_first")]
|
self.out_visitors = [ConsoleVisitor(expand_mode="all_but_first")]
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
self.sheerka.bind_service_method(self.process_return_values, False)
|
self.sheerka.bind_service_method(self.NAME, self.process_return_values, False)
|
||||||
self.sheerka.register_debug_vars("Visitor", "create_out_tree", "Exception")
|
self.sheerka.register_debug_vars("Visitor", "create_out_tree", "Exception")
|
||||||
self.sheerka.register_debug_vars(SheerkaOut.NAME, "create_out_tree", "out_tree")
|
self.sheerka.register_debug_vars(SheerkaOut.NAME, "create_out_tree", "out_tree")
|
||||||
|
|
||||||
|
|||||||
@@ -26,13 +26,13 @@ class SheerkaQueryManager(BaseService):
|
|||||||
self.rule_evaluator = None
|
self.rule_evaluator = None
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
self.sheerka.bind_service_method(self.filter_objects, False)
|
self.sheerka.bind_service_method(self.NAME, self.filter_objects, False)
|
||||||
self.sheerka.bind_service_method(self.select_objects, False)
|
self.sheerka.bind_service_method(self.NAME, self.select_objects, False)
|
||||||
self.sheerka.bind_service_method(self.collect_attributes, False)
|
self.sheerka.bind_service_method(self.NAME, self.collect_attributes, False)
|
||||||
|
|
||||||
self.sheerka.bind_service_method(self.filter_objects, False, as_name="pipe_where")
|
self.sheerka.bind_service_method(self.NAME, self.filter_objects, False, as_name="pipe_where")
|
||||||
self.sheerka.bind_service_method(self.select_objects, False, as_name="pipe_select")
|
self.sheerka.bind_service_method(self.NAME, self.select_objects, False, as_name="pipe_select")
|
||||||
self.sheerka.bind_service_method(self.collect_attributes, False, as_name="pipe_props")
|
self.sheerka.bind_service_method(self.NAME, self.collect_attributes, False, as_name="pipe_props")
|
||||||
|
|
||||||
self.sheerka.register_debug_vars(SheerkaQueryManager.NAME, "filter_objects", "query")
|
self.sheerka.register_debug_vars(SheerkaQueryManager.NAME, "filter_objects", "query")
|
||||||
|
|
||||||
@@ -59,12 +59,13 @@ class SheerkaQueryManager(BaseService):
|
|||||||
if k == "__type":
|
if k == "__type":
|
||||||
conditions.append(f"get_type(self) == {current_variable_name}")
|
conditions.append(f"get_type(self) == {current_variable_name}")
|
||||||
|
|
||||||
elif k == "atomic_def":
|
|
||||||
conditions.append(f"atomic_def(self) == {current_variable_name}")
|
|
||||||
|
|
||||||
elif k in ("__self", "_"):
|
elif k in ("__self", "_"):
|
||||||
conditions.append(f"self == {current_variable_name}")
|
conditions.append(f"self == {current_variable_name}")
|
||||||
|
|
||||||
|
elif k.endswith("_contains"):
|
||||||
|
prop_name = k[:-9]
|
||||||
|
conditions.append(f"{current_variable_name} in self.{prop_name}")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
conditions.append(f"self.{k} == {current_variable_name}")
|
conditions.append(f"self.{k} == {current_variable_name}")
|
||||||
|
|
||||||
@@ -91,6 +92,7 @@ class SheerkaQueryManager(BaseService):
|
|||||||
objects = objects.body
|
objects = objects.body
|
||||||
|
|
||||||
debugger.debug_entering(nb_objects=len(objects), predicate=predicate, **kwargs)
|
debugger.debug_entering(nb_objects=len(objects), predicate=predicate, **kwargs)
|
||||||
|
|
||||||
local_namespace = {}
|
local_namespace = {}
|
||||||
query_by_kwargs = self.get_query_by_kwargs(local_namespace, **kwargs)
|
query_by_kwargs = self.get_query_by_kwargs(local_namespace, **kwargs)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
from core.builtin_concepts import BuiltinConcepts
|
from core.builtin_concepts import BuiltinConcepts
|
||||||
from core.concept import Concept
|
|
||||||
from core.sheerka.services.sheerka_service import BaseService
|
from core.sheerka.services.sheerka_service import BaseService
|
||||||
|
|
||||||
|
|
||||||
@@ -10,7 +9,7 @@ class SheerkaQuestion(BaseService):
|
|||||||
super().__init__(sheerka)
|
super().__init__(sheerka)
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
self.sheerka.bind_service_method(self.is_question, False)
|
self.sheerka.bind_service_method(self.NAME, self.is_question, False)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_question(context):
|
def is_question(context):
|
||||||
|
|||||||
@@ -31,14 +31,15 @@ class SheerkaResultManager(BaseService):
|
|||||||
self.state_vars = ["last_created_concept_id", "last_error_event_id"]
|
self.state_vars = ["last_created_concept_id", "last_error_event_id"]
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
self.sheerka.bind_service_method(self.get_results_by_digest, True) # digest is recorded
|
self.sheerka.bind_service_method(self.NAME, self.get_results_by_digest, True) # digest is recorded
|
||||||
self.sheerka.bind_service_method(self.get_results_by_command, True) # digest is recorded
|
self.sheerka.bind_service_method(self.NAME, self.get_results_by_command, True) # digest is recorded
|
||||||
self.sheerka.bind_service_method(self.get_last_results, True) # digest is recorded
|
self.sheerka.bind_service_method(self.NAME, self.get_last_results, True) # digest is recorded
|
||||||
self.sheerka.bind_service_method(self.get_results, False)
|
self.sheerka.bind_service_method(self.NAME, self.get_results, False)
|
||||||
self.sheerka.bind_service_method(self.get_execution_item, False)
|
self.sheerka.bind_service_method(self.NAME, self.get_execution_item, False)
|
||||||
self.sheerka.bind_service_method(self.get_last_return_value, False, as_name="last_ret")
|
self.sheerka.bind_service_method(self.NAME, self.get_last_return_value, False, as_name="last_ret")
|
||||||
self.sheerka.bind_service_method(self.get_last_created_concept, False, as_name="last_created_concept")
|
self.sheerka.bind_service_method(self.NAME, self.get_last_created_concept, False,
|
||||||
self.sheerka.bind_service_method(self.get_last_error, False, as_name="last_err")
|
as_name="last_created_concept")
|
||||||
|
self.sheerka.bind_service_method(self.NAME, self.get_last_error, False, as_name="last_err")
|
||||||
|
|
||||||
self.sheerka.subscribe(EVENT_USER_INPUT_EVALUATED, self.user_input_evaluated)
|
self.sheerka.subscribe(EVENT_USER_INPUT_EVALUATED, self.user_input_evaluated)
|
||||||
self.sheerka.subscribe(EVENT_CONCEPT_CREATED, self.new_concept_created)
|
self.sheerka.subscribe(EVENT_CONCEPT_CREATED, self.new_concept_created)
|
||||||
@@ -77,6 +78,7 @@ class SheerkaResultManager(BaseService):
|
|||||||
"""
|
"""
|
||||||
if len(kwargs) == 0:
|
if len(kwargs) == 0:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
res = []
|
res = []
|
||||||
if "filter" in kwargs:
|
if "filter" in kwargs:
|
||||||
res.append(kwargs["filter"])
|
res.append(kwargs["filter"])
|
||||||
@@ -90,6 +92,10 @@ class SheerkaResultManager(BaseService):
|
|||||||
v = '"' + v.translate(str.maketrans({'"': r'\"'})) + '"'
|
v = '"' + v.translate(str.maketrans({'"': r'\"'})) + '"'
|
||||||
res.append(f"{k} == {v}")
|
res.append(f"{k} == {v}")
|
||||||
predicate = " and ".join(res)
|
predicate = " and ".join(res)
|
||||||
|
|
||||||
|
if predicate.strip() == "":
|
||||||
|
return None
|
||||||
|
|
||||||
return compile(ast.parse(predicate, mode="eval"), "<SheerkaResultManager.get_predicate>", mode="eval")
|
return compile(ast.parse(predicate, mode="eval"), "<SheerkaResultManager.get_predicate>", mode="eval")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -380,15 +386,16 @@ class SheerkaResultManager(BaseService):
|
|||||||
|
|
||||||
folder = os.getenv(SHEERKA_BACKUP_FOLDER)
|
folder = os.getenv(SHEERKA_BACKUP_FOLDER)
|
||||||
if folder is None:
|
if folder is None:
|
||||||
print(f"{CCM['red']}Cannot backup command. Backup folder (env SHEERKA_BACKUP_FOLDER) is not defined.{CCM['reset']}")
|
print(
|
||||||
|
f"{CCM['red']}Cannot backup command. Backup folder (env SHEERKA_BACKUP_FOLDER) is not defined.{CCM['reset']}")
|
||||||
return
|
return
|
||||||
|
|
||||||
file = os.getenv(SHEERKA_BACKUP_FILE)
|
file = os.getenv(SHEERKA_BACKUP_FILE)
|
||||||
if file is None:
|
if file is None:
|
||||||
print(f"{CCM['red']}Cannot backup command. Backup file (env SHEERKA_BACKUP_FILE) is not defined.{CCM['reset']}")
|
print(
|
||||||
|
f"{CCM['red']}Cannot backup command. Backup file (env SHEERKA_BACKUP_FILE) is not defined.{CCM['reset']}")
|
||||||
return
|
return
|
||||||
|
|
||||||
full_path = os.path.join(folder, file)
|
full_path = os.path.join(folder, file)
|
||||||
with open(full_path, "a") as f:
|
with open(full_path, "a") as f:
|
||||||
f.write(f"{execution_context.event.message}\n")
|
f.write(f"{execution_context.event.message}\n")
|
||||||
|
|
||||||
|
|||||||
@@ -82,13 +82,13 @@ class SheerkaRuleManager(BaseService):
|
|||||||
self.expression_parser = LogicalOperatorParser()
|
self.expression_parser = LogicalOperatorParser()
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
self.sheerka.bind_service_method(self.create_new_rule, True, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.create_new_rule, True, visible=False)
|
||||||
self.sheerka.bind_service_method(self.remove_rule, True)
|
self.sheerka.bind_service_method(self.NAME, self.remove_rule, True)
|
||||||
self.sheerka.bind_service_method(self.get_rule_by_id, False)
|
self.sheerka.bind_service_method(self.NAME, self.get_rule_by_id, False)
|
||||||
self.sheerka.bind_service_method(self.get_rule_by_name, False)
|
self.sheerka.bind_service_method(self.NAME, self.get_rule_by_name, False)
|
||||||
self.sheerka.bind_service_method(self.get_format_rules, False, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.get_format_rules, False, visible=False)
|
||||||
self.sheerka.bind_service_method(self.get_exec_rules, False, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.get_exec_rules, False, visible=False)
|
||||||
self.sheerka.bind_service_method(self.resolve_rule, False, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.resolve_rule, False, visible=False)
|
||||||
|
|
||||||
cache = Cache().auto_configure(self.FORMAT_RULE_ENTRY)
|
cache = Cache().auto_configure(self.FORMAT_RULE_ENTRY)
|
||||||
self.sheerka.om.register_cache(self.FORMAT_RULE_ENTRY, cache, True, True)
|
self.sheerka.om.register_cache(self.FORMAT_RULE_ENTRY, cache, True, True)
|
||||||
|
|||||||
@@ -53,14 +53,14 @@ class SheerkaVariableManager(BaseService):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
self.sheerka.bind_service_method(self.record_var, True, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.record_var, True, visible=False)
|
||||||
self.sheerka.bind_service_method(self.load_var, False, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.load_var, False, visible=False)
|
||||||
self.sheerka.bind_service_method(self.record_internal_var, True, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.record_internal_var, True, visible=False)
|
||||||
self.sheerka.bind_service_method(self.load_internal_var, False, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.load_internal_var, False, visible=False)
|
||||||
self.sheerka.bind_service_method(self.delete_var, True, visible=False)
|
self.sheerka.bind_service_method(self.NAME, self.delete_var, True, visible=False)
|
||||||
self.sheerka.bind_service_method(self.set_var, True)
|
self.sheerka.bind_service_method(self.NAME, self.set_var, True)
|
||||||
self.sheerka.bind_service_method(self.get_var, False)
|
self.sheerka.bind_service_method(self.NAME, self.get_var, False)
|
||||||
self.sheerka.bind_service_method(self.list_vars, False)
|
self.sheerka.bind_service_method(self.NAME, self.list_vars, False)
|
||||||
|
|
||||||
cache = Cache().auto_configure(self.VARIABLES_ENTRY)
|
cache = Cache().auto_configure(self.VARIABLES_ENTRY)
|
||||||
self.sheerka.om.register_cache(self.VARIABLES_ENTRY, cache, True, True)
|
self.sheerka.om.register_cache(self.VARIABLES_ENTRY, cache, True, True)
|
||||||
|
|||||||
+46
-8
@@ -327,6 +327,12 @@ def merge_dictionaries(a, b):
|
|||||||
|
|
||||||
|
|
||||||
def merge_sets(a, b):
|
def merge_sets(a, b):
|
||||||
|
"""
|
||||||
|
Merge that can handle None
|
||||||
|
:param a:
|
||||||
|
:param b:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
if a is None and b is None:
|
if a is None and b is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -494,7 +500,7 @@ def unstr_concept(concept_repr, prefix='c:'):
|
|||||||
"""
|
"""
|
||||||
if concept_repr is like :c:key:id:
|
if concept_repr is like :c:key:id:
|
||||||
return the key and the id
|
return the key and the id
|
||||||
>>> assert unstr_concept("c:key:") == "key"
|
>>> assert unstr_concept("c:key:") == ("key", None)
|
||||||
>>> assert unstr_concept("c:key|id:") == ("key", "id")
|
>>> assert unstr_concept("c:key|id:") == ("key", "id")
|
||||||
>>> assert unstr_concept("c:|id:") == ("None", "id")
|
>>> assert unstr_concept("c:|id:") == ("None", "id")
|
||||||
>>> assert unstr_concept("c:key|:") == ("key", "None")
|
>>> assert unstr_concept("c:key|:") == ("key", "None")
|
||||||
@@ -515,28 +521,30 @@ def unstr_concept(concept_repr, prefix='c:'):
|
|||||||
key = ""
|
key = ""
|
||||||
while i < length:
|
while i < length:
|
||||||
c = concept_repr[i]
|
c = concept_repr[i]
|
||||||
|
i += 1
|
||||||
if c in (":", "|"):
|
if c in (":", "|"):
|
||||||
break
|
break
|
||||||
key += c
|
key += c
|
||||||
i += 1
|
|
||||||
else:
|
else:
|
||||||
return None, None
|
return None, None
|
||||||
|
|
||||||
if c == ":":
|
if c == ":":
|
||||||
return key if key != "" else None, None
|
return key if key != "" and i == length else None, None
|
||||||
|
|
||||||
i += 1
|
c_id = ""
|
||||||
id = ""
|
|
||||||
while i < length:
|
while i < length:
|
||||||
c = concept_repr[i]
|
c = concept_repr[i]
|
||||||
|
i += 1
|
||||||
if c == ":":
|
if c == ":":
|
||||||
break
|
break
|
||||||
id += c
|
c_id += c
|
||||||
i += 1
|
|
||||||
else:
|
else:
|
||||||
return None, None
|
return None, None
|
||||||
|
|
||||||
return key if key != "" else None, id if id != "" else None
|
if i != length:
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
return key if key != "" else None, c_id if c_id != "" else None
|
||||||
|
|
||||||
|
|
||||||
def encode_concept(t, wrapper="C"):
|
def encode_concept(t, wrapper="C"):
|
||||||
@@ -682,6 +690,36 @@ def flatten(list_of_lists):
|
|||||||
return functools.reduce(operator.iconcat, list_of_lists, [])
|
return functools.reduce(operator.iconcat, list_of_lists, [])
|
||||||
|
|
||||||
|
|
||||||
|
def replace_after(lst: list, start_item, new_items: list):
|
||||||
|
"""
|
||||||
|
given a list 'lst', replace all items (starting with 'item') with the new_items
|
||||||
|
>>> my_new_items =["alpha", "beta", "gamma"]
|
||||||
|
>>>
|
||||||
|
>>> my_list1 = ["a", "b", "c", "d"]
|
||||||
|
>>> replace_after(my_list1, "c", new_items)
|
||||||
|
>>> assert my_list1 == ["a", "b", "alpha", "beta", "gamma"]
|
||||||
|
>>>
|
||||||
|
>>> my_list2 = ["a", "b", "c", "d"]
|
||||||
|
>>> replace_after(my_list2, "a", new_items)
|
||||||
|
>>> assert my_list2 == ["alpha", "beta", "gamma"]
|
||||||
|
>>> # replace_after(lst, "x", new_items) raises a KeyError
|
||||||
|
|
||||||
|
:param lst:
|
||||||
|
:param start_item:
|
||||||
|
:param new_items:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
for i, current in enumerate(lst):
|
||||||
|
if current == start_item:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
raise KeyError(start_item)
|
||||||
|
|
||||||
|
del lst[i:]
|
||||||
|
lst.extend(new_items)
|
||||||
|
return lst
|
||||||
|
|
||||||
|
|
||||||
def get_text_from_tokens(tokens, custom_switcher=None, tracker=None):
|
def get_text_from_tokens(tokens, custom_switcher=None, tracker=None):
|
||||||
"""
|
"""
|
||||||
Create the source code, from the list of token
|
Create the source code, from the list of token
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class ExpressionEvaluator(OneReturnValueEvaluator):
|
|||||||
success = False
|
success = False
|
||||||
|
|
||||||
with context.push(BuiltinConcepts.EXEC_CODE, return_value.value.value.source) as sub_context:
|
with context.push(BuiltinConcepts.EXEC_CODE, return_value.value.value.source) as sub_context:
|
||||||
# sub condition is created only to add a namespace
|
# sub_context is created only to add a namespace
|
||||||
|
|
||||||
requested_vars = set()
|
requested_vars = set()
|
||||||
for c in conditions:
|
for c in conditions:
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
from core.builtin_concepts import BuiltinConcepts
|
||||||
|
from evaluators.BaseEvaluator import OneReturnValueEvaluator
|
||||||
|
|
||||||
|
|
||||||
|
class PrepareEvalGlobalTruthEvaluator(OneReturnValueEvaluator):
|
||||||
|
"""
|
||||||
|
To recognize when the user input is a global truth
|
||||||
|
"""
|
||||||
|
|
||||||
|
NAME = "PrepareEvalGlobalTruth"
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super().__init__(self.NAME, [BuiltinConcepts.BEFORE_PARSING], 90)
|
||||||
|
self.inner_text = None
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self.inner_text = None
|
||||||
|
|
||||||
|
def matches(self, context, return_value):
|
||||||
|
if not (return_value.status and
|
||||||
|
context.sheerka.isinstance(return_value.body, BuiltinConcepts.USER_INPUT) and
|
||||||
|
isinstance(return_value.body.body, str)):
|
||||||
|
return False
|
||||||
|
|
||||||
|
text = return_value.body.body.strip()
|
||||||
|
if not (text.startswith("global_truth(") and text.endswith(")")):
|
||||||
|
return False
|
||||||
|
|
||||||
|
self.inner_text = text[13:-1].strip()
|
||||||
|
if self.inner_text == "":
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def eval(self, context, return_value):
|
||||||
|
sheerka = context.sheerka
|
||||||
|
|
||||||
|
new_text_to_parse = sheerka.ret(
|
||||||
|
self.name,
|
||||||
|
True, sheerka.new(BuiltinConcepts.USER_INPUT, body=self.inner_text, user_name=context.event.user_id))
|
||||||
|
|
||||||
|
root = context.get_parents(lambda ec: ec.action in (BuiltinConcepts.EVALUATING_CONCEPT,
|
||||||
|
BuiltinConcepts.PROCESS_INPUT))
|
||||||
|
root = root[0] if root else context
|
||||||
|
root.add_to_protected_hints(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED)
|
||||||
|
root.add_to_protected_hints(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||||
|
root.add_to_protected_hints(BuiltinConcepts.RETURN_BODY_REQUESTED)
|
||||||
|
|
||||||
|
return new_text_to_parse
|
||||||
@@ -2,6 +2,7 @@ from core.builtin_concepts import BuiltinConcepts
|
|||||||
from core.builtin_helpers import resolve_ambiguity
|
from core.builtin_helpers import resolve_ambiguity
|
||||||
from core.concept import Concept
|
from core.concept import Concept
|
||||||
from evaluators.BaseEvaluator import AllReturnValuesEvaluator
|
from evaluators.BaseEvaluator import AllReturnValuesEvaluator
|
||||||
|
from parsers.BaseNodeParser import ConceptNode
|
||||||
|
|
||||||
|
|
||||||
class ResolveAmbiguityEvaluator(AllReturnValuesEvaluator):
|
class ResolveAmbiguityEvaluator(AllReturnValuesEvaluator):
|
||||||
@@ -24,10 +25,12 @@ class ResolveAmbiguityEvaluator(AllReturnValuesEvaluator):
|
|||||||
# If they share the same source, that means that there are multiple results for one ParserInput
|
# If they share the same source, that means that there are multiple results for one ParserInput
|
||||||
self.sources = {}
|
self.sources = {}
|
||||||
success = False
|
success = False
|
||||||
for ret in [ret for ret in return_values if ret.status]:
|
for ret in [ret for ret in return_values if
|
||||||
|
ret.status and context.sheerka.isinstance(ret.body, BuiltinConcepts.PARSER_RESULT)]:
|
||||||
source = self.get_source(context, ret)
|
source = self.get_source(context, ret)
|
||||||
|
concept_is_instance = self.get_has_concept_instance(ret)
|
||||||
|
|
||||||
if source:
|
if source and concept_is_instance:
|
||||||
self.sources.setdefault(source, []).append(ret)
|
self.sources.setdefault(source, []).append(ret)
|
||||||
|
|
||||||
if len(self.sources[source]) > 1:
|
if len(self.sources[source]) > 1:
|
||||||
@@ -39,17 +42,26 @@ class ResolveAmbiguityEvaluator(AllReturnValuesEvaluator):
|
|||||||
ret = []
|
ret = []
|
||||||
|
|
||||||
for ret_vals in self.sources.values():
|
for ret_vals in self.sources.values():
|
||||||
parser_results = {id(r.body.body): r.body for r in ret_vals}
|
presults_concepts_map = {id(self.get_concept(r)): r.body for r in ret_vals}
|
||||||
resolved = resolve_ambiguity(context, [r.body.body for r in ret_vals])
|
resolved = resolve_ambiguity(context, [self.get_concept(r) for r in ret_vals])
|
||||||
if len(resolved) == 0:
|
if len(resolved) == 0:
|
||||||
ret.append(context.sheerka.ret(self.name, True, BuiltinConcepts.NO_RESULT, parents=ret_vals))
|
ret.append(context.sheerka.ret(self.name, True, BuiltinConcepts.NO_RESULT, parents=ret_vals))
|
||||||
else:
|
else:
|
||||||
if len(resolved) < len(ret_vals):
|
if len(resolved) < len(ret_vals):
|
||||||
for c in resolved:
|
for c in resolved:
|
||||||
ret.append(context.sheerka.ret(self.name, True, parser_results[id(c)], parents=ret_vals))
|
ret.append(context.sheerka.ret(self.name, True, presults_concepts_map[id(c)], parents=ret_vals))
|
||||||
|
|
||||||
return None if len(ret) == 0 else ret
|
return None if len(ret) == 0 else ret
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_concept(return_value):
|
||||||
|
if isinstance(return_value.body.body, Concept):
|
||||||
|
return return_value.body.body
|
||||||
|
elif isinstance(return_value.body.body, list) and isinstance(return_value.body.body[0], ConceptNode):
|
||||||
|
return return_value.body.body[0].concept
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_source(context, return_value):
|
def get_source(context, return_value):
|
||||||
"""
|
"""
|
||||||
@@ -60,6 +72,16 @@ class ResolveAmbiguityEvaluator(AllReturnValuesEvaluator):
|
|||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
if context.sheerka.isinstance(return_value.body, BuiltinConcepts.PARSER_RESULT) and \
|
if context.sheerka.isinstance(return_value.body, BuiltinConcepts.PARSER_RESULT) and \
|
||||||
isinstance(return_value.body.body, Concept):
|
(isinstance(return_value.body.body, Concept) or
|
||||||
|
(isinstance(return_value.body.body, list) and
|
||||||
|
len(return_value.body.body) == 1) and
|
||||||
|
isinstance(return_value.body.body[0], ConceptNode)):
|
||||||
return return_value.body.source
|
return return_value.body.source
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def get_has_concept_instance(self, return_value):
|
||||||
|
concept = self.get_concept(return_value)
|
||||||
|
if concept is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return concept.get_hints().is_instance
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from parsers.BaseParser import BaseParser
|
|||||||
|
|
||||||
class ValidateConceptEvaluator(OneReturnValueEvaluator):
|
class ValidateConceptEvaluator(OneReturnValueEvaluator):
|
||||||
"""
|
"""
|
||||||
To recognize when the user input is a question
|
Filter the concept that does not meet its pre and where conditions
|
||||||
"""
|
"""
|
||||||
|
|
||||||
NAME = "ValidateConcept"
|
NAME = "ValidateConcept"
|
||||||
@@ -40,9 +40,12 @@ class ValidateConceptEvaluator(OneReturnValueEvaluator):
|
|||||||
|
|
||||||
def eval(self, context, return_value):
|
def eval(self, context, return_value):
|
||||||
"""
|
"""
|
||||||
This evaluator returns None is the concept validates its PRE and POST constraint or if the constraint cannot
|
This evaluator returns None if
|
||||||
be validated
|
* the constraint cannot be validated
|
||||||
|
* the concept is already a copy and it validates its PRE and POST constraint
|
||||||
If the constraint can be validated, but fails, an error is returned
|
If the constraint can be validated, but fails, an error is returned
|
||||||
|
If concept was not a copy and the constraint is validated, an evaluated copy is returned
|
||||||
|
|
||||||
:param context:
|
:param context:
|
||||||
:param return_value:
|
:param return_value:
|
||||||
:return:
|
:return:
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
from itertools import product
|
||||||
from typing import List, Union
|
from typing import List, Union
|
||||||
|
|
||||||
from core.builtin_concepts_ids import BuiltinConcepts
|
from core.builtin_concepts_ids import BuiltinConcepts
|
||||||
@@ -453,7 +454,7 @@ class BaseExpressionParser(BaseParser):
|
|||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def parse_input(self, context, parser_input, error_sink):
|
def parse_input(self, context, parser_input: ParserInput, error_sink: list):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def parse_tokens_stop_condition(self, token, parser_input):
|
def parse_tokens_stop_condition(self, token, parser_input):
|
||||||
@@ -666,3 +667,71 @@ class IsAQuestionVisitor(ExpressionVisitor):
|
|||||||
def is_a_question(self, expr_node):
|
def is_a_question(self, expr_node):
|
||||||
res = self.visit(expr_node)
|
res = self.visit(expr_node)
|
||||||
return isinstance(res, bool) and res
|
return isinstance(res, bool) and res
|
||||||
|
|
||||||
|
|
||||||
|
def compile_disjunctions(expr_node, nest: bool = True):
|
||||||
|
def get_start_end(items):
|
||||||
|
start, end = None, None
|
||||||
|
for item in items:
|
||||||
|
if start is None or item.start < start:
|
||||||
|
start = item.start
|
||||||
|
if end is None or item.end > end:
|
||||||
|
end = item.end
|
||||||
|
|
||||||
|
return start, end
|
||||||
|
|
||||||
|
def _compile_disjunctions(node, _nest: bool = True):
|
||||||
|
if isinstance(node, OrNode):
|
||||||
|
inner = []
|
||||||
|
for part in node.parts:
|
||||||
|
result = _compile_disjunctions(part, _nest=False)
|
||||||
|
if isinstance(result, tuple):
|
||||||
|
inner.extend(result)
|
||||||
|
else:
|
||||||
|
inner.append(result)
|
||||||
|
return tuple(inner)
|
||||||
|
|
||||||
|
elif isinstance(node, AndNode):
|
||||||
|
inner = []
|
||||||
|
for ele in node.parts:
|
||||||
|
if isinstance(ele, NotNode):
|
||||||
|
t = _compile_disjunctions(ele),
|
||||||
|
inner.append(t)
|
||||||
|
else:
|
||||||
|
inner.append(_compile_disjunctions(ele))
|
||||||
|
|
||||||
|
temp_res = tuple(product(*inner))
|
||||||
|
|
||||||
|
all_conjunctions = []
|
||||||
|
for conjunctions in temp_res:
|
||||||
|
# first transform 'a and (b and c)' into 'a and b and c'
|
||||||
|
conjunctions_to_use = []
|
||||||
|
for item in conjunctions:
|
||||||
|
if isinstance(item, tuple) and isinstance(item[0], AndNode):
|
||||||
|
conjunctions_to_use.extend(item[0].parts)
|
||||||
|
elif isinstance(item, AndNode):
|
||||||
|
conjunctions_to_use.extend(item.parts)
|
||||||
|
else:
|
||||||
|
conjunctions_to_use.append(item)
|
||||||
|
|
||||||
|
start, end = get_start_end(conjunctions_to_use)
|
||||||
|
all_conjunctions.append(AndNode(start, end, expr_node.tokens[start: end + 1], *conjunctions_to_use))
|
||||||
|
return tuple(all_conjunctions)
|
||||||
|
|
||||||
|
elif isinstance(node, NotNode):
|
||||||
|
inner = _compile_disjunctions(node.node)
|
||||||
|
if len(inner) == 1:
|
||||||
|
return node, # do not remove the comma, it's a tuple
|
||||||
|
|
||||||
|
temp_res = tuple(NotNode(branch.start, branch.end, [], branch) for branch in inner)
|
||||||
|
start, end = get_start_end(temp_res)
|
||||||
|
conjunction = AndNode(start, end, expr_node.tokens[start: end + 1], *temp_res)
|
||||||
|
return conjunction, # do not remove the comma, it's a tuple
|
||||||
|
|
||||||
|
elif _nest:
|
||||||
|
return node, # do not remove the comma, it's a tuple
|
||||||
|
|
||||||
|
else:
|
||||||
|
return node
|
||||||
|
|
||||||
|
return list(_compile_disjunctions(expr_node, nest))
|
||||||
|
|||||||
@@ -224,8 +224,14 @@ class ConceptNode(LexerNode):
|
|||||||
return f'CN({self.concept})'
|
return f'CN({self.concept})'
|
||||||
|
|
||||||
def get_concept(self):
|
def get_concept(self):
|
||||||
|
"""
|
||||||
|
Used when there is a mix of Concept and ConceptNode
|
||||||
|
To quickly get the inner concept
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
return self.concept
|
return self.concept
|
||||||
|
|
||||||
|
|
||||||
class SourceCodeNode(LexerNode):
|
class SourceCodeNode(LexerNode):
|
||||||
"""
|
"""
|
||||||
Returned when some source code (like Python source code is recognized)
|
Returned when some source code (like Python source code is recognized)
|
||||||
|
|||||||
@@ -250,23 +250,3 @@ class BaseParserInputParser(BaseParser):
|
|||||||
end -= 1
|
end -= 1
|
||||||
|
|
||||||
return start, end
|
return start, end
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def merge_concepts(list_a, b):
|
|
||||||
if not b:
|
|
||||||
return list_a
|
|
||||||
|
|
||||||
list_b = b if isinstance(b, list) else [b]
|
|
||||||
|
|
||||||
if not list_a:
|
|
||||||
return list_b
|
|
||||||
|
|
||||||
by_ids = {c.id for c in list_b}
|
|
||||||
for c in list_b:
|
|
||||||
if c.id in by_ids: # and c.metadata.is_evaluated == by_ids[c.id].metadata.is_evaluated:
|
|
||||||
continue
|
|
||||||
|
|
||||||
list_a.append(c)
|
|
||||||
by_ids.add(c.id)
|
|
||||||
|
|
||||||
return list_a
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ class RegExDef:
|
|||||||
return flags
|
return flags
|
||||||
|
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
return f"{self.to_match}__!##ZZSEPZZ##!__{self.ignore_case}|{self.multiline}|{self.explicit_flags}"
|
return f"{self.to_match}__!##ZZSEPZZ##!__{self.ignore_case}|{self.multiline}|{int(self.explicit_flags)}"
|
||||||
|
|
||||||
def deserialize(self, txt):
|
def deserialize(self, txt):
|
||||||
parts = txt.split("__!##ZZSEPZZ##!__")
|
parts = txt.split("__!##ZZSEPZZ##!__")
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import core.builtin_helpers
|
import core.builtin_helpers
|
||||||
from core.builtin_concepts import ReturnValueConcept, BuiltinConcepts
|
from core.builtin_concepts import ReturnValueConcept, BuiltinConcepts
|
||||||
from core.concept import VARIABLE_PREFIX
|
from core.concept import VARIABLE_PREFIX
|
||||||
|
from core.sheerka.Sheerka import RECOGNIZED_BY_KEY
|
||||||
from core.sheerka.services.SheerkaExecute import ParserInput
|
from core.sheerka.services.SheerkaExecute import ParserInput
|
||||||
from core.tokenizer import TokenKind
|
from core.tokenizer import TokenKind
|
||||||
from core.utils import str_concept
|
from core.utils import str_concept
|
||||||
@@ -43,6 +44,7 @@ class ExactConceptParser(BaseParserInputParser):
|
|||||||
body = sheerka.new(BuiltinConcepts.NOT_FOR_ME, body=parser_input.as_text(), reason=too_long)
|
body = sheerka.new(BuiltinConcepts.NOT_FOR_ME, body=parser_input.as_text(), reason=too_long)
|
||||||
return sheerka.ret(self.name, False, body)
|
return sheerka.ret(self.name, False, body)
|
||||||
|
|
||||||
|
# First, get the concept using there keys
|
||||||
already_recognized = [] # keep track of the concepts founds
|
already_recognized = [] # keep track of the concepts founds
|
||||||
for combination in self.combinations(words):
|
for combination in self.combinations(words):
|
||||||
|
|
||||||
@@ -75,11 +77,19 @@ class ExactConceptParser(BaseParserInputParser):
|
|||||||
value = words[i]
|
value = words[i]
|
||||||
concept.def_var_by_index(index, str_concept(value) if isinstance(value, tuple) else value)
|
concept.def_var_by_index(index, str_concept(value) if isinstance(value, tuple) else value)
|
||||||
concept.get_hints().need_validation = True
|
concept.get_hints().need_validation = True
|
||||||
|
concept.get_hints().recognized_by = RECOGNIZED_BY_KEY
|
||||||
|
|
||||||
already_recognized.append(concept)
|
already_recognized.append(concept)
|
||||||
|
|
||||||
|
# Also try to recognize concepts by their names
|
||||||
by_name = sheerka.fast_resolve(parser_input.as_text())
|
by_name = sheerka.fast_resolve(parser_input.as_text())
|
||||||
core.builtin_helpers.set_is_evaluated(by_name)
|
if by_name:
|
||||||
|
core.builtin_helpers.update_concepts_hints(by_name,
|
||||||
|
# recognized_by=RECOGNIZED_BY_NAME, # keep fast_resolve settings
|
||||||
|
is_instance=False,
|
||||||
|
is_evaluated=True)
|
||||||
|
|
||||||
|
# merge the two
|
||||||
recognized = self.merge_concepts(already_recognized, by_name)
|
recognized = self.merge_concepts(already_recognized, by_name)
|
||||||
for c in recognized:
|
for c in recognized:
|
||||||
c.get_hints().use_copy = True
|
c.get_hints().use_copy = True
|
||||||
@@ -169,6 +179,32 @@ class ExactConceptParser(BaseParserInputParser):
|
|||||||
res.append(vars[value] if value in vars else value)
|
res.append(vars[value] if value in vars else value)
|
||||||
return tuple(res)
|
return tuple(res)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def merge_concepts(concepts_by_key, concepts_by_name):
|
||||||
|
"""
|
||||||
|
Merge concepts when the id is the same and there is no variable
|
||||||
|
:param concepts_by_key:
|
||||||
|
:param concepts_by_name:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if not concepts_by_name:
|
||||||
|
return concepts_by_key
|
||||||
|
|
||||||
|
concepts_by_name = concepts_by_name if isinstance(concepts_by_name, list) else [concepts_by_name]
|
||||||
|
|
||||||
|
if not concepts_by_key:
|
||||||
|
return concepts_by_name
|
||||||
|
|
||||||
|
by_ids = {c.id for c in concepts_by_key}
|
||||||
|
for c in concepts_by_name:
|
||||||
|
if c.id in by_ids:
|
||||||
|
continue # keep the 'by_key' version to allow evaluation
|
||||||
|
|
||||||
|
concepts_by_key.append(c)
|
||||||
|
by_ids.add(c.id)
|
||||||
|
|
||||||
|
return concepts_by_key
|
||||||
|
|
||||||
def as_return_value(self, context, parser_input, concept):
|
def as_return_value(self, context, parser_input, concept):
|
||||||
return ReturnValueConcept(
|
return ReturnValueConcept(
|
||||||
self.name,
|
self.name,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from dataclasses import dataclass
|
|||||||
|
|
||||||
from core import builtin_helpers
|
from core import builtin_helpers
|
||||||
from core.builtin_concepts import BuiltinConcepts
|
from core.builtin_concepts import BuiltinConcepts
|
||||||
|
from core.builtin_helpers import update_concepts_hints
|
||||||
from core.concept import DEFINITION_TYPE_BNF, Concept
|
from core.concept import DEFINITION_TYPE_BNF, Concept
|
||||||
from core.sheerka.services.SheerkaExecute import ParserInput
|
from core.sheerka.services.SheerkaExecute import ParserInput
|
||||||
from core.tokenizer import Tokenizer, TokenKind
|
from core.tokenizer import Tokenizer, TokenKind
|
||||||
@@ -230,7 +231,8 @@ class SequenceNodeParser(BaseNodeParser):
|
|||||||
:param concept:
|
:param concept:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
return len(concept.get_metadata().variables) == 0 and concept.get_metadata().definition_type != DEFINITION_TYPE_BNF
|
return len(concept.get_metadata().variables) == 0 \
|
||||||
|
and concept.get_metadata().definition_type != DEFINITION_TYPE_BNF
|
||||||
|
|
||||||
def get_concepts(self, token, to_keep, custom=None, to_map=None, strip_quotes=False):
|
def get_concepts(self, token, to_keep, custom=None, to_map=None, strip_quotes=False):
|
||||||
|
|
||||||
@@ -245,11 +247,11 @@ class SequenceNodeParser(BaseNodeParser):
|
|||||||
|
|
||||||
def as_list(a):
|
def as_list(a):
|
||||||
if a is None:
|
if a is None:
|
||||||
return a
|
return None
|
||||||
|
|
||||||
return a if isinstance(a, list) else [a]
|
return a if isinstance(a, list) else [a]
|
||||||
|
|
||||||
concepts_by_name = as_list(self.sheerka.resolve(token))
|
concepts_by_name = as_list(self.sheerka.fast_resolve(token))
|
||||||
concepts_by_first_keyword = new_instances(self.sheerka.get_concepts_by_first_token(token, self._is_eligible))
|
concepts_by_first_keyword = new_instances(self.sheerka.get_concepts_by_first_token(token, self._is_eligible))
|
||||||
|
|
||||||
if concepts_by_name is None:
|
if concepts_by_name is None:
|
||||||
@@ -339,11 +341,17 @@ class SequenceNodeParser(BaseNodeParser):
|
|||||||
It will use the name of the concept, but also its compact form (c::)
|
It will use the name of the concept, but also its compact form (c::)
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
source = self.parser_input.as_text()
|
source = self.parser_input.as_text()
|
||||||
concepts = self.sheerka.resolve(source.strip())
|
concepts = self.sheerka.fast_resolve(source.strip())
|
||||||
if concepts is None:
|
if concepts is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
update_concepts_hints(concepts,
|
||||||
|
# recognized_by=RECOGNIZED_BY_NAME, # keep fast_resolve settings
|
||||||
|
is_instance=False,
|
||||||
|
is_evaluated=True)
|
||||||
|
|
||||||
concepts = [concepts] if isinstance(concepts, Concept) else concepts
|
concepts = [concepts] if isinstance(concepts, Concept) else concepts
|
||||||
res = []
|
res = []
|
||||||
start, end = self.get_tokens_boundaries(self.parser_input.as_tokens())
|
start, end = self.get_tokens_boundaries(self.parser_input.as_tokens())
|
||||||
@@ -414,6 +422,8 @@ class SequenceNodeParser(BaseNodeParser):
|
|||||||
|
|
||||||
sequences = self.get_concepts_sequences()
|
sequences = self.get_concepts_sequences()
|
||||||
if by_name := self.get_by_name():
|
if by_name := self.get_by_name():
|
||||||
|
# note that concepts by names must be appended, not prepended
|
||||||
|
# In case of conflict, we want to keep the one found by get_concepts_sequences()
|
||||||
sequences.extend(by_name)
|
sequences.extend(by_name)
|
||||||
|
|
||||||
parser_helpers = self.get_valid(sequences)
|
parser_helpers = self.get_valid(sequences)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from core.global_symbols import CONCEPT_COMPARISON_CONTEXT, SyaAssociativity
|
|||||||
from core.sheerka.services.SheerkaComparisonManager import SheerkaComparisonManager
|
from core.sheerka.services.SheerkaComparisonManager import SheerkaComparisonManager
|
||||||
from core.sheerka.services.SheerkaExecute import ParserInput
|
from core.sheerka.services.SheerkaExecute import ParserInput
|
||||||
from core.tokenizer import Token, TokenKind, Tokenizer
|
from core.tokenizer import Token, TokenKind, Tokenizer
|
||||||
from core.utils import get_n_clones, get_text_from_tokens, NextIdManager
|
from core.utils import get_n_clones, get_text_from_tokens, NextIdManager, replace_after
|
||||||
from parsers.BaseNodeParser import UnrecognizedTokensNode, ConceptNode, SourceCodeNode, \
|
from parsers.BaseNodeParser import UnrecognizedTokensNode, ConceptNode, SourceCodeNode, \
|
||||||
SourceCodeWithConceptNode, BaseNodeParser, VariableNode
|
SourceCodeWithConceptNode, BaseNodeParser, VariableNode
|
||||||
from parsers.BaseParser import ParsingError
|
from parsers.BaseParser import ParsingError
|
||||||
@@ -185,6 +185,19 @@ class SyaConceptParserHelper:
|
|||||||
if token.type != TokenKind.WHITESPACE:
|
if token.type != TokenKind.WHITESPACE:
|
||||||
self.expected_parameters_before_first_token += 1
|
self.expected_parameters_before_first_token += 1
|
||||||
|
|
||||||
|
# remove useless whitespaces (spaces that are between VAR_DEF)
|
||||||
|
if len(self.expected) > 2:
|
||||||
|
temp = [self.expected[0]]
|
||||||
|
for i in range(1, len(self.expected) - 1):
|
||||||
|
token = self.expected[i]
|
||||||
|
if (token.type == TokenKind.WHITESPACE and
|
||||||
|
self.expected[i - 1].type == TokenKind.VAR_DEF and
|
||||||
|
self.expected[i + 1].type == TokenKind.VAR_DEF):
|
||||||
|
continue # skip it
|
||||||
|
temp.append(token)
|
||||||
|
temp.append(self.expected[-1])
|
||||||
|
self.expected = temp
|
||||||
|
|
||||||
self.eat_token(first_keyword_found) # remove the first token
|
self.eat_token(first_keyword_found) # remove the first token
|
||||||
self.tokens.append(first_keyword_found)
|
self.tokens.append(first_keyword_found)
|
||||||
|
|
||||||
@@ -496,10 +509,19 @@ class InFixToPostFix:
|
|||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
if len(self.parameters_list) < parser_helper.expected_parameters_before_first_token:
|
if len(self.parameters_list) < parser_helper.expected_parameters_before_first_token:
|
||||||
|
# There is not enough parameters to fill the new concept
|
||||||
|
# Try to develop the UnrecognizedTokesNode, to see if it can match
|
||||||
|
developed_param_list = self.develop_parameter_list(self.parameters_list)
|
||||||
|
if len(developed_param_list) < parser_helper.expected_parameters_before_first_token:
|
||||||
# The new concept expect some prefix parameters, but there's not enough
|
# The new concept expect some prefix parameters, but there's not enough
|
||||||
parser_helper.error = "Not enough prefix parameters"
|
parser_helper.error = "Not enough prefix parameters"
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# the developed_param_list does the job. Let's replace the previous values
|
||||||
|
pivot = self.parameters_list[0]
|
||||||
|
replace_after(self.parameters_list, pivot, developed_param_list)
|
||||||
|
replace_after(self.out, pivot, developed_param_list)
|
||||||
|
|
||||||
if len(self.parameters_list) > parser_helper.expected_parameters_before_first_token:
|
if len(self.parameters_list) > parser_helper.expected_parameters_before_first_token:
|
||||||
# There are more parameters than needed by the new concept
|
# There are more parameters than needed by the new concept
|
||||||
# These others parameters are either
|
# These others parameters are either
|
||||||
@@ -530,6 +552,20 @@ class InFixToPostFix:
|
|||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def nb_expected_parameters(expected):
|
||||||
|
"""
|
||||||
|
Count the number of successive variables that are expected
|
||||||
|
:param expected:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
i = 0
|
||||||
|
for token in expected:
|
||||||
|
if token.type == TokenKind.VAR_DEF:
|
||||||
|
i += 1
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
return i
|
||||||
|
|
||||||
# manage parenthesis that didn't find any match
|
# manage parenthesis that didn't find any match
|
||||||
if self._is_lpar(self.stack[-1]):
|
if self._is_lpar(self.stack[-1]):
|
||||||
self._add_error(ParenthesisMismatchError(self.stack[-1]))
|
self._add_error(ParenthesisMismatchError(self.stack[-1]))
|
||||||
@@ -538,6 +574,16 @@ class InFixToPostFix:
|
|||||||
assert len(self._concepts()) != 0 # sanity check
|
assert len(self._concepts()) != 0 # sanity check
|
||||||
|
|
||||||
current_concept = self._concepts()[-1]
|
current_concept = self._concepts()[-1]
|
||||||
|
|
||||||
|
if (nb_expected := nb_expected_parameters(current_concept.expected)) > len(self.parameters_list):
|
||||||
|
# There is not enough parameters in the list to fill the concept
|
||||||
|
# Try to develop the UnrecognizedTokensNode to see if it can match
|
||||||
|
developed_param_list = self.develop_parameter_list(self.parameters_list)
|
||||||
|
if nb_expected == len(developed_param_list):
|
||||||
|
pivot = self.parameters_list[0]
|
||||||
|
replace_after(self.parameters_list, pivot, developed_param_list)
|
||||||
|
replace_after(self.out, pivot, developed_param_list)
|
||||||
|
|
||||||
while len(current_concept.expected) > 0 and current_concept.expected[0].type == TokenKind.VAR_DEF:
|
while len(current_concept.expected) > 0 and current_concept.expected[0].type == TokenKind.VAR_DEF:
|
||||||
# eat everything that was expected
|
# eat everything that was expected
|
||||||
if len(self.parameters_list) == 0:
|
if len(self.parameters_list) == 0:
|
||||||
@@ -640,13 +686,24 @@ class InFixToPostFix:
|
|||||||
Helper function that pops the stack and put the item to the output, if needed
|
Helper function that pops the stack and put the item to the output, if needed
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
item = self.stack[-1]
|
item = self.stack[-1]
|
||||||
|
|
||||||
# fix the concept is needed
|
# fix the concept is needed
|
||||||
if isinstance(item, SyaConceptParserHelper):
|
if isinstance(item, SyaConceptParserHelper):
|
||||||
|
if len(item.expected) > 0:
|
||||||
# make sure the expected parameters of this item are eaten
|
# make sure the expected parameters of this item are eaten
|
||||||
if 0 < len(item.expected) <= len(self.parameters_list):
|
if len(item.expected) <= len(self.parameters_list):
|
||||||
self.manage_parameters()
|
self.manage_parameters()
|
||||||
|
else:
|
||||||
|
# second chance to match the parameter list when it contains unrecognized token
|
||||||
|
developed_param_list = self.develop_parameter_list(self.parameters_list)
|
||||||
|
if len(item.expected) <= len(developed_param_list):
|
||||||
|
pivot = self.parameters_list[0]
|
||||||
|
replace_after(self.parameters_list, pivot, developed_param_list)
|
||||||
|
replace_after(self.out, pivot, developed_param_list)
|
||||||
|
self.manage_parameters()
|
||||||
|
|
||||||
item.fix_concept()
|
item.fix_concept()
|
||||||
|
|
||||||
self.stack.pop()
|
self.stack.pop()
|
||||||
@@ -1119,6 +1176,25 @@ class InFixToPostFix:
|
|||||||
# clone.forked = self.forked
|
# clone.forked = self.forked
|
||||||
return clone
|
return clone
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def develop_parameter_list(parameter_list):
|
||||||
|
"""
|
||||||
|
given a list of parameter (solely from self.parameter_list)
|
||||||
|
develop UnrecognizedTokensNode parameter that contains whitespaces
|
||||||
|
:param parameter_list:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
temp = []
|
||||||
|
for parameter in parameter_list:
|
||||||
|
if isinstance(parameter, UnrecognizedTokensNode):
|
||||||
|
for i, token in [(i, t) for i, t in enumerate(parameter.tokens) if t.type != TokenKind.WHITESPACE]:
|
||||||
|
temp.append(UnrecognizedTokensNode(parameter.start + i,
|
||||||
|
parameter.start + i,
|
||||||
|
[token]))
|
||||||
|
else:
|
||||||
|
temp.append(parameter)
|
||||||
|
return temp
|
||||||
|
|
||||||
|
|
||||||
@dataclass()
|
@dataclass()
|
||||||
class PostFixToItem:
|
class PostFixToItem:
|
||||||
@@ -1428,8 +1504,8 @@ class SyaNodeParser(BaseNodeParser):
|
|||||||
def _has_sya(items):
|
def _has_sya(items):
|
||||||
for item in items:
|
for item in items:
|
||||||
if isinstance(item, SourceCodeWithConceptNode):
|
if isinstance(item, SourceCodeWithConceptNode):
|
||||||
if _has_sya(item.nodes):
|
return _has_sya(item.nodes)
|
||||||
return True
|
|
||||||
if isinstance(item, SyaConceptParserHelper):
|
if isinstance(item, SyaConceptParserHelper):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ class SheerkaPickler:
|
|||||||
self.to_reduce.append(ToReduce(lambda o: isinstance(o, (BaseParser, BaseEvaluator)), lambda o: o.name))
|
self.to_reduce.append(ToReduce(lambda o: isinstance(o, (BaseParser, BaseEvaluator)), lambda o: o.name))
|
||||||
self.to_reduce.append(ToReduce(lambda o: isinstance(o, ParserInput), lambda o: o.as_text()))
|
self.to_reduce.append(ToReduce(lambda o: isinstance(o, ParserInput), lambda o: o.as_text()))
|
||||||
self.to_reduce.append(ToReduce(lambda o: isinstance(o, Ontology), lambda o: o.name))
|
self.to_reduce.append(ToReduce(lambda o: isinstance(o, Ontology), lambda o: o.name))
|
||||||
|
from core.sheerka.Sheerka import SheerkaMethod
|
||||||
|
self.to_reduce.append(ToReduce(lambda o: isinstance(o, SheerkaMethod), lambda o: o.name))
|
||||||
|
|
||||||
def flatten(self, obj):
|
def flatten(self, obj):
|
||||||
if utils.is_to_discard(obj):
|
if utils.is_to_discard(obj):
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ def resolve_object(context, who, obj):
|
|||||||
raise Exception()
|
raise Exception()
|
||||||
|
|
||||||
if (isinstance(obj, str) and obj.startswith("c:")) or isinstance(obj, Token):
|
if (isinstance(obj, str) and obj.startswith("c:")) or isinstance(obj, Token):
|
||||||
concept = context.sheerka.fast_resolve(obj)
|
concept = context.sheerka.fast_resolve(obj, force_instance=True)
|
||||||
if concept is None:
|
if concept is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
+19
-5
@@ -104,7 +104,7 @@ class BaseTest:
|
|||||||
def get_sheerka(self, **kwargs) -> Sheerka:
|
def get_sheerka(self, **kwargs) -> Sheerka:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get_context(self, sheerka=None, eval_body=False, eval_where=False, message=""):
|
def get_context(self, sheerka=None, eval_body=False, eval_where=False, global_truth=False, message=""):
|
||||||
context = ExecutionContext("test",
|
context = ExecutionContext("test",
|
||||||
Event(message=message),
|
Event(message=message),
|
||||||
sheerka or self.get_sheerka(),
|
sheerka or self.get_sheerka(),
|
||||||
@@ -114,20 +114,29 @@ class BaseTest:
|
|||||||
context.protected_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
context.protected_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||||
if eval_where:
|
if eval_where:
|
||||||
context.protected_hints.add(BuiltinConcepts.EVAL_WHERE_REQUESTED)
|
context.protected_hints.add(BuiltinConcepts.EVAL_WHERE_REQUESTED)
|
||||||
|
if global_truth:
|
||||||
|
context.protected_hints.add(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED)
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_init_test_args(**kwargs):
|
def get_init_test_args(**kwargs):
|
||||||
return {k: v for k, v in kwargs.items() if k in ["cache_only", "ontology", "eval_body", "eval_where"]}
|
return {k: v for k, v in kwargs.items() if k in ["cache_only",
|
||||||
|
"ontology",
|
||||||
|
"eval_body",
|
||||||
|
"eval_where",
|
||||||
|
"global_truth"]}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_with_concepts_args(**kwargs):
|
def get_with_concepts_args(**kwargs):
|
||||||
return {k: v for k, v in kwargs.items() if k in ["create_new"]}
|
return {k: v for k, v in kwargs.items() if k in ["create_new"]}
|
||||||
|
|
||||||
def init_test(self, cache_only=None, ontology=None, eval_body=False, eval_where=False):
|
def init_test(self, cache_only=None, ontology=None, eval_body=False, eval_where=False, global_truth=False):
|
||||||
sheerka = self.get_sheerka(cache_only=cache_only, ontology=ontology)
|
sheerka = self.get_sheerka(cache_only=cache_only, ontology=ontology)
|
||||||
context = self.get_context(sheerka=sheerka, eval_body=eval_body, eval_where=eval_where)
|
context = self.get_context(sheerka=sheerka,
|
||||||
|
eval_body=eval_body,
|
||||||
|
eval_where=eval_where,
|
||||||
|
global_truth=global_truth)
|
||||||
|
|
||||||
return InitTestHelper(sheerka, context)
|
return InitTestHelper(sheerka, context)
|
||||||
|
|
||||||
@@ -255,14 +264,19 @@ class BaseTest:
|
|||||||
concept.get_metadata().variables[k] = v
|
concept.get_metadata().variables[k] = v
|
||||||
return concept
|
return concept
|
||||||
|
|
||||||
def init_scenario(self, init_expressions):
|
def init_scenario(self, init_expressions, global_truth=False):
|
||||||
sheerka = self.get_sheerka()
|
sheerka = self.get_sheerka()
|
||||||
|
if global_truth:
|
||||||
|
sheerka.add_to_context(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED)
|
||||||
|
|
||||||
for expression in init_expressions:
|
for expression in init_expressions:
|
||||||
res = sheerka.evaluate_user_input(expression)
|
res = sheerka.evaluate_user_input(expression)
|
||||||
assert len(res) == 1, f"Failed to execute '{expression}'"
|
assert len(res) == 1, f"Failed to execute '{expression}'"
|
||||||
assert res[0].status, f"Error while executing '{expression}'"
|
assert res[0].status, f"Error while executing '{expression}'"
|
||||||
|
|
||||||
|
if global_truth:
|
||||||
|
sheerka.remove_fom_context(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED)
|
||||||
|
|
||||||
return sheerka
|
return sheerka
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
|||||||
|
|
||||||
class TestSheerkaConceptsAlgebra(TestUsingMemoryBasedSheerka):
|
class TestSheerkaConceptsAlgebra(TestUsingMemoryBasedSheerka):
|
||||||
def test_i_can_add_concepts(self):
|
def test_i_can_add_concepts(self):
|
||||||
sheerka, context, man, human, male, driver, licence, car = self.init_concepts(
|
sheerka, context, man, human, male, driver, licence, car = self.init_test(global_truth=True).with_concepts(
|
||||||
"man", "human", "male",
|
"man", "human", "male",
|
||||||
"driver", "licence", "car")
|
"driver", "licence", "car").unpack()
|
||||||
|
|
||||||
sheerka.set_isa(context, sheerka.new("man"), human)
|
sheerka.set_isa(context, sheerka.new("man"), human)
|
||||||
sheerka.set_isa(context, sheerka.new("man"), male)
|
sheerka.set_isa(context, sheerka.new("man"), male)
|
||||||
@@ -23,8 +23,8 @@ class TestSheerkaConceptsAlgebra(TestUsingMemoryBasedSheerka):
|
|||||||
BuiltinConcepts.HASA: {car, licence}, }
|
BuiltinConcepts.HASA: {car, licence}, }
|
||||||
|
|
||||||
def test_can_add_concepts_when_property_already_exist(self):
|
def test_can_add_concepts_when_property_already_exist(self):
|
||||||
sheerka, context, man, human, king, male = self.init_concepts(
|
sheerka, context, man, human, king, male = self.init_test(global_truth=True).with_concepts(
|
||||||
"man", "human", "king", "male")
|
"man", "human", "king", "male").unpack()
|
||||||
|
|
||||||
sheerka.set_isa(context, sheerka.new("man"), human)
|
sheerka.set_isa(context, sheerka.new("man"), human)
|
||||||
sheerka.set_isa(context, sheerka.new("king"), male)
|
sheerka.set_isa(context, sheerka.new("king"), male)
|
||||||
@@ -35,9 +35,9 @@ class TestSheerkaConceptsAlgebra(TestUsingMemoryBasedSheerka):
|
|||||||
assert res.get_metadata().props == {BuiltinConcepts.ISA: {male, human}}
|
assert res.get_metadata().props == {BuiltinConcepts.ISA: {male, human}}
|
||||||
|
|
||||||
def test_i_can_subtract_concepts(self):
|
def test_i_can_subtract_concepts(self):
|
||||||
sheerka, context, foo, bar, isa1, isa2, hasa1, hasa2 = self.init_concepts(
|
sheerka, context, foo, bar, isa1, isa2, hasa1, hasa2 = self.init_test(global_truth=True).with_concepts(
|
||||||
"foo", "bar",
|
"foo", "bar",
|
||||||
"isa1", "isa2", "has1", "has2")
|
"isa1", "isa2", "has1", "has2").unpack()
|
||||||
|
|
||||||
new_foo = sheerka.new("foo")
|
new_foo = sheerka.new("foo")
|
||||||
sheerka.set_isa(context, new_foo, isa1)
|
sheerka.set_isa(context, new_foo, isa1)
|
||||||
@@ -61,9 +61,10 @@ class TestSheerkaConceptsAlgebra(TestUsingMemoryBasedSheerka):
|
|||||||
BuiltinConcepts.HASA: {hasa2}, }
|
BuiltinConcepts.HASA: {hasa2}, }
|
||||||
|
|
||||||
def test_i_can_recognize_myself_when_using_sdp_repository(self):
|
def test_i_can_recognize_myself_when_using_sdp_repository(self):
|
||||||
sheerka, context, foo, isa1, hasa1, = self.init_test(cache_only=False). \
|
sheerka, context, foo, isa1, hasa1, = self.init_test(cache_only=False, global_truth=True).with_concepts(
|
||||||
with_concepts("foo", "isa1", "has1", create_new=True). \
|
"foo",
|
||||||
unpack()
|
"isa1",
|
||||||
|
"has1", create_new=True).unpack()
|
||||||
sheerka.om.commit(context)
|
sheerka.om.commit(context)
|
||||||
|
|
||||||
new_foo = sheerka.new("foo")
|
new_foo = sheerka.new("foo")
|
||||||
@@ -74,7 +75,10 @@ class TestSheerkaConceptsAlgebra(TestUsingMemoryBasedSheerka):
|
|||||||
assert sheerka.recognize(new_foo, all_scores=True) == [ConceptScore(1, new_foo, new_foo)]
|
assert sheerka.recognize(new_foo, all_scores=True) == [ConceptScore(1, new_foo, new_foo)]
|
||||||
|
|
||||||
def test_i_can_recognize_myself_when_not_using_sdp_repository(self):
|
def test_i_can_recognize_myself_when_not_using_sdp_repository(self):
|
||||||
sheerka, context, foo, isa1, hasa1, = self.init_concepts("foo", "isa1", "has1")
|
sheerka, context, foo, isa1, hasa1, = self.init_test(global_truth=True).with_concepts(
|
||||||
|
"foo",
|
||||||
|
"isa1",
|
||||||
|
"has1").unpack()
|
||||||
|
|
||||||
new_foo = sheerka.new("foo")
|
new_foo = sheerka.new("foo")
|
||||||
sheerka.set_isa(context, new_foo, isa1)
|
sheerka.set_isa(context, new_foo, isa1)
|
||||||
@@ -100,9 +104,9 @@ class TestSheerkaConceptsAlgebra(TestUsingMemoryBasedSheerka):
|
|||||||
assert sheerka.recognize(Concept(), all_scores=True) == []
|
assert sheerka.recognize(Concept(), all_scores=True) == []
|
||||||
|
|
||||||
def test_i_can_recognize_multiple_concepts_with_the_proper_score(self):
|
def test_i_can_recognize_multiple_concepts_with_the_proper_score(self):
|
||||||
sheerka, context, foo, bar, isa1, isa2, hasa1, hasa2 = self.init_concepts(
|
sheerka, context, foo, bar, isa1, isa2, hasa1, hasa2 = self.init_test(global_truth=True).with_concepts(
|
||||||
"foo", "bar",
|
"foo", "bar",
|
||||||
"isa1", "isa2", "has1", "has2")
|
"isa1", "isa2", "has1", "has2").unpack()
|
||||||
|
|
||||||
new_foo = sheerka.new("foo")
|
new_foo = sheerka.new("foo")
|
||||||
sheerka.set_isa(context, new_foo, isa1)
|
sheerka.set_isa(context, new_foo, isa1)
|
||||||
@@ -131,9 +135,9 @@ class TestSheerkaConceptsAlgebra(TestUsingMemoryBasedSheerka):
|
|||||||
ConceptScore(0.5, sheerka.new("bar"), to_recognize)]
|
ConceptScore(0.5, sheerka.new("bar"), to_recognize)]
|
||||||
|
|
||||||
def test_i_can_recognize_if_all_scores_is_disabled(self):
|
def test_i_can_recognize_if_all_scores_is_disabled(self):
|
||||||
sheerka, context, foo, bar, isa1, isa2, hasa1, hasa2 = self.init_concepts(
|
sheerka, context, foo, bar, isa1, isa2, hasa1, hasa2 = self.init_test(global_truth=True).with_concepts(
|
||||||
"foo", "bar",
|
"foo", "bar",
|
||||||
"isa1", "isa2", "has1", "has2")
|
"isa1", "isa2", "has1", "has2").unpack()
|
||||||
|
|
||||||
new_foo = sheerka.new("foo")
|
new_foo = sheerka.new("foo")
|
||||||
sheerka.set_isa(context, new_foo, isa1)
|
sheerka.set_isa(context, new_foo, isa1)
|
||||||
@@ -153,9 +157,9 @@ class TestSheerkaConceptsAlgebra(TestUsingMemoryBasedSheerka):
|
|||||||
assert res == ConceptScore(1.0, sheerka.new("bar"), to_recognize)
|
assert res == ConceptScore(1.0, sheerka.new("bar"), to_recognize)
|
||||||
|
|
||||||
def test_i_can_recognize_if_all_scores_is_disabled_but_multiple_high_scores(self):
|
def test_i_can_recognize_if_all_scores_is_disabled_but_multiple_high_scores(self):
|
||||||
sheerka, context, foo, bar, isa1, hasa1 = self.init_concepts(
|
sheerka, context, foo, bar, isa1, hasa1 = self.init_test(global_truth=True).with_concepts(
|
||||||
"foo", "bar",
|
"foo", "bar",
|
||||||
"isa1", "has1")
|
"isa1", "has1").unpack()
|
||||||
|
|
||||||
new_foo = sheerka.new("foo")
|
new_foo = sheerka.new("foo")
|
||||||
sheerka.set_isa(context, new_foo, isa1)
|
sheerka.set_isa(context, new_foo, isa1)
|
||||||
|
|||||||
@@ -1105,13 +1105,14 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
|
|||||||
Concept("hundreds", definition="number hundred"),
|
Concept("hundreds", definition="number hundred"),
|
||||||
)
|
)
|
||||||
|
|
||||||
sheerka.set_isa(context, sheerka.new("one"), number)
|
global_truth_context = self.get_context(sheerka, global_truth=True)
|
||||||
sheerka.set_isa(context, sheerka.new("two"), number)
|
sheerka.set_isa(global_truth_context, sheerka.new("one"), number)
|
||||||
sheerka.set_isa(context, sheerka.new("twenty"), number)
|
sheerka.set_isa(global_truth_context, sheerka.new("two"), number)
|
||||||
sheerka.set_isa(context, sheerka.new("thirty"), number)
|
sheerka.set_isa(global_truth_context, sheerka.new("twenty"), number)
|
||||||
sheerka.set_isa(context, sheerka.new("hundred"), number)
|
sheerka.set_isa(global_truth_context, sheerka.new("thirty"), number)
|
||||||
sheerka.set_isa(context, sheerka.new("twenties"), number)
|
sheerka.set_isa(global_truth_context, sheerka.new("hundred"), number)
|
||||||
sheerka.set_isa(context, sheerka.new("hundreds"), number)
|
sheerka.set_isa(global_truth_context, sheerka.new("twenties"), number)
|
||||||
|
sheerka.set_isa(global_truth_context, sheerka.new("hundreds"), number)
|
||||||
|
|
||||||
sheerka.clear_bnf_definition() # reset all the grammar to simulate Sheerka restart
|
sheerka.clear_bnf_definition() # reset all the grammar to simulate Sheerka restart
|
||||||
|
|
||||||
@@ -1129,12 +1130,12 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def test_i_can_resolve_when_concepts_have_multiple_levels_of_sets(self):
|
def test_i_can_resolve_when_concepts_have_multiple_levels_of_sets(self):
|
||||||
sheerka, context, adjective, color, red, qualified_table = self.init_concepts(
|
sheerka, context, adjective, color, red, qualified_table = self.init_test(global_truth=True).with_concepts(
|
||||||
"adjective",
|
"adjective",
|
||||||
"color",
|
"color",
|
||||||
"red",
|
"red",
|
||||||
Concept("qualified table", definition="adjective 'table'"),
|
Concept("qualified table", definition="adjective 'table'"),
|
||||||
)
|
).unpack()
|
||||||
|
|
||||||
sheerka.set_isa(context, color, adjective)
|
sheerka.set_isa(context, color, adjective)
|
||||||
sheerka.set_isa(context, red, color)
|
sheerka.set_isa(context, red, color)
|
||||||
@@ -1404,7 +1405,8 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
|
|||||||
def test_i_cannot_smart_get_attr_when_attribute_does_not_exist(self):
|
def test_i_cannot_smart_get_attr_when_attribute_does_not_exist(self):
|
||||||
sheerka, context, adjective, color, red, size, table = self.init_concepts("adjective",
|
sheerka, context, adjective, color, red, size, table = self.init_concepts("adjective",
|
||||||
"color",
|
"color",
|
||||||
Concept("red", body="red").auto_init(),
|
Concept("red",
|
||||||
|
body="red").auto_init(),
|
||||||
"size",
|
"size",
|
||||||
"table",
|
"table",
|
||||||
create_new=True)
|
create_new=True)
|
||||||
|
|||||||
@@ -391,8 +391,8 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
|||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
sheerka, context, predicate, foo = self.init_concepts(
|
sheerka, context, predicate, foo = self.init_concepts(
|
||||||
Concept("Sometimes True", body="in_context('a')"),
|
Concept("Sometimes True", body="in_context('a')", pre="is_question()"),
|
||||||
Concept("foo", pre="c:Sometimes True:"))
|
Concept("foo", pre="Sometimes True"))
|
||||||
|
|
||||||
foo1 = sheerka.new("foo")
|
foo1 = sheerka.new("foo")
|
||||||
foo1 = sheerka.evaluate_concept(context, foo1) # 'a' is not in context, so it fails
|
foo1 = sheerka.evaluate_concept(context, foo1) # 'a' is not in context, so it fails
|
||||||
@@ -400,7 +400,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
|||||||
context2 = self.get_context(sheerka)
|
context2 = self.get_context(sheerka)
|
||||||
context2.add_to_protected_hints('a')
|
context2.add_to_protected_hints('a')
|
||||||
foo2 = sheerka.new("foo")
|
foo2 = sheerka.new("foo")
|
||||||
foo2 = sheerka.evaluate_concept(context2, foo2) # 'a' in context + new instance of 'Sometimes True'
|
foo2 = sheerka.evaluate_concept(context2, foo2) # 'a' is now in context
|
||||||
|
|
||||||
assert sheerka.isinstance(foo1, BuiltinConcepts.CONDITION_FAILED)
|
assert sheerka.isinstance(foo1, BuiltinConcepts.CONDITION_FAILED)
|
||||||
assert sheerka.isinstance(foo2, "foo")
|
assert sheerka.isinstance(foo2, "foo")
|
||||||
|
|||||||
@@ -7,6 +7,33 @@ class TestSheerkaHasAManager(TestUsingMemoryBasedSheerka):
|
|||||||
def test_i_can_set_hasa(self):
|
def test_i_can_set_hasa(self):
|
||||||
sheerka, context, king, kingdom = self.init_concepts("king", "kingdom")
|
sheerka, context, king, kingdom = self.init_concepts("king", "kingdom")
|
||||||
|
|
||||||
|
king_instance = sheerka.new("king")
|
||||||
|
res = sheerka.set_hasa(context, king_instance, kingdom)
|
||||||
|
assert res.status
|
||||||
|
|
||||||
|
# when global truth is not activated, only the current instance is modified
|
||||||
|
another_king = sheerka.get_by_key("king")
|
||||||
|
assert not another_king.get_prop(BuiltinConcepts.HASA) == {kingdom}
|
||||||
|
assert not sheerka.hasa(another_king, kingdom)
|
||||||
|
|
||||||
|
def test_i_cannot_set_the_same_attribute_twice(self):
|
||||||
|
sheerka, context, king, kingdom = self.init_concepts("king", "kingdom")
|
||||||
|
|
||||||
|
king_instance = sheerka.new("king")
|
||||||
|
sheerka.set_hasa(context, king_instance, kingdom)
|
||||||
|
res = sheerka.set_hasa(context, king_instance, kingdom)
|
||||||
|
|
||||||
|
assert not res.status
|
||||||
|
assert sheerka.isinstance(res.body, BuiltinConcepts.PROPERTY_ALREADY_DEFINED)
|
||||||
|
assert res.body.property_name == BuiltinConcepts.HASA
|
||||||
|
assert res.body.property_value == kingdom
|
||||||
|
assert res.body.concept == king_instance
|
||||||
|
|
||||||
|
def test_i_can_set_hasa_when_global_truth_is_activated(self):
|
||||||
|
sheerka, context, king, kingdom = self.init_test(global_truth=True).with_concepts(
|
||||||
|
"king",
|
||||||
|
"kingdom").unpack()
|
||||||
|
|
||||||
res = sheerka.set_hasa(context, sheerka.new("king"), kingdom)
|
res = sheerka.set_hasa(context, sheerka.new("king"), kingdom)
|
||||||
assert res.status
|
assert res.status
|
||||||
|
|
||||||
@@ -16,8 +43,10 @@ class TestSheerkaHasAManager(TestUsingMemoryBasedSheerka):
|
|||||||
# check that the definition of the concept has been updated
|
# check that the definition of the concept has been updated
|
||||||
assert sheerka.hasa(sheerka.new("king"), kingdom)
|
assert sheerka.hasa(sheerka.new("king"), kingdom)
|
||||||
|
|
||||||
def test_i_cannot_set_the_same_attribute_twice(self):
|
def test_i_cannot_set_the_same_attribute_twice_when_global_truth_is_activated(self):
|
||||||
sheerka, context, king, kingdom = self.init_concepts("king", "kingdom")
|
sheerka, context, king, kingdom = self.init_test(global_truth=True).with_concepts(
|
||||||
|
"king",
|
||||||
|
"kingdom").unpack()
|
||||||
|
|
||||||
sheerka.set_hasa(context, sheerka.new("king"), kingdom)
|
sheerka.set_hasa(context, sheerka.new("king"), kingdom)
|
||||||
res = sheerka.set_hasa(context, sheerka.new("king"), kingdom)
|
res = sheerka.set_hasa(context, sheerka.new("king"), kingdom)
|
||||||
|
|||||||
@@ -86,15 +86,46 @@ class TestSheerkaIsAManager(TestUsingMemoryBasedSheerka):
|
|||||||
|
|
||||||
def test_isa(self):
|
def test_isa(self):
|
||||||
sheerka, context, blue, color = self.init_concepts(Concept("blue"), Concept("color"))
|
sheerka, context, blue, color = self.init_concepts(Concept("blue"), Concept("color"))
|
||||||
|
|
||||||
assert not sheerka.isa(blue, color)
|
assert not sheerka.isa(blue, color)
|
||||||
|
|
||||||
sheerka.set_isa(context, blue, color)
|
blue_instance = sheerka.new("blue")
|
||||||
assert sheerka.isa(blue, color)
|
assert not sheerka.isa(blue_instance, color)
|
||||||
|
|
||||||
|
sheerka.set_isa(context, blue_instance, color)
|
||||||
|
assert sheerka.isa(blue_instance, color)
|
||||||
|
|
||||||
# isa tests the id of a concept, not it's content
|
# isa tests the id of a concept, not it's content
|
||||||
another_color_instance_but_with_a_body = sheerka.new(color, body="a body")
|
another_color_instance_but_with_a_body = sheerka.new(color, body="a body")
|
||||||
assert sheerka.isa(blue, another_color_instance_but_with_a_body)
|
assert sheerka.isa(blue_instance, another_color_instance_but_with_a_body)
|
||||||
|
|
||||||
|
# isa, when EVAL_GLOBAL_TRUTH_REQUESTED is not activated, only affect the current concept
|
||||||
|
another_blue_instance = sheerka.new("blue")
|
||||||
|
assert not sheerka.isa(another_blue_instance, color)
|
||||||
|
|
||||||
|
# when EVAL_GLOBAL_TRUTH_REQUESTED is not activated, color is not a set
|
||||||
|
assert not sheerka.isinset(blue_instance, color)
|
||||||
|
assert not sheerka.isaset(context, color)
|
||||||
|
|
||||||
|
def test_isa_global_truth(self):
|
||||||
|
sheerka, context, blue, color = self.init_concepts(Concept("blue"), Concept("color"))
|
||||||
|
|
||||||
|
blue_instance = sheerka.new("blue")
|
||||||
|
assert not sheerka.isa(blue_instance, color)
|
||||||
|
assert not sheerka.isaset(context, color)
|
||||||
|
assert not sheerka.isinset(blue_instance, color)
|
||||||
|
|
||||||
|
context.add_to_private_hints(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED)
|
||||||
|
|
||||||
|
sheerka.set_isa(context, blue_instance, color)
|
||||||
|
assert sheerka.isa(blue_instance, color)
|
||||||
|
assert sheerka.isaset(context, color)
|
||||||
|
assert sheerka.isinset(blue_instance, color)
|
||||||
|
|
||||||
|
# all blue instances are now a color
|
||||||
|
another_blue_instance = sheerka.new("blue")
|
||||||
|
assert sheerka.isa(another_blue_instance, color)
|
||||||
|
assert sheerka.isaset(context, color)
|
||||||
|
assert sheerka.isinset(another_blue_instance, color)
|
||||||
|
|
||||||
def test_isaset(self):
|
def test_isaset(self):
|
||||||
sheerka, context, group, foo = self.init_concepts(Concept("group"), Concept("foo"))
|
sheerka, context, group, foo = self.init_concepts(Concept("group"), Concept("foo"))
|
||||||
@@ -246,13 +277,28 @@ class TestSheerkaIsAManager(TestUsingMemoryBasedSheerka):
|
|||||||
|
|
||||||
foo = sheerka.new(foo.key) # new instance
|
foo = sheerka.new(foo.key) # new instance
|
||||||
sheerka.set_isa(context, foo, all_foo)
|
sheerka.set_isa(context, foo, all_foo)
|
||||||
|
sheerka.set_isa(context, foo, all_bar)
|
||||||
|
|
||||||
|
assert foo.get_prop(BuiltinConcepts.ISA) == {all_foo, all_bar}
|
||||||
|
assert sheerka.isa(foo, all_foo)
|
||||||
|
assert sheerka.isa(foo, all_bar)
|
||||||
|
|
||||||
|
def test_a_concept_can_be_in_multiple_sets_when_global_truth_is_activated(self):
|
||||||
|
sheerka, context, foo, all_foo, all_bar = self.init_test(global_truth=True).with_concepts(
|
||||||
|
Concept("foo"),
|
||||||
|
Concept("all_foo"),
|
||||||
|
Concept("all_bar"),
|
||||||
|
create_new=True).unpack()
|
||||||
|
|
||||||
|
foo = sheerka.new(foo.key) # new instance
|
||||||
|
sheerka.set_isa(context, foo, all_foo)
|
||||||
foo = sheerka.new(foo.key) # new instance
|
foo = sheerka.new(foo.key) # new instance
|
||||||
sheerka.set_isa(context, foo, all_bar)
|
sheerka.set_isa(context, foo, all_bar)
|
||||||
|
|
||||||
assert foo.get_prop(BuiltinConcepts.ISA) == {all_foo, all_bar}
|
assert foo.get_prop(BuiltinConcepts.ISA) == {all_foo, all_bar}
|
||||||
assert sheerka.isa(foo, all_foo)
|
assert sheerka.isa(foo, all_foo)
|
||||||
assert sheerka.isa(foo, all_bar)
|
assert sheerka.isa(foo, all_bar)
|
||||||
|
|
||||||
assert sheerka.isinset(foo, all_foo)
|
assert sheerka.isinset(foo, all_foo)
|
||||||
assert sheerka.isinset(foo, all_bar)
|
assert sheerka.isinset(foo, all_bar)
|
||||||
assert sheerka.isaset(context, all_foo)
|
assert sheerka.isaset(context, all_foo)
|
||||||
@@ -270,6 +316,25 @@ class TestSheerkaIsAManager(TestUsingMemoryBasedSheerka):
|
|||||||
Concept("baz"),
|
Concept("baz"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
sheerka.set_isa(context, foo, bar)
|
||||||
|
sheerka.set_isa(context, bar, baz)
|
||||||
|
|
||||||
|
assert sheerka.isa(foo, bar)
|
||||||
|
assert sheerka.isa(bar, baz)
|
||||||
|
assert sheerka.isa(foo, baz)
|
||||||
|
|
||||||
|
def test_i_can_manage_isa_transitivity_when_global_truth_is_activated(self):
|
||||||
|
"""
|
||||||
|
if foo isa bar and bar isa baz, then foo isa baz
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
sheerka, context, foo, bar, baz = self.init_test(global_truth=True).with_concepts(
|
||||||
|
Concept("foo"),
|
||||||
|
Concept("bar"),
|
||||||
|
Concept("baz"),
|
||||||
|
).unpack()
|
||||||
|
|
||||||
sheerka.set_isa(context, sheerka.new("foo"), bar)
|
sheerka.set_isa(context, sheerka.new("foo"), bar)
|
||||||
sheerka.set_isa(context, sheerka.new("bar"), baz)
|
sheerka.set_isa(context, sheerka.new("bar"), baz)
|
||||||
|
|
||||||
@@ -278,11 +343,11 @@ class TestSheerkaIsAManager(TestUsingMemoryBasedSheerka):
|
|||||||
assert sheerka.isa(sheerka.new("foo"), baz)
|
assert sheerka.isa(sheerka.new("foo"), baz)
|
||||||
|
|
||||||
def test_i_cannot_manage_isa_transitivity_when_using_body(self):
|
def test_i_cannot_manage_isa_transitivity_when_using_body(self):
|
||||||
sheerka, context, one, another_one, number = self.init_concepts(
|
sheerka, context, one, another_one, number = self.init_test(global_truth=True).with_concepts(
|
||||||
"one",
|
"one",
|
||||||
Concept("another one", body="one"),
|
Concept("another one", body="one"),
|
||||||
"number"
|
"number"
|
||||||
)
|
).unpack()
|
||||||
|
|
||||||
sheerka.set_isa(context, sheerka.new("one"), number)
|
sheerka.set_isa(context, sheerka.new("one"), number)
|
||||||
|
|
||||||
@@ -290,7 +355,10 @@ class TestSheerkaIsAManager(TestUsingMemoryBasedSheerka):
|
|||||||
assert not sheerka.isa(another_one, number) # Correct this misbehaviour when BuiltinConcepts.IS is implemented
|
assert not sheerka.isa(another_one, number) # Correct this misbehaviour when BuiltinConcepts.IS is implemented
|
||||||
|
|
||||||
def test_concepts_in_group_cache_is_updated(self):
|
def test_concepts_in_group_cache_is_updated(self):
|
||||||
sheerka, context, one, two, number = self.init_concepts("one", "two", "number")
|
sheerka, context, one, two, number = self.init_test(global_truth=True).with_concepts(
|
||||||
|
"one",
|
||||||
|
"two",
|
||||||
|
"number").unpack()
|
||||||
|
|
||||||
sheerka.set_isa(context, sheerka.new("one"), number)
|
sheerka.set_isa(context, sheerka.new("one"), number)
|
||||||
|
|
||||||
@@ -315,12 +383,12 @@ class TestSheerkaIsAManager(TestUsingMemoryBasedSheerka):
|
|||||||
assert number.id not in sheerka.get_concepts_bnf_definitions()
|
assert number.id not in sheerka.get_concepts_bnf_definitions()
|
||||||
|
|
||||||
def test_i_can_get_and_set_isa_when_multiple_ontology_layers(self):
|
def test_i_can_get_and_set_isa_when_multiple_ontology_layers(self):
|
||||||
sheerka, context, foo, group1, group2 = self.init_concepts(
|
sheerka, context, foo, group1, group2 = self.init_test(global_truth=True).with_concepts(
|
||||||
Concept("foo"),
|
Concept("foo"),
|
||||||
Concept("group1"),
|
Concept("group1"),
|
||||||
Concept("group2"),
|
Concept("group2"),
|
||||||
cache_only=False
|
cache_only=False
|
||||||
)
|
).unpack()
|
||||||
|
|
||||||
sheerka.set_isa(context, foo, group1)
|
sheerka.set_isa(context, foo, group1)
|
||||||
|
|
||||||
@@ -401,7 +469,7 @@ class TestSheerkaSetsManagerUsingFileBasedSheerka(TestUsingFileBasedSheerka):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def test_i_can_set_isa(self):
|
def test_i_can_set_isa(self):
|
||||||
sheerka, context, foo, bar, group = self.init_test().with_concepts("foo",
|
sheerka, context, foo, bar, group = self.init_test(global_truth=True).with_concepts("foo",
|
||||||
"bar",
|
"bar",
|
||||||
"group",
|
"group",
|
||||||
).unpack()
|
).unpack()
|
||||||
|
|||||||
@@ -116,6 +116,15 @@ class TestSheerkaMemory(TestUsingMemoryBasedSheerka):
|
|||||||
|
|
||||||
assert sheerka.memory(context, "self.name == 'foo'") == foo
|
assert sheerka.memory(context, "self.name == 'foo'") == foo
|
||||||
|
|
||||||
|
def test_i_can_use_memory_when_the_entry_does_not_exist(self):
|
||||||
|
sheerka, context, foo, bar = self.init_test().with_concepts("foo", "bar", create_new=True).unpack()
|
||||||
|
|
||||||
|
sheerka.add_to_memory(context, "foo", foo) # add at least one element
|
||||||
|
|
||||||
|
res = sheerka.memory(context, "bar")
|
||||||
|
assert sheerka.isinstance(res, BuiltinConcepts.NOT_FOUND)
|
||||||
|
assert res.body == {'#name': 'bar'}
|
||||||
|
|
||||||
def test_i_retrieve_the_last_entry_when_requesting_memory_with_a_query(self):
|
def test_i_retrieve_the_last_entry_when_requesting_memory_with_a_query(self):
|
||||||
sheerka, context, foo, bar, foo2 = self.init_concepts("foo", "bar", Concept("foo", body="2"))
|
sheerka, context, foo, bar, foo2 = self.init_concepts("foo", "bar", Concept("foo", body="2"))
|
||||||
|
|
||||||
|
|||||||
@@ -52,22 +52,16 @@ class TestSheerkaQueryManager(TestUsingMemoryBasedSheerka):
|
|||||||
assert sheerka.filter_objects(context, lst, prop2={"key": "value"}) == [lst[3]]
|
assert sheerka.filter_objects(context, lst, prop2={"key": "value"}) == [lst[3]]
|
||||||
# assert sheerka.filter_objects(context, lst, prop1={1, "v"}) == [lst[2]] set are not supported
|
# assert sheerka.filter_objects(context, lst, prop1={1, "v"}) == [lst[2]] set are not supported
|
||||||
|
|
||||||
|
# complex properties
|
||||||
|
assert sheerka.filter_objects(context, lst, prop1_contains="a") == [lst[0], lst[1]]
|
||||||
|
assert sheerka.filter_objects(context, lst, prop1_contains=1) == [lst[2], lst[3]]
|
||||||
|
|
||||||
def test_i_can_filter_by_object_type(self):
|
def test_i_can_filter_by_object_type(self):
|
||||||
sheerka, context = self.init_test().unpack()
|
sheerka, context = self.init_test().unpack()
|
||||||
lst = [A("a11", "a12"), Concept("foo", body="a").auto_init(), Concept("foo", body="b").auto_init()]
|
lst = [A("a11", "a12"), Concept("foo", body="a").auto_init(), Concept("foo", body="b").auto_init()]
|
||||||
|
|
||||||
assert sheerka.filter_objects(context, lst, __type="foo") == [lst[1], lst[2]]
|
assert sheerka.filter_objects(context, lst, __type="foo") == [lst[1], lst[2]]
|
||||||
|
|
||||||
def test_i_can_filter_on_atomic_def(self):
|
|
||||||
sheerka, context, isa, plus, isa2 = self.init_concepts(
|
|
||||||
Concept('x is a y').def_var("x").def_var("y"),
|
|
||||||
Concept('a plus b').def_var("a").def_var("b"),
|
|
||||||
Concept('u is a v').def_var("u").def_var("v"),
|
|
||||||
)
|
|
||||||
|
|
||||||
lst = [isa, plus, isa2]
|
|
||||||
assert sheerka.filter_objects(context, lst, atomic_def="is a") == [lst[0], lst[2]]
|
|
||||||
|
|
||||||
def test_i_can_filter_on_as_bag_property(self):
|
def test_i_can_filter_on_as_bag_property(self):
|
||||||
sheerka, context = self.init_test().unpack()
|
sheerka, context = self.init_test().unpack()
|
||||||
lst = [B("a11", "a12"), B("a21", "a22"), B("a31", "a32")]
|
lst = [B("a11", "a12"), B("a21", "a22"), B("a31", "a32")]
|
||||||
|
|||||||
@@ -253,6 +253,28 @@ class TestBuiltinHelpers(TestUsingMemoryBasedSheerka):
|
|||||||
# a second time, now that bar is already evaluated
|
# a second time, now that bar is already evaluated
|
||||||
assert core.builtin_helpers.ensure_evaluated(context, bar) == foo
|
assert core.builtin_helpers.ensure_evaluated(context, bar) == foo
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("concept, concepts_parts, expected", [
|
||||||
|
(Concept("foo"), ["where"], 0),
|
||||||
|
(Concept("foo", where="x"), ["where"], 1),
|
||||||
|
(Concept("foo", where="x and y"), ["where"], 2),
|
||||||
|
(Concept("foo", where="x or y"), ["where"], 1),
|
||||||
|
(Concept("foo", where="x or y and z"), ["where"], 2),
|
||||||
|
(Concept("foo", where="not w"), ["where"], 1),
|
||||||
|
(Concept("foo", where=""), ["where"], 0),
|
||||||
|
|
||||||
|
(Concept("foo", pre="x"), ["pre", "where"], 101),
|
||||||
|
(Concept("foo", where="x"), ["pre", "where"], 1),
|
||||||
|
(Concept("foo", where="x and y", pre="z"), ["pre", "where"], 103),
|
||||||
|
|
||||||
|
(Concept("foo", pre="x"), ["pre|where"], 1),
|
||||||
|
(Concept("foo", where="x"), ["pre|where"], 1),
|
||||||
|
(Concept("foo", where="x and y", pre="z"), ["pre|where"], 3),
|
||||||
|
|
||||||
|
])
|
||||||
|
def test_i_can_get_concept_complexity(self, concept, concepts_parts, expected):
|
||||||
|
context = self.get_context()
|
||||||
|
assert core.builtin_helpers.get_concept_complexity(context, concept, concepts_parts) == expected
|
||||||
|
|
||||||
# @pytest.mark.parametrize("return_values", [
|
# @pytest.mark.parametrize("return_values", [
|
||||||
# None,
|
# None,
|
||||||
# []
|
# []
|
||||||
|
|||||||
@@ -559,6 +559,37 @@ class TestSheerkaUsingMemoryBasedSheerka(TestUsingMemoryBasedSheerka):
|
|||||||
ret_val = ReturnValueConcept("Test", True, sheerka.err("an error"))
|
ret_val = ReturnValueConcept("Test", True, sheerka.err("an error"))
|
||||||
assert sheerka.get_errors(context, ret_val) == []
|
assert sheerka.get_errors(context, ret_val) == []
|
||||||
|
|
||||||
|
def test_i_can_add_and_remove_global_context_hints(self):
|
||||||
|
sheerka, context = self.init_test().unpack()
|
||||||
|
|
||||||
|
sheerka.add_to_context(BuiltinConcepts.EVAL_QUESTION_REQUESTED)
|
||||||
|
assert sheerka._global_context_hints == {BuiltinConcepts.EVAL_QUESTION_REQUESTED}
|
||||||
|
|
||||||
|
sheerka.remove_fom_context(BuiltinConcepts.EVAL_QUESTION_REQUESTED)
|
||||||
|
assert sheerka._global_context_hints == set()
|
||||||
|
|
||||||
|
sheerka.add_to_context(sheerka.new(BuiltinConcepts.EVAL_QUESTION_REQUESTED))
|
||||||
|
assert sheerka._global_context_hints == {BuiltinConcepts.EVAL_QUESTION_REQUESTED}
|
||||||
|
|
||||||
|
sheerka.remove_fom_context(sheerka.new(BuiltinConcepts.EVAL_QUESTION_REQUESTED))
|
||||||
|
assert sheerka._global_context_hints == set()
|
||||||
|
|
||||||
|
def test_global_context_hints_are_added_to_every_user_input_execution(self):
|
||||||
|
sheerka, context, foo = self.init_test().with_concepts(
|
||||||
|
Concept("foo", pre="in_context(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED)")
|
||||||
|
).unpack()
|
||||||
|
|
||||||
|
res = sheerka.evaluate_user_input("eval foo", "testing_user")
|
||||||
|
assert sheerka.isinstance(res[0].value, BuiltinConcepts.CONDITION_FAILED) # sanity check
|
||||||
|
|
||||||
|
sheerka.add_to_context(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED)
|
||||||
|
res = sheerka.evaluate_user_input("eval foo", "testing_user")
|
||||||
|
assert sheerka.isinstance(res[0].value, "foo")
|
||||||
|
|
||||||
|
sheerka.remove_fom_context(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED)
|
||||||
|
res = sheerka.evaluate_user_input("eval foo", "testing_user")
|
||||||
|
assert sheerka.isinstance(res[0].value, BuiltinConcepts.CONDITION_FAILED)
|
||||||
|
|
||||||
|
|
||||||
class TestSheerkaUsingFileBasedSheerka(TestUsingFileBasedSheerka):
|
class TestSheerkaUsingFileBasedSheerka(TestUsingFileBasedSheerka):
|
||||||
|
|
||||||
|
|||||||
@@ -842,11 +842,9 @@ class TestSheerkaOntology(TestUsingMemoryBasedSheerka):
|
|||||||
sheerka, context, foo = self.init_concepts("foo", cache_only=False)
|
sheerka, context, foo = self.init_concepts("foo", cache_only=False)
|
||||||
|
|
||||||
manager = SheerkaOntologyManager(sheerka, sheerka.root_folder, sheerka.cache_only)
|
manager = SheerkaOntologyManager(sheerka, sheerka.root_folder, sheerka.cache_only)
|
||||||
cache = Cache(default=lambda sdp, key: sdp.get("by_id", key),
|
cache = Cache().auto_configure("by_id")
|
||||||
extend_exists=lambda sdp, key: sdp.get("by_id", key))
|
|
||||||
manager.register_concept_cache("by_id", cache, lambda obj: obj.id, use_ref=True)
|
manager.register_concept_cache("by_id", cache, lambda obj: obj.id, use_ref=True)
|
||||||
cache = ListIfNeededCache(default=lambda sdp, key: sdp.get("by_key", key),
|
cache = ListIfNeededCache().auto_configure("by_key")
|
||||||
extend_exists=lambda sdp, key: sdp.get("by_key", key))
|
|
||||||
manager.register_concept_cache("by_key", cache, lambda obj: obj.key, use_ref=True)
|
manager.register_concept_cache("by_key", cache, lambda obj: obj.key, use_ref=True)
|
||||||
manager.freeze()
|
manager.freeze()
|
||||||
|
|
||||||
@@ -863,11 +861,9 @@ class TestSheerkaOntology(TestUsingMemoryBasedSheerka):
|
|||||||
sheerka, context, foo = self.init_concepts("foo", cache_only=False)
|
sheerka, context, foo = self.init_concepts("foo", cache_only=False)
|
||||||
|
|
||||||
manager = SheerkaOntologyManager(sheerka, sheerka.root_folder, sheerka.cache_only)
|
manager = SheerkaOntologyManager(sheerka, sheerka.root_folder, sheerka.cache_only)
|
||||||
cache = Cache(default=lambda sdp, key: sdp.get("by_id", key),
|
cache = Cache().auto_configure("by_id")
|
||||||
extend_exists=lambda sdp, key: sdp.get("by_id", key))
|
|
||||||
manager.register_concept_cache("by_id", cache, lambda obj: obj.id, use_ref=True)
|
manager.register_concept_cache("by_id", cache, lambda obj: obj.id, use_ref=True)
|
||||||
cache = ListIfNeededCache(default=lambda sdp, key: sdp.get("by_key", key),
|
cache = ListIfNeededCache().auto_configure("by_key")
|
||||||
extend_exists=lambda sdp, key: sdp.get("by_key", key))
|
|
||||||
manager.register_concept_cache("by_key", cache, lambda obj: obj.key, use_ref=True)
|
manager.register_concept_cache("by_key", cache, lambda obj: obj.key, use_ref=True)
|
||||||
manager.freeze()
|
manager.freeze()
|
||||||
|
|
||||||
@@ -887,15 +883,33 @@ class TestSheerkaOntology(TestUsingMemoryBasedSheerka):
|
|||||||
assert list(manager.ontologies[0].cache_manager.sdp.state.data.keys()) == ['by_id', 'by_key']
|
assert list(manager.ontologies[0].cache_manager.sdp.state.data.keys()) == ['by_id', 'by_key']
|
||||||
assert manager.ontologies[1].cache_manager.sdp.state.data == {}
|
assert manager.ontologies[1].cache_manager.sdp.state.data == {}
|
||||||
|
|
||||||
|
def test_i_can_add_the_concepts_with_the_same_key_from_different_layers(self):
|
||||||
|
sheerka, context, foo_1, foo_2 = self.init_concepts(
|
||||||
|
Concept("foo x", body="x + 1").def_var("x"),
|
||||||
|
Concept("foo x", body="x + 2").def_var("x"),
|
||||||
|
cache_only=False)
|
||||||
|
|
||||||
|
manager = SheerkaOntologyManager(sheerka, sheerka.root_folder, sheerka.cache_only)
|
||||||
|
cache = ListIfNeededCache().auto_configure("by_key")
|
||||||
|
manager.register_concept_cache("by_key", cache, lambda obj: obj.key, use_ref=True)
|
||||||
|
manager.freeze()
|
||||||
|
|
||||||
|
manager.add_concept(foo_1)
|
||||||
|
manager.commit(context)
|
||||||
|
|
||||||
|
manager.push_ontology("new ontology")
|
||||||
|
manager.add_concept(foo_2)
|
||||||
|
manager.commit(context)
|
||||||
|
|
||||||
|
assert manager.current_sdp().get("by_key", foo_1.key) == [foo_1, foo_2]
|
||||||
|
|
||||||
def test_i_can_update_concept_in_default_layer(self):
|
def test_i_can_update_concept_in_default_layer(self):
|
||||||
sheerka, context, foo = self.init_concepts("foo", cache_only=False)
|
sheerka, context, foo = self.init_concepts("foo", cache_only=False)
|
||||||
|
|
||||||
manager = SheerkaOntologyManager(sheerka, sheerka.root_folder, sheerka.cache_only)
|
manager = SheerkaOntologyManager(sheerka, sheerka.root_folder, sheerka.cache_only)
|
||||||
cache = Cache(default=lambda sdp, key: sdp.get("by_id", key),
|
cache = Cache().auto_configure("by_id")
|
||||||
extend_exists=lambda sdp, key: sdp.get("by_id", key))
|
|
||||||
manager.register_concept_cache("by_id", cache, lambda obj: obj.id, use_ref=True)
|
manager.register_concept_cache("by_id", cache, lambda obj: obj.id, use_ref=True)
|
||||||
cache = ListIfNeededCache(default=lambda sdp, key: sdp.get("by_key", key),
|
cache = ListIfNeededCache().auto_configure("by_key")
|
||||||
extend_exists=lambda sdp, key: sdp.get("by_key", key))
|
|
||||||
manager.register_concept_cache("by_key", cache, lambda obj: obj.key, use_ref=True)
|
manager.register_concept_cache("by_key", cache, lambda obj: obj.key, use_ref=True)
|
||||||
manager.freeze()
|
manager.freeze()
|
||||||
|
|
||||||
@@ -953,11 +967,9 @@ class TestSheerkaOntology(TestUsingMemoryBasedSheerka):
|
|||||||
sheerka, context, foo = self.init_concepts("foo", cache_only=False)
|
sheerka, context, foo = self.init_concepts("foo", cache_only=False)
|
||||||
|
|
||||||
manager = SheerkaOntologyManager(sheerka, sheerka.root_folder, sheerka.cache_only)
|
manager = SheerkaOntologyManager(sheerka, sheerka.root_folder, sheerka.cache_only)
|
||||||
cache = Cache(default=lambda sdp, key: sdp.get("by_id", key),
|
cache = Cache().auto_configure("by_id")
|
||||||
extend_exists=lambda sdp, key: sdp.get("by_id", key))
|
|
||||||
manager.register_concept_cache("by_id", cache, lambda obj: obj.id, use_ref=True)
|
manager.register_concept_cache("by_id", cache, lambda obj: obj.id, use_ref=True)
|
||||||
cache = ListIfNeededCache(default=lambda sdp, key: sdp.get("by_key", key),
|
cache = ListIfNeededCache().auto_configure("by_key")
|
||||||
extend_exists=lambda sdp, key: sdp.get("by_key", key))
|
|
||||||
manager.register_concept_cache("by_key", cache, lambda obj: obj.key, use_ref=True)
|
manager.register_concept_cache("by_key", cache, lambda obj: obj.key, use_ref=True)
|
||||||
manager.freeze()
|
manager.freeze()
|
||||||
|
|
||||||
|
|||||||
@@ -193,6 +193,8 @@ def test_i_can_escape():
|
|||||||
("c:|id:", None, "id"),
|
("c:|id:", None, "id"),
|
||||||
("c:key|:", "key", None),
|
("c:key|:", "key", None),
|
||||||
("c:key|id:x", None, None),
|
("c:key|id:x", None, None),
|
||||||
|
("c:one: plus c:two:", None, None),
|
||||||
|
("c:one|id: plus c:two:", None, None),
|
||||||
])
|
])
|
||||||
def test_i_can_unstr_concept(text, expected_key, expected_id):
|
def test_i_can_unstr_concept(text, expected_key, expected_id):
|
||||||
k, i = core.utils.unstr_concept(text)
|
k, i = core.utils.unstr_concept(text)
|
||||||
@@ -494,3 +496,19 @@ def test_sheerka_hasattr_get_attr():
|
|||||||
assert not core.utils.sheerka_hasattr(concept, "b")
|
assert not core.utils.sheerka_hasattr(concept, "b")
|
||||||
with pytest.raises(AttributeError):
|
with pytest.raises(AttributeError):
|
||||||
core.utils.sheerka_getattr(concept, "b")
|
core.utils.sheerka_getattr(concept, "b")
|
||||||
|
|
||||||
|
|
||||||
|
def test_i_can_replace_after():
|
||||||
|
my_new_items = ["alpha", "beta", "gamma"]
|
||||||
|
|
||||||
|
my_list1 = ["a", "b", "c", "d"]
|
||||||
|
core.utils.replace_after(my_list1, "c", my_new_items)
|
||||||
|
assert my_list1 == ["a", "b", "alpha", "beta", "gamma"]
|
||||||
|
|
||||||
|
my_list2 = ["a", "b", "c", "d"]
|
||||||
|
core.utils.replace_after(my_list2, "a", my_new_items)
|
||||||
|
assert my_list2 == ["alpha", "beta", "gamma"]
|
||||||
|
|
||||||
|
with pytest.raises(KeyError):
|
||||||
|
my_list3 = ["a", "b", "c", "d"]
|
||||||
|
core.utils.replace_after(my_list3, "x", my_new_items)
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept, BuiltinConcepts
|
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept, BuiltinConcepts
|
||||||
from core.concept import Concept
|
from core.concept import Concept
|
||||||
from core.tokenizer import Tokenizer
|
from core.tokenizer import Tokenizer
|
||||||
from evaluators.AddConceptInSetEvaluator import AddConceptInSetEvaluator
|
from evaluators.AddConceptInSetEvaluator import AddConceptInSetEvaluator
|
||||||
from parsers.DefConceptParser import IsaConceptNode, NameNode
|
from parsers.DefConceptParser import IsaConceptNode, NameNode
|
||||||
|
|
||||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||||
|
|
||||||
|
|
||||||
@@ -51,7 +51,20 @@ class TestAddConceptInSetEvaluator(TestUsingMemoryBasedSheerka):
|
|||||||
assert res.value.body == "bar"
|
assert res.value.body == "bar"
|
||||||
|
|
||||||
def test_i_can_add_concept_to_a_set_of_concept(self):
|
def test_i_can_add_concept_to_a_set_of_concept(self):
|
||||||
sheerka, context, foo, bar = self.init_test().with_concepts("foo", "bar", create_new=True).unpack()
|
sheerka, context, foo, bar = self.init_test().with_concepts("foo", "bar").unpack()
|
||||||
|
ret_val = get_isa_ret_val("foo", "bar")
|
||||||
|
|
||||||
|
res = AddConceptInSetEvaluator().eval(context, ret_val)
|
||||||
|
foo = res.body # get the created instance
|
||||||
|
|
||||||
|
assert res.status
|
||||||
|
assert context.sheerka.isinstance(res.value, foo.key)
|
||||||
|
assert context.sheerka.isa(foo, bar)
|
||||||
|
|
||||||
|
assert foo.get_prop(BuiltinConcepts.ISA) == {bar}
|
||||||
|
|
||||||
|
def test_i_can_add_concept_to_a_set_of_concept_when_global_truth_is_activated(self):
|
||||||
|
sheerka, context, foo, bar = self.init_test(global_truth=True).with_concepts("foo", "bar").unpack()
|
||||||
ret_val = get_isa_ret_val("foo", "bar")
|
ret_val = get_isa_ret_val("foo", "bar")
|
||||||
|
|
||||||
res = AddConceptInSetEvaluator().eval(context, ret_val)
|
res = AddConceptInSetEvaluator().eval(context, ret_val)
|
||||||
@@ -65,19 +78,18 @@ class TestAddConceptInSetEvaluator(TestUsingMemoryBasedSheerka):
|
|||||||
|
|
||||||
assert foo.get_prop(BuiltinConcepts.ISA) == {bar}
|
assert foo.get_prop(BuiltinConcepts.ISA) == {bar}
|
||||||
|
|
||||||
def test_i_can_add_bnf_concept_to_a_set_of_concept(self):
|
def test_i_can_add_bnf_concept_to_a_set_of_concept_when_global_truth_is_activated(self):
|
||||||
"""
|
"""
|
||||||
This test is the reason why I have started the whole eval on demand stuff
|
This test is the reason why I have started the whole eval on demand stuff
|
||||||
Sheerka tries to evaluate the body but it can't (as a and b are not defined)
|
Sheerka tries to evaluate the body but it can't (as a and b are not defined)
|
||||||
So 'foo' cannot be put is set
|
So 'foo' cannot be put is set
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
sheerka, context, one, two, foo, bar = self.init_test().with_concepts(
|
sheerka, context, one, two, foo, bar = self.init_test(global_truth=True).with_concepts(
|
||||||
"one",
|
"one",
|
||||||
"two",
|
"two",
|
||||||
Concept("foo", definition="(one|two)=a 'plus' (one|two)=b", body="a + b").def_var("a").def_var("b"),
|
Concept("foo", definition="(one|two)=a 'plus' (one|two)=b", body="a + b").def_var("a").def_var("b"),
|
||||||
"bar",
|
"bar").unpack()
|
||||||
create_new=True).unpack()
|
|
||||||
|
|
||||||
ret_val = get_isa_ret_val("foo", "bar")
|
ret_val = get_isa_ret_val("foo", "bar")
|
||||||
res = AddConceptInSetEvaluator().eval(context, ret_val)
|
res = AddConceptInSetEvaluator().eval(context, ret_val)
|
||||||
@@ -103,11 +115,25 @@ class TestAddConceptInSetEvaluator(TestUsingMemoryBasedSheerka):
|
|||||||
ret_val = get_isa_ret_val("foo", "bar")
|
ret_val = get_isa_ret_val("foo", "bar")
|
||||||
res = AddConceptInSetEvaluator().eval(context, ret_val)
|
res = AddConceptInSetEvaluator().eval(context, ret_val)
|
||||||
|
|
||||||
|
assert res.status
|
||||||
|
assert context.sheerka.isinstance(res.value, foo.key)
|
||||||
|
|
||||||
|
def test_i_can_add_concept_with_a_body_to_a_set_of_concept_when_global_truth_is_activated(self):
|
||||||
|
context = self.get_context(global_truth=True)
|
||||||
|
foo = Concept("foo", body="1")
|
||||||
|
context.sheerka.create_new_concept(context, foo)
|
||||||
|
|
||||||
|
bar = Concept("bar")
|
||||||
|
context.sheerka.create_new_concept(context, bar)
|
||||||
|
|
||||||
|
ret_val = get_isa_ret_val("foo", "bar")
|
||||||
|
res = AddConceptInSetEvaluator().eval(context, ret_val)
|
||||||
|
|
||||||
assert res.status
|
assert res.status
|
||||||
assert context.sheerka.isinstance(res.value, BuiltinConcepts.SUCCESS)
|
assert context.sheerka.isinstance(res.value, BuiltinConcepts.SUCCESS)
|
||||||
|
|
||||||
def test_i_cannot_add_the_same_concept_twice(self):
|
def test_i_cannot_add_the_same_concept_twice(self):
|
||||||
sheerka, context, foo, bar = self.init_test().with_concepts("foo", "bar", create_new=True).unpack()
|
sheerka, context, foo, bar = self.init_test(global_truth=True).with_concepts("foo", "bar").unpack()
|
||||||
|
|
||||||
ret_val = get_isa_ret_val("foo", "bar")
|
ret_val = get_isa_ret_val("foo", "bar")
|
||||||
AddConceptInSetEvaluator().eval(context, ret_val)
|
AddConceptInSetEvaluator().eval(context, ret_val)
|
||||||
|
|||||||
@@ -43,7 +43,8 @@ class TestExpressionEvaluator(TestUsingMemoryBasedSheerka):
|
|||||||
assert not res.body
|
assert not res.body
|
||||||
|
|
||||||
# second time
|
# second time
|
||||||
sheerka.set_isa(context, one, number)
|
global_truth_context = self.get_context(sheerka, global_truth=True)
|
||||||
|
sheerka.set_isa(global_truth_context, one, number)
|
||||||
parsed_return_value = ExpressionParser().parse(context, ParserInput("one is a number"))
|
parsed_return_value = ExpressionParser().parse(context, ParserInput("one is a number"))
|
||||||
res = evaluator.eval(context, parsed_return_value)
|
res = evaluator.eval(context, parsed_return_value)
|
||||||
assert res.status
|
assert res.status
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept, UserInputConcept
|
||||||
|
from core.concept import Concept
|
||||||
|
from evaluators.PrepareEvalGlobalTruthEvaluator import PrepareEvalGlobalTruthEvaluator
|
||||||
|
|
||||||
|
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||||
|
|
||||||
|
r = ReturnValueConcept
|
||||||
|
|
||||||
|
|
||||||
|
class TestPrepareEvalGlobalTruthEvaluator(TestUsingMemoryBasedSheerka):
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("ret_val, expected", [
|
||||||
|
(r("name", True, UserInputConcept("global_truth(1 + 1)")), True),
|
||||||
|
(r("name", True, UserInputConcept(" global_truth(1 + 1) ")), True),
|
||||||
|
(r("name", True, UserInputConcept("global_truth()")), False),
|
||||||
|
(r("name", True, UserInputConcept("1+1")), False),
|
||||||
|
(r("name", True, UserInputConcept("")), False),
|
||||||
|
(r("name", True, UserInputConcept("global_truth(")), False),
|
||||||
|
(r("name", True, UserInputConcept(")")), False),
|
||||||
|
(r("name", True, UserInputConcept([])), False),
|
||||||
|
(r("name", True, Concept("foo")), False),
|
||||||
|
(r("name", True, "not a concept"), False),
|
||||||
|
(r("name", False, UserInputConcept("global_truth(1 + 1)")), False),
|
||||||
|
])
|
||||||
|
def test_i_can_match(self, ret_val, expected):
|
||||||
|
context = self.get_context()
|
||||||
|
assert PrepareEvalGlobalTruthEvaluator().matches(context, ret_val) == expected
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("ret_val, expected", [
|
||||||
|
(r("name", True, UserInputConcept("global_truth(1 + 1)")), "1 + 1"),
|
||||||
|
(r("name", True, UserInputConcept(" global_truth( 1 + 1 ) ")), "1 + 1"),
|
||||||
|
])
|
||||||
|
def test_i_can_eval(self, ret_val, expected):
|
||||||
|
context = self.get_context()
|
||||||
|
sheerka = context.sheerka
|
||||||
|
|
||||||
|
prepare_evaluator = PrepareEvalGlobalTruthEvaluator()
|
||||||
|
prepare_evaluator.matches(context, ret_val)
|
||||||
|
res = prepare_evaluator.eval(context, ret_val)
|
||||||
|
|
||||||
|
assert res.status
|
||||||
|
assert sheerka.isinstance(res.body, BuiltinConcepts.USER_INPUT)
|
||||||
|
assert res.body.body == expected
|
||||||
|
|
||||||
|
assert BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED in context.protected_hints
|
||||||
|
assert BuiltinConcepts.EVAL_BODY_REQUESTED in context.protected_hints
|
||||||
|
assert BuiltinConcepts.RETURN_BODY_REQUESTED in context.protected_hints
|
||||||
@@ -1,12 +1,15 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from core.builtin_concepts import BuiltinConcepts
|
from core.builtin_concepts import BuiltinConcepts
|
||||||
from core.concept import Concept
|
from core.concept import Concept
|
||||||
|
from core.sheerka.services.SheerkaExecute import ParserInput
|
||||||
|
from evaluators.BaseEvaluator import BaseEvaluator
|
||||||
from evaluators.ResolveAmbiguityEvaluator import ResolveAmbiguityEvaluator
|
from evaluators.ResolveAmbiguityEvaluator import ResolveAmbiguityEvaluator
|
||||||
|
from parsers.ExactConceptParser import ExactConceptParser
|
||||||
|
from parsers.SyaNodeParser import SyaNodeParser
|
||||||
from tests.BaseTest import BaseTest
|
from tests.BaseTest import BaseTest
|
||||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||||
|
|
||||||
|
|
||||||
pretval = BaseTest.pretval
|
pretval = BaseTest.pretval
|
||||||
|
|
||||||
|
|
||||||
@@ -21,6 +24,37 @@ class TestResolveAmbiguityEvaluator(TestUsingMemoryBasedSheerka):
|
|||||||
context = self.get_context()
|
context = self.get_context()
|
||||||
assert ResolveAmbiguityEvaluator().matches(context, return_values) == expected
|
assert ResolveAmbiguityEvaluator().matches(context, return_values) == expected
|
||||||
|
|
||||||
|
def test_i_can_match_when_the_input_comes_from_an_evaluator(self):
|
||||||
|
ret_val1 = pretval(Concept("foo"), source="source", parser=BaseEvaluator.get_name("evaluator"))
|
||||||
|
ret_val2 = pretval(Concept("bar"), source="source", parser=BaseEvaluator.get_name("evaluator"))
|
||||||
|
return_values = [ret_val1, ret_val2]
|
||||||
|
|
||||||
|
context = self.get_context()
|
||||||
|
assert ResolveAmbiguityEvaluator().matches(context, return_values)
|
||||||
|
|
||||||
|
def test_i_can_match_when_concept_nodes(self):
|
||||||
|
sheerka, context, a, foo_1, foo_2 = self.init_concepts(
|
||||||
|
Concept("a"),
|
||||||
|
Concept("foo x").def_var("x"),
|
||||||
|
Concept("foo y").def_var("y"),
|
||||||
|
create_new=True
|
||||||
|
)
|
||||||
|
|
||||||
|
return_values = SyaNodeParser().parse(context, ParserInput("foo a"))
|
||||||
|
assert ResolveAmbiguityEvaluator().matches(context, return_values)
|
||||||
|
|
||||||
|
def test_i_can_match_when_concept_node_mixed_with_concept(self):
|
||||||
|
sheerka, context, a, foo_1, foo_a = self.init_concepts(
|
||||||
|
Concept("a"),
|
||||||
|
Concept("foo x").def_var("x"),
|
||||||
|
Concept("foo a"),
|
||||||
|
create_new=True
|
||||||
|
)
|
||||||
|
|
||||||
|
sya_return_value = SyaNodeParser().parse(context, ParserInput("foo a"))
|
||||||
|
|
||||||
|
assert ResolveAmbiguityEvaluator().matches(context, [sya_return_value, pretval(foo_a, source="foo a")])
|
||||||
|
|
||||||
def test_i_can_manage_when_no_source(self):
|
def test_i_can_manage_when_no_source(self):
|
||||||
context = self.get_context()
|
context = self.get_context()
|
||||||
return_values = [BaseTest.retval(Concept("foo"))]
|
return_values = [BaseTest.retval(Concept("foo"))]
|
||||||
@@ -53,6 +87,44 @@ class TestResolveAmbiguityEvaluator(TestUsingMemoryBasedSheerka):
|
|||||||
return_values[2],
|
return_values[2],
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("concepts, expected", [
|
||||||
|
([Concept("c1"), Concept("c2", where="True")], "c2"),
|
||||||
|
([Concept("c1"), Concept("c2", pre="True")], "c2"),
|
||||||
|
([Concept("c1"), Concept("c2", where="False")], "c1"),
|
||||||
|
([Concept("c1"), Concept("c2", pre="False")], "c1"),
|
||||||
|
([Concept("c1", pre="True"), Concept("c2", where="True")], "c1"),
|
||||||
|
([Concept("c1", pre="False"), Concept("c2", where="True")], "c2"),
|
||||||
|
([Concept("c1", pre="False"), Concept("c2", where="False")], BuiltinConcepts.NO_RESULT),
|
||||||
|
])
|
||||||
|
def test_i_can_eval_2(self, concepts, expected):
|
||||||
|
context = self.get_context()
|
||||||
|
return_values = [self.pretval(c, source="foo") for c in concepts]
|
||||||
|
|
||||||
|
evaluator = ResolveAmbiguityEvaluator()
|
||||||
|
evaluator.matches(context, return_values)
|
||||||
|
res = evaluator.eval(context, return_values)
|
||||||
|
|
||||||
|
assert len(res) == 1
|
||||||
|
if expected != BuiltinConcepts.NO_RESULT:
|
||||||
|
selected_concept = res[0].body.body
|
||||||
|
assert selected_concept.name == expected
|
||||||
|
else:
|
||||||
|
assert res[0].body == BuiltinConcepts.NO_RESULT
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("concepts", [
|
||||||
|
[Concept("c1"), Concept("c2")],
|
||||||
|
[Concept("c1", pre="True"), Concept("c2", pre="True")],
|
||||||
|
])
|
||||||
|
def test_i_can_eval_when_same_complexity(self, concepts):
|
||||||
|
context = self.get_context()
|
||||||
|
return_values = [self.pretval(c, "foo") for c in concepts]
|
||||||
|
|
||||||
|
evaluator = ResolveAmbiguityEvaluator()
|
||||||
|
evaluator.matches(context, return_values)
|
||||||
|
res = evaluator.eval(context, return_values)
|
||||||
|
|
||||||
|
assert res is None
|
||||||
|
|
||||||
def test_i_can_eval_all_fail(self):
|
def test_i_can_eval_all_fail(self):
|
||||||
context = self.get_context()
|
context = self.get_context()
|
||||||
return_values = [
|
return_values = [
|
||||||
@@ -91,3 +163,70 @@ class TestResolveAmbiguityEvaluator(TestUsingMemoryBasedSheerka):
|
|||||||
res = evaluator.eval(context, return_values)
|
res = evaluator.eval(context, return_values)
|
||||||
|
|
||||||
assert res is None
|
assert res is None
|
||||||
|
|
||||||
|
def test_i_can_eval_to_the_simplest_concept(self):
|
||||||
|
"""
|
||||||
|
def concept foo x where x
|
||||||
|
def concept foo a
|
||||||
|
|
||||||
|
When the input is foo a, 'foo x' must be discarded as concept 'foo a' is more accurate
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
sheerka, context, a, foo_1, foo_a = self.init_concepts(
|
||||||
|
Concept("a"),
|
||||||
|
Concept("foo x").def_var("x"),
|
||||||
|
Concept("foo a"),
|
||||||
|
create_new=True
|
||||||
|
)
|
||||||
|
|
||||||
|
sya_return_value = SyaNodeParser().parse(context, ParserInput("foo a"))
|
||||||
|
exact_concept_return_value = pretval(foo_a, source="foo a")
|
||||||
|
return_values = [sya_return_value, exact_concept_return_value]
|
||||||
|
evaluator = ResolveAmbiguityEvaluator()
|
||||||
|
|
||||||
|
evaluator.matches(context, return_values)
|
||||||
|
res = evaluator.eval(context, return_values)
|
||||||
|
|
||||||
|
assert len(res) == 1
|
||||||
|
assert res[0].who == evaluator.name
|
||||||
|
assert res[0].body == exact_concept_return_value.body
|
||||||
|
assert res[0].parents == return_values
|
||||||
|
|
||||||
|
def test_i_can_eval_to_the_simplest_concept_when_concept_nodes(self):
|
||||||
|
"""
|
||||||
|
Same explanation than test_i_can_eval_to_the_simplest_concept()
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
sheerka, context, a, b, foo_1, foo_2 = self.init_concepts(
|
||||||
|
Concept("a"),
|
||||||
|
Concept("b"),
|
||||||
|
Concept("foo x y").def_var("x").def_var("y"),
|
||||||
|
Concept("foo a x").def_var("x"),
|
||||||
|
create_new=True
|
||||||
|
)
|
||||||
|
|
||||||
|
return_values = SyaNodeParser().parse(context, ParserInput("foo a b"))
|
||||||
|
evaluator = ResolveAmbiguityEvaluator()
|
||||||
|
|
||||||
|
evaluator.matches(context, return_values)
|
||||||
|
res = evaluator.eval(context, return_values)
|
||||||
|
|
||||||
|
assert len(res) == 1
|
||||||
|
assert res[0].who == evaluator.name
|
||||||
|
assert sheerka.isinstance(res[0].body.body[0].concept, foo_2)
|
||||||
|
|
||||||
|
def test_i_can_eval_when_non_instance_concepts(self):
|
||||||
|
sheerka, context, foo_1, foo_2 = self.init_concepts(
|
||||||
|
Concept("foo x", body="1", pre="True").def_var("x"),
|
||||||
|
Concept("foo x", body="2", pre="True").def_var("x"),
|
||||||
|
create_new=True
|
||||||
|
)
|
||||||
|
|
||||||
|
exact_parser_return_values = ExactConceptParser().parse(context, ParserInput("c:foo x:"))
|
||||||
|
evaluator = ResolveAmbiguityEvaluator()
|
||||||
|
|
||||||
|
evaluator.matches(context, exact_parser_return_values)
|
||||||
|
res = evaluator.eval(context, exact_parser_return_values)
|
||||||
|
|
||||||
|
assert res is None # means that there is nothing to resolve as the concepts are not instances
|
||||||
|
|||||||
@@ -185,14 +185,3 @@ class TestValidateConceptEvaluator(TestUsingMemoryBasedSheerka):
|
|||||||
assert not res.status
|
assert not res.status
|
||||||
assert sheerka.isinstance(res.body, BuiltinConcepts.FILTERED)
|
assert sheerka.isinstance(res.body, BuiltinConcepts.FILTERED)
|
||||||
assert res.body.body == ret_val.body.body
|
assert res.body.body == ret_val.body.body
|
||||||
|
|
||||||
def test_i_can_manage_infinite_recursion(self):
|
|
||||||
sheerka, context, a_and_b = self.init_concepts(
|
|
||||||
Concept("a and b", where="is_question()", body="a and b").def_var("a").def_var("b"),
|
|
||||||
create_new=True)
|
|
||||||
evaluator = ValidateConceptEvaluator()
|
|
||||||
|
|
||||||
ret_val = pr_ret_val(a_and_b)
|
|
||||||
res = evaluator.eval(context, ret_val)
|
|
||||||
|
|
||||||
assert res is None # infinite recursion detected, res is None to drop the validator
|
|
||||||
|
|||||||
@@ -362,6 +362,7 @@ as:
|
|||||||
])
|
])
|
||||||
def test_i_can_mix_concept_with_python_to_define_numbers(self, desc, definitions):
|
def test_i_can_mix_concept_with_python_to_define_numbers(self, desc, definitions):
|
||||||
sheerka = self.get_sheerka()
|
sheerka = self.get_sheerka()
|
||||||
|
sheerka.add_to_context(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED)
|
||||||
|
|
||||||
for definition in definitions:
|
for definition in definitions:
|
||||||
sheerka.evaluate_user_input(definition)
|
sheerka.evaluate_user_input(definition)
|
||||||
@@ -396,6 +397,7 @@ as:
|
|||||||
assert len(res) == 1
|
assert len(res) == 1
|
||||||
assert res[0].status
|
assert res[0].status
|
||||||
assert res[0].body == 23
|
assert res[0].body == 23
|
||||||
|
sheerka.remove_fom_context(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED)
|
||||||
|
|
||||||
def test_i_can_mix_bnf_and_isa(self):
|
def test_i_can_mix_bnf_and_isa(self):
|
||||||
"""
|
"""
|
||||||
@@ -406,8 +408,8 @@ as:
|
|||||||
sheerka.evaluate_user_input("def concept one as 1")
|
sheerka.evaluate_user_input("def concept one as 1")
|
||||||
sheerka.evaluate_user_input("def concept two as 2")
|
sheerka.evaluate_user_input("def concept two as 2")
|
||||||
sheerka.evaluate_user_input("def concept number")
|
sheerka.evaluate_user_input("def concept number")
|
||||||
sheerka.evaluate_user_input("set_isa(one, number)")
|
sheerka.evaluate_user_input("global_truth(set_isa(one, number))")
|
||||||
sheerka.evaluate_user_input("set_isa(two, number)")
|
sheerka.evaluate_user_input("global_truth(set_isa(two, number))")
|
||||||
sheerka.evaluate_user_input("def concept twenties from bnf 'twenty' number as 20 + number")
|
sheerka.evaluate_user_input("def concept twenties from bnf 'twenty' number as 20 + number")
|
||||||
|
|
||||||
res = sheerka.evaluate_user_input("twenty one")
|
res = sheerka.evaluate_user_input("twenty one")
|
||||||
@@ -443,6 +445,7 @@ as:
|
|||||||
|
|
||||||
def test_i_can_mix_bnf_and_isa_2(self):
|
def test_i_can_mix_bnf_and_isa_2(self):
|
||||||
sheerka = self.get_sheerka()
|
sheerka = self.get_sheerka()
|
||||||
|
sheerka.add_to_context(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED)
|
||||||
|
|
||||||
init = [
|
init = [
|
||||||
"def concept one as 1",
|
"def concept one as 1",
|
||||||
@@ -460,6 +463,7 @@ as:
|
|||||||
assert len(res) == 1
|
assert len(res) == 1
|
||||||
assert res[0].status
|
assert res[0].status
|
||||||
assert res[0].body == 21
|
assert res[0].body == 21
|
||||||
|
sheerka.remove_fom_context(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED)
|
||||||
|
|
||||||
def test_i_can_use_concepts_defined_with_from(self):
|
def test_i_can_use_concepts_defined_with_from(self):
|
||||||
sheerka = self.get_sheerka()
|
sheerka = self.get_sheerka()
|
||||||
@@ -565,7 +569,7 @@ as:
|
|||||||
"def concept plus_one from bnf number=n1 'plus_one' as n1 + 1",
|
"def concept plus_one from bnf number=n1 'plus_one' as n1 + 1",
|
||||||
]
|
]
|
||||||
|
|
||||||
sheerka = self.init_scenario(definitions)
|
sheerka = self.init_scenario(definitions, global_truth=True)
|
||||||
|
|
||||||
res = sheerka.evaluate_user_input("eval two plus_one")
|
res = sheerka.evaluate_user_input("eval two plus_one")
|
||||||
assert len(res) == 1
|
assert len(res) == 1
|
||||||
@@ -642,8 +646,6 @@ as:
|
|||||||
assert res[0].body == 21
|
assert res[0].body == 21
|
||||||
|
|
||||||
def test_i_can_use_where_in_bnf(self):
|
def test_i_can_use_where_in_bnf(self):
|
||||||
sheerka, context = self.init_test().unpack()
|
|
||||||
|
|
||||||
init = [
|
init = [
|
||||||
"def concept one as 1",
|
"def concept one as 1",
|
||||||
"def concept two as 2",
|
"def concept two as 2",
|
||||||
@@ -656,8 +658,8 @@ as:
|
|||||||
"def concept twenties from bnf twenty number where number <= 2 as twenty + number"
|
"def concept twenties from bnf twenty number where number <= 2 as twenty + number"
|
||||||
]
|
]
|
||||||
|
|
||||||
for exp in init:
|
sheerka = self.init_scenario(init, global_truth=True)
|
||||||
sheerka.evaluate_user_input(exp)
|
context = self.get_context(sheerka)
|
||||||
|
|
||||||
res = sheerka.evaluate_user_input("twenty one")
|
res = sheerka.evaluate_user_input("twenty one")
|
||||||
assert len(res) == 1
|
assert len(res) == 1
|
||||||
@@ -765,7 +767,7 @@ as:
|
|||||||
sheerka.evaluate_user_input("def concept two as 2")
|
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")
|
sheerka.evaluate_user_input("def concept twenties from bnf 'twenty' (one|two)=unit as 20 + unit")
|
||||||
|
|
||||||
res = sheerka.evaluate_user_input("set_isa(twenties, number)")
|
res = sheerka.evaluate_user_input("global_truth(set_isa(twenties, number))")
|
||||||
assert len(res) == 1
|
assert len(res) == 1
|
||||||
assert res[0].status
|
assert res[0].status
|
||||||
|
|
||||||
@@ -946,7 +948,7 @@ as:
|
|||||||
"set_isa(twenties, number)",
|
"set_isa(twenties, number)",
|
||||||
]
|
]
|
||||||
|
|
||||||
sheerka = self.init_scenario(init)
|
sheerka = self.init_scenario(init, global_truth=True)
|
||||||
|
|
||||||
# simulate that sheerka was stopped and restarted
|
# simulate that sheerka was stopped and restarted
|
||||||
sheerka.clear_bnf_definition()
|
sheerka.clear_bnf_definition()
|
||||||
@@ -967,8 +969,8 @@ as:
|
|||||||
res = sheerka.evaluate_user_input("set_isa(last_created_concept(), number)")
|
res = sheerka.evaluate_user_input("set_isa(last_created_concept(), number)")
|
||||||
|
|
||||||
assert res[0].status
|
assert res[0].status
|
||||||
assert sheerka.isinstance(res[0].body, BuiltinConcepts.SUCCESS)
|
assert sheerka.isinstance(res[0].body, "one")
|
||||||
assert sheerka.isa(sheerka.new("one"), sheerka.new("number"))
|
assert sheerka.isa(res[0].body, sheerka.new("number"))
|
||||||
|
|
||||||
def test_i_can_evaluate_sya_and_ret_concepts(self):
|
def test_i_can_evaluate_sya_and_ret_concepts(self):
|
||||||
init = [
|
init = [
|
||||||
@@ -1001,7 +1003,7 @@ as:
|
|||||||
# Since command is a __COMMAND, the body is auto evaluated
|
# Since command is a __COMMAND, the body is auto evaluated
|
||||||
# and we return the body, not the concept
|
# and we return the body, not the concept
|
||||||
|
|
||||||
sheerka = self.init_scenario(init)
|
sheerka = self.init_scenario(init, global_truth=True)
|
||||||
res = sheerka.evaluate_user_input("command")
|
res = sheerka.evaluate_user_input("command")
|
||||||
assert res[0].status
|
assert res[0].status
|
||||||
assert res[0].body == "Executed !"
|
assert res[0].body == "Executed !"
|
||||||
@@ -1016,7 +1018,7 @@ as:
|
|||||||
"def concept x is a y as set_isa(x,y)",
|
"def concept x is a y as set_isa(x,y)",
|
||||||
]
|
]
|
||||||
|
|
||||||
sheerka = self.init_scenario(init)
|
sheerka = self.init_scenario(init, global_truth=True)
|
||||||
res = sheerka.evaluate_user_input("question(one is a number)") # automatically evaluated
|
res = sheerka.evaluate_user_input("question(one is a number)") # automatically evaluated
|
||||||
assert len(res) == 1
|
assert len(res) == 1
|
||||||
assert res[0].status
|
assert res[0].status
|
||||||
@@ -1042,7 +1044,7 @@ as:
|
|||||||
# So the first one should be picked.
|
# So the first one should be picked.
|
||||||
# the second concept 'one' 's value is an integer, to make sure that it won't be rejected because of its type
|
# the second concept 'one' 's value is an integer, to make sure that it won't be rejected because of its type
|
||||||
|
|
||||||
sheerka = self.init_scenario(init)
|
sheerka = self.init_scenario(init, global_truth=True)
|
||||||
res = sheerka.evaluate_user_input("def concept x plus y where x is a number as x + y")
|
res = sheerka.evaluate_user_input("def concept x plus y where x is a number as x + y")
|
||||||
assert len(res) == 1
|
assert len(res) == 1
|
||||||
assert res[0].status
|
assert res[0].status
|
||||||
@@ -1065,7 +1067,7 @@ as:
|
|||||||
"set_is_greater_than(BuiltinConcepts.PRECEDENCE, c:is_a:, c:q:, 'Sya')",
|
"set_is_greater_than(BuiltinConcepts.PRECEDENCE, c:is_a:, c:q:, 'Sya')",
|
||||||
]
|
]
|
||||||
|
|
||||||
sheerka = self.init_scenario(init)
|
sheerka = self.init_scenario(init, global_truth=True)
|
||||||
res = sheerka.evaluate_user_input("one is a number ?") # automatically evaluated
|
res = sheerka.evaluate_user_input("one is a number ?") # automatically evaluated
|
||||||
assert len(res) == 1
|
assert len(res) == 1
|
||||||
assert res[0].status
|
assert res[0].status
|
||||||
@@ -1133,7 +1135,7 @@ as:
|
|||||||
res = sheerka.evaluate_user_input("twenty one")
|
res = sheerka.evaluate_user_input("twenty one")
|
||||||
assert len(res) > 1 # not recognized
|
assert len(res) > 1 # not recognized
|
||||||
|
|
||||||
sheerka.evaluate_user_input("set_isa(one, number)")
|
sheerka.evaluate_user_input("global_truth(set_isa(one, number))")
|
||||||
res = sheerka.evaluate_user_input("twenty one")
|
res = sheerka.evaluate_user_input("twenty one")
|
||||||
assert len(res) == 1
|
assert len(res) == 1
|
||||||
assert res[0].status
|
assert res[0].status
|
||||||
@@ -1252,9 +1254,9 @@ as:
|
|||||||
"def concept two",
|
"def concept two",
|
||||||
"def concept number",
|
"def concept number",
|
||||||
"def concept nb times from bnf number 'times'",
|
"def concept nb times from bnf number 'times'",
|
||||||
"set_isa(two, number)",
|
"set_isa(two, number)", # defined after 'nb times'
|
||||||
]
|
]
|
||||||
sheerka = self.init_scenario(init)
|
sheerka = self.init_scenario(init, global_truth=True)
|
||||||
|
|
||||||
res = sheerka.evaluate_user_input("two times")
|
res = sheerka.evaluate_user_input("two times")
|
||||||
|
|
||||||
@@ -1270,7 +1272,7 @@ as:
|
|||||||
"def concept cars",
|
"def concept cars",
|
||||||
"def concept quantify x from bnf number x as set_attr(x, 'qty', number) ret x"
|
"def concept quantify x from bnf number x as set_attr(x, 'qty', number) ret x"
|
||||||
]
|
]
|
||||||
sheerka = self.init_scenario(init)
|
sheerka = self.init_scenario(init, global_truth=True)
|
||||||
|
|
||||||
res = sheerka.evaluate_user_input("eval two cars")
|
res = sheerka.evaluate_user_input("eval two cars")
|
||||||
|
|
||||||
@@ -1287,7 +1289,7 @@ as:
|
|||||||
"def concept cars",
|
"def concept cars",
|
||||||
"def concept quantify x from bnf number=n1 x as set_attr(x, 'qty', n1) ret x"
|
"def concept quantify x from bnf number=n1 x as set_attr(x, 'qty', n1) ret x"
|
||||||
]
|
]
|
||||||
sheerka = self.init_scenario(init)
|
sheerka = self.init_scenario(init, global_truth=True)
|
||||||
|
|
||||||
res = sheerka.evaluate_user_input("eval two cars")
|
res = sheerka.evaluate_user_input("eval two cars")
|
||||||
|
|
||||||
@@ -1317,7 +1319,7 @@ as:
|
|||||||
"def concept she ret memory('isa(self, female)')",
|
"def concept she ret memory('isa(self, female)')",
|
||||||
"girl"
|
"girl"
|
||||||
]
|
]
|
||||||
sheerka = self.init_scenario(init)
|
sheerka = self.init_scenario(init, global_truth=True)
|
||||||
context = self.get_context(sheerka)
|
context = self.get_context(sheerka)
|
||||||
|
|
||||||
res = sheerka.evaluate_user_input("set_attr(she, 'my_attr', 'my value')")
|
res = sheerka.evaluate_user_input("set_attr(she, 'my_attr', 'my value')")
|
||||||
@@ -1337,7 +1339,7 @@ as:
|
|||||||
"def concept x attribute y equals z as set_attr(x, y, z)",
|
"def concept x attribute y equals z as set_attr(x, y, z)",
|
||||||
"girl"
|
"girl"
|
||||||
]
|
]
|
||||||
sheerka = self.init_scenario(init)
|
sheerka = self.init_scenario(init, global_truth=True)
|
||||||
context = self.get_context(sheerka)
|
context = self.get_context(sheerka)
|
||||||
|
|
||||||
res = sheerka.evaluate_user_input("eval she attribute 'my_attr' equals 'my value'")
|
res = sheerka.evaluate_user_input("eval she attribute 'my_attr' equals 'my value'")
|
||||||
@@ -1392,7 +1394,7 @@ as:
|
|||||||
"def concept qualify x from bnf adjective x as set_attr(x, c:adjective:, adjective) ret x",
|
"def concept qualify x from bnf adjective x as set_attr(x, c:adjective:, adjective) ret x",
|
||||||
"eval a red short",
|
"eval a red short",
|
||||||
]
|
]
|
||||||
sheerka = self.init_scenario(init)
|
sheerka = self.init_scenario(init, global_truth=True)
|
||||||
|
|
||||||
res = sheerka.evaluate_user_input("what is the color of the short ?")
|
res = sheerka.evaluate_user_input("what is the color of the short ?")
|
||||||
assert len(res) == 1
|
assert len(res) == 1
|
||||||
|
|||||||
@@ -13,6 +13,34 @@ class TestSheerkaNonRegMemory2(TestUsingMemoryBasedSheerka):
|
|||||||
|
|
||||||
res = sheerka.evaluate_user_input("question(foo is a foo)")
|
res = sheerka.evaluate_user_input("question(foo is a foo)")
|
||||||
|
|
||||||
# assert len(res) == 1
|
assert len(res) == 1
|
||||||
# assert res[0].status
|
assert res[0].status
|
||||||
# assert res[0].value
|
assert res[0].value # value is True since 'x is a foo' was chosen
|
||||||
|
|
||||||
|
def test_i_can_select_the_correct_concept_vs_bnf(self):
|
||||||
|
init = [
|
||||||
|
"def concept one as 1",
|
||||||
|
"def concept two as 2",
|
||||||
|
"def concept twenties from bnf 'twenty' (one|two)=unit as 20 + unit",
|
||||||
|
"def concept twenty two as 'specific occurrence'",
|
||||||
|
]
|
||||||
|
sheerka = self.init_scenario(init)
|
||||||
|
|
||||||
|
res = sheerka.evaluate_user_input("eval twenty one")
|
||||||
|
assert res[0].value == 21
|
||||||
|
|
||||||
|
res = sheerka.evaluate_user_input("eval twenty two")
|
||||||
|
assert res[0].value == "specific occurrence" # thanks to ExactConceptParser
|
||||||
|
|
||||||
|
def test_i_can_use_global_truth_when_calling_a_concept(self):
|
||||||
|
init = [
|
||||||
|
"def concept one",
|
||||||
|
"def concept number",
|
||||||
|
"def concept x is a y as set_isa(x, y)",
|
||||||
|
]
|
||||||
|
sheerka = self.init_scenario(init)
|
||||||
|
|
||||||
|
res = sheerka.evaluate_user_input("global_truth(one is a number)")
|
||||||
|
|
||||||
|
assert res[0].status
|
||||||
|
assert sheerka.isa(sheerka.new("one"), sheerka.new("number"))
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ class TestSheerkaNonRegFile(TestUsingFileBasedSheerka):
|
|||||||
"set_isa(thirty, number)",
|
"set_isa(thirty, number)",
|
||||||
"def concept thirties from bnf thirty number where number < 10 as thirty + number",
|
"def concept thirties from bnf thirty number where number < 10 as thirty + number",
|
||||||
"set_isa(thirties, number)",
|
"set_isa(thirties, number)",
|
||||||
])
|
], global_truth=True)
|
||||||
|
|
||||||
sheerka = self.new_sheerka_instance()
|
sheerka = self.new_sheerka_instance()
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,45 @@ post : None
|
|||||||
ret : None
|
ret : None
|
||||||
vars : []
|
vars : []
|
||||||
props : {}
|
props : {}
|
||||||
|
"""
|
||||||
|
|
||||||
|
def test_i_can_display_multiple_concepts_description_when_concept_definition(self, capsys):
|
||||||
|
init = [
|
||||||
|
"def concept foo as 1",
|
||||||
|
"def concept foo as 2 where True",
|
||||||
|
]
|
||||||
|
sheerka = self.init_scenario(init)
|
||||||
|
capsys.readouterr()
|
||||||
|
|
||||||
|
sheerka.enable_process_return_values = True
|
||||||
|
sheerka.evaluate_user_input("desc(c:foo:)")
|
||||||
|
captured = capsys.readouterr()
|
||||||
|
assert captured.out == """id : 1001
|
||||||
|
name : foo
|
||||||
|
key : foo
|
||||||
|
definition: None
|
||||||
|
type : None
|
||||||
|
hash : 16f7fbb8bc509b8c652edaf3d0c0457d15a37f0a862fbe03fa357b0c77249c46
|
||||||
|
body : 1
|
||||||
|
where : None
|
||||||
|
pre : None
|
||||||
|
post : None
|
||||||
|
ret : None
|
||||||
|
vars : []
|
||||||
|
props : {}
|
||||||
|
id : 1002
|
||||||
|
name : foo
|
||||||
|
key : foo
|
||||||
|
definition: None
|
||||||
|
type : None
|
||||||
|
hash : e8dd1af1b6bc0eca0fb4a87a6fabb16655caa4b7a6ea9dbbd1f887757e6caf89
|
||||||
|
body : 2
|
||||||
|
where : True
|
||||||
|
pre : None
|
||||||
|
post : None
|
||||||
|
ret : None
|
||||||
|
vars : []
|
||||||
|
props : {}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def test_i_can_describe_a_rule(self, capsys):
|
def test_i_can_describe_a_rule(self, capsys):
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class TestSheerkaNonRegPipeFunctions(TestUsingMemoryBasedSheerka):
|
|||||||
"add_to_memory('x', [one])"
|
"add_to_memory('x', [one])"
|
||||||
]
|
]
|
||||||
|
|
||||||
sheerka = self.init_scenario(init)
|
sheerka = self.init_scenario(init, global_truth=True)
|
||||||
res = sheerka.evaluate_user_input("x | where('isa(self, number)')")
|
res = sheerka.evaluate_user_input("x | where('isa(self, number)')")
|
||||||
|
|
||||||
assert len(res) == 1
|
assert len(res) == 1
|
||||||
|
|||||||
@@ -98,22 +98,24 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setup_class(cls):
|
def setup_class(cls):
|
||||||
init_test_helper = cls().init_test(cache_only=False, ontology="#TestBnfNodeParser#")
|
test_instance = cls()
|
||||||
|
init_test_helper = test_instance.init_test(cache_only=False, ontology="#TestBnfNodeParser#")
|
||||||
sheerka, context, *updated = init_test_helper.with_concepts(*cmap.values(), create_new=True).unpack()
|
sheerka, context, *updated = init_test_helper.with_concepts(*cmap.values(), create_new=True).unpack()
|
||||||
for i, concept_name in enumerate(cmap):
|
for i, concept_name in enumerate(cmap):
|
||||||
cmap[concept_name] = updated[i]
|
cmap[concept_name] = updated[i]
|
||||||
|
|
||||||
# end of initialisation
|
# end of initialisation
|
||||||
|
global_truth_context = test_instance.get_context(sheerka, global_truth=True)
|
||||||
sheerka = TestBnfNodeParser.sheerka
|
sheerka = TestBnfNodeParser.sheerka
|
||||||
sheerka.set_isa(context, cmap["one"], cmap["number"])
|
sheerka.set_isa(global_truth_context, cmap["one"], cmap["number"])
|
||||||
sheerka.set_isa(context, cmap["two"], cmap["number"])
|
sheerka.set_isa(global_truth_context, cmap["two"], cmap["number"])
|
||||||
sheerka.set_isa(context, cmap["three"], cmap["number"])
|
sheerka.set_isa(global_truth_context, cmap["three"], cmap["number"])
|
||||||
sheerka.set_isa(context, cmap["four"], cmap["number"])
|
sheerka.set_isa(global_truth_context, cmap["four"], cmap["number"])
|
||||||
sheerka.set_isa(context, cmap["thirty"], cmap["number"])
|
sheerka.set_isa(global_truth_context, cmap["thirty"], cmap["number"])
|
||||||
sheerka.set_isa(context, cmap["forty"], cmap["number"])
|
sheerka.set_isa(global_truth_context, cmap["forty"], cmap["number"])
|
||||||
sheerka.set_isa(context, cmap["fifty"], cmap["number"])
|
sheerka.set_isa(global_truth_context, cmap["fifty"], cmap["number"])
|
||||||
sheerka.set_isa(context, cmap["one hundred"], cmap["number"])
|
sheerka.set_isa(global_truth_context, cmap["one hundred"], cmap["number"])
|
||||||
sheerka.set_isa(context, cmap["hundreds"], cmap["number"])
|
sheerka.set_isa(global_truth_context, cmap["hundreds"], cmap["number"])
|
||||||
|
|
||||||
# Pay attention. 'twenties (t1 and t2) are not set as 'number'
|
# Pay attention. 'twenties (t1 and t2) are not set as 'number'
|
||||||
|
|
||||||
@@ -122,28 +124,28 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
|
|||||||
where="number < 10",
|
where="number < 10",
|
||||||
body="thirty + number").def_var("thirty").def_var("number"))
|
body="thirty + number").def_var("thirty").def_var("number"))
|
||||||
cmap["thirties"] = sheerka.create_new_concept(context, thirties).body.body
|
cmap["thirties"] = sheerka.create_new_concept(context, thirties).body.body
|
||||||
sheerka.set_isa(context, sheerka.new("thirties"), sheerka.new("number"))
|
sheerka.set_isa(global_truth_context, sheerka.new("thirties"), sheerka.new("number"))
|
||||||
|
|
||||||
forties = cls.update_bnf(context, Concept("forties",
|
forties = cls.update_bnf(context, Concept("forties",
|
||||||
definition="forty number",
|
definition="forty number",
|
||||||
where="number < 10",
|
where="number < 10",
|
||||||
body="forty + number").def_var("forty").def_var("number"))
|
body="forty + number").def_var("forty").def_var("number"))
|
||||||
cmap["forties"] = sheerka.create_new_concept(context, forties).body.body
|
cmap["forties"] = sheerka.create_new_concept(context, forties).body.body
|
||||||
sheerka.set_isa(context, sheerka.new("forties"), sheerka.new("number"))
|
sheerka.set_isa(global_truth_context, sheerka.new("forties"), sheerka.new("number"))
|
||||||
|
|
||||||
fifties = cls.update_bnf(context, Concept("fifties",
|
fifties = cls.update_bnf(context, Concept("fifties",
|
||||||
definition="fifty number",
|
definition="fifty number",
|
||||||
where="number < 10",
|
where="number < 10",
|
||||||
body="fifty + number").def_var("fifty").def_var("number"))
|
body="fifty + number").def_var("fifty").def_var("number"))
|
||||||
cmap["fifties"] = sheerka.create_new_concept(context, fifties).body.body
|
cmap["fifties"] = sheerka.create_new_concept(context, fifties).body.body
|
||||||
sheerka.set_isa(context, sheerka.new("fifties"), sheerka.new("number"))
|
sheerka.set_isa(global_truth_context, sheerka.new("fifties"), sheerka.new("number"))
|
||||||
|
|
||||||
thousands = cls.update_bnf(context, Concept("thousands",
|
thousands = cls.update_bnf(context, Concept("thousands",
|
||||||
definition="number 'thousand'",
|
definition="number 'thousand'",
|
||||||
where="number < 999",
|
where="number < 999",
|
||||||
body="number * 1000").def_var("number"))
|
body="number * 1000").def_var("number"))
|
||||||
cmap["thousands"] = sheerka.create_new_concept(context, thousands).body.body
|
cmap["thousands"] = sheerka.create_new_concept(context, thousands).body.body
|
||||||
sheerka.set_isa(context, sheerka.new("thousands"), sheerka.new("number"))
|
sheerka.set_isa(global_truth_context, sheerka.new("thousands"), sheerka.new("number"))
|
||||||
|
|
||||||
cls.shared_ontology = sheerka.get_ontology(context)
|
cls.shared_ontology = sheerka.get_ontology(context)
|
||||||
sheerka.pop_ontology(context)
|
sheerka.pop_ontology(context)
|
||||||
@@ -1217,10 +1219,11 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
|
|||||||
"twenties": self.bnf_concept("twenties", Sequence(ConceptExpression("twenty"), ConceptExpression("number")))
|
"twenties": self.bnf_concept("twenties", Sequence(ConceptExpression("twenty"), ConceptExpression("number")))
|
||||||
}
|
}
|
||||||
sheerka, context, parser = self.init_parser(my_map)
|
sheerka, context, parser = self.init_parser(my_map)
|
||||||
|
global_truth_context = self.get_context(sheerka, global_truth=True)
|
||||||
parser.context = context
|
parser.context = context
|
||||||
parser.sheerka = sheerka
|
parser.sheerka = sheerka
|
||||||
sheerka.set_isa(context, sheerka.new("one"), my_map["number"])
|
sheerka.set_isa(global_truth_context, sheerka.new("one"), my_map["number"])
|
||||||
sheerka.set_isa(context, sheerka.new("twenty"), my_map["number"])
|
sheerka.set_isa(global_truth_context, sheerka.new("twenty"), my_map["number"])
|
||||||
|
|
||||||
parser.concepts_grammars.clear() # make sure parsing expression is created from scratch
|
parser.concepts_grammars.clear() # make sure parsing expression is created from scratch
|
||||||
|
|
||||||
@@ -1251,9 +1254,10 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
|
|||||||
sheerka, context, parser = self.init_parser(my_map, singleton=True)
|
sheerka, context, parser = self.init_parser(my_map, singleton=True)
|
||||||
parser.context = context
|
parser.context = context
|
||||||
parser.sheerka = sheerka
|
parser.sheerka = sheerka
|
||||||
sheerka.set_isa(context, sheerka.new("one"), my_map["number"])
|
global_truth_context = self.get_context(sheerka, global_truth=True)
|
||||||
sheerka.set_isa(context, sheerka.new("two"), my_map["number"])
|
sheerka.set_isa(global_truth_context, sheerka.new("one"), my_map["number"])
|
||||||
sheerka.set_isa(context, sheerka.new("hundreds"), my_map["number"])
|
sheerka.set_isa(global_truth_context, sheerka.new("two"), my_map["number"])
|
||||||
|
sheerka.set_isa(global_truth_context, sheerka.new("hundreds"), my_map["number"])
|
||||||
|
|
||||||
parser.concepts_grammars.clear() # make sure parsing expression is created from scratch
|
parser.concepts_grammars.clear() # make sure parsing expression is created from scratch
|
||||||
parsing_expression = parser.get_parsing_expression(context, my_map["hundreds"])
|
parsing_expression = parser.get_parsing_expression(context, my_map["hundreds"])
|
||||||
@@ -1281,9 +1285,10 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
|
|||||||
sheerka, context, parser = self.init_parser(my_map, singleton=True)
|
sheerka, context, parser = self.init_parser(my_map, singleton=True)
|
||||||
parser.context = context
|
parser.context = context
|
||||||
parser.sheerka = sheerka
|
parser.sheerka = sheerka
|
||||||
sheerka.set_isa(context, sheerka.new("one"), my_map["number"])
|
global_truth_context = self.get_context(sheerka, global_truth=True)
|
||||||
sheerka.set_isa(context, sheerka.new("twenty"), my_map["number"])
|
sheerka.set_isa(global_truth_context, sheerka.new("one"), my_map["number"])
|
||||||
sheerka.set_isa(context, sheerka.new("twenties"), my_map["number"]) # <- twenties is also a number
|
sheerka.set_isa(global_truth_context, sheerka.new("twenty"), my_map["number"])
|
||||||
|
sheerka.set_isa(global_truth_context, sheerka.new("twenties"), my_map["number"]) # <- twenties is also a number
|
||||||
|
|
||||||
parser.concepts_grammars.clear() # make sure parsing expression is created from scratch
|
parser.concepts_grammars.clear() # make sure parsing expression is created from scratch
|
||||||
|
|
||||||
@@ -1900,15 +1905,16 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
|
|||||||
}
|
}
|
||||||
|
|
||||||
sheerka, context, parser = self.init_parser(my_map, init_from_sheerka=True, create_new=True)
|
sheerka, context, parser = self.init_parser(my_map, init_from_sheerka=True, create_new=True)
|
||||||
sheerka.set_isa(context, my_map["light_red"], my_map["adjective"])
|
global_truth_context = self.get_context(sheerka, global_truth=True)
|
||||||
sheerka.set_isa(context, my_map["dark_red"], my_map["adjective"])
|
sheerka.set_isa(global_truth_context, my_map["light_red"], my_map["adjective"])
|
||||||
sheerka.set_isa(context, my_map["light_red"], my_map["color"])
|
sheerka.set_isa(global_truth_context, my_map["dark_red"], my_map["adjective"])
|
||||||
sheerka.set_isa(context, my_map["dark_red"], my_map["color"])
|
sheerka.set_isa(global_truth_context, my_map["light_red"], my_map["color"])
|
||||||
sheerka.set_isa(context, my_map["light_red"], my_map["red colors"])
|
sheerka.set_isa(global_truth_context, my_map["dark_red"], my_map["color"])
|
||||||
sheerka.set_isa(context, my_map["dark_red"], my_map["red colors"])
|
sheerka.set_isa(global_truth_context, my_map["light_red"], my_map["red colors"])
|
||||||
sheerka.set_isa(context, my_map["color"], my_map["adjective"])
|
sheerka.set_isa(global_truth_context, my_map["dark_red"], my_map["red colors"])
|
||||||
sheerka.set_isa(context, my_map["red colors"], my_map["color"])
|
sheerka.set_isa(global_truth_context, my_map["color"], my_map["adjective"])
|
||||||
sheerka.set_isa(context, my_map["red colors"], my_map["adjective"])
|
sheerka.set_isa(global_truth_context, my_map["red colors"], my_map["color"])
|
||||||
|
sheerka.set_isa(global_truth_context, my_map["red colors"], my_map["adjective"])
|
||||||
|
|
||||||
text = "light red table"
|
text = "light red table"
|
||||||
|
|
||||||
|
|||||||
@@ -144,6 +144,7 @@ class TestExactConceptParser(TestUsingMemoryBasedSheerka):
|
|||||||
assert concept_found == foo
|
assert concept_found == foo
|
||||||
assert not concept_found.get_hints().need_validation
|
assert not concept_found.get_hints().need_validation
|
||||||
assert concept_found.get_hints().is_evaluated
|
assert concept_found.get_hints().is_evaluated
|
||||||
|
assert not concept_found.get_hints().is_instance
|
||||||
|
|
||||||
def test_i_can_parse_concept_with_concept_tokens(self):
|
def test_i_can_parse_concept_with_concept_tokens(self):
|
||||||
sheerka, context, one, two, plus = self.init_concepts(
|
sheerka, context, one, two, plus = self.init_concepts(
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from core.builtin_concepts import BuiltinConcepts
|
|||||||
from core.sheerka.services.SheerkaExecute import ParserInput
|
from core.sheerka.services.SheerkaExecute import ParserInput
|
||||||
from core.tokenizer import TokenKind
|
from core.tokenizer import TokenKind
|
||||||
from parsers.BaseExpressionParser import TrueifyVisitor, IsAQuestionVisitor, LeftPartNotFoundError, \
|
from parsers.BaseExpressionParser import TrueifyVisitor, IsAQuestionVisitor, LeftPartNotFoundError, \
|
||||||
ParenthesisMismatchError
|
ParenthesisMismatchError, compile_disjunctions, NotNode, AndNode, OrNode
|
||||||
from parsers.BaseParser import UnexpectedEofParsingError, UnexpectedTokenParsingError
|
from parsers.BaseParser import UnexpectedEofParsingError, UnexpectedTokenParsingError
|
||||||
from parsers.LogicalOperatorParser import LogicalOperatorParser
|
from parsers.LogicalOperatorParser import LogicalOperatorParser
|
||||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||||
@@ -12,6 +12,46 @@ from tests.parsers.parsers_utils import EXPR, OR, AND, NOT, \
|
|||||||
get_expr_node_from_test_node
|
get_expr_node_from_test_node
|
||||||
|
|
||||||
|
|
||||||
|
class DoNotCompareStartStopContextManager:
|
||||||
|
def __init__(self):
|
||||||
|
self.original_not_eq = None
|
||||||
|
self.original_and_eq = None
|
||||||
|
self.original_or_eq = None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def not_eq(self, other):
|
||||||
|
if not isinstance(other, NotNode):
|
||||||
|
return False
|
||||||
|
return self.node == other.node
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def and_eq(self, other):
|
||||||
|
if not isinstance(other, AndNode):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return self.parts == other.parts
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def or_eq(self, other):
|
||||||
|
if not isinstance(other, OrNode):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return self.parts == other.parts
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
self.original_not_eq = NotNode.__eq__
|
||||||
|
self.original_and_eq = AndNode.__eq__
|
||||||
|
self.original_or_eq = OrNode.__eq__
|
||||||
|
NotNode.__eq__ = self.not_eq
|
||||||
|
AndNode.__eq__ = self.and_eq
|
||||||
|
OrNode.__eq__ = self.or_eq
|
||||||
|
|
||||||
|
def __exit__(self, *args):
|
||||||
|
NotNode.__eq__ = self.original_not_eq
|
||||||
|
AndNode.__eq__ = self.original_and_eq
|
||||||
|
OrNode.__eq__ = self.original_or_eq
|
||||||
|
|
||||||
|
|
||||||
class TestLogicalOperatorParser(TestUsingMemoryBasedSheerka):
|
class TestLogicalOperatorParser(TestUsingMemoryBasedSheerka):
|
||||||
|
|
||||||
def init_parser(self):
|
def init_parser(self):
|
||||||
@@ -175,6 +215,50 @@ class TestLogicalOperatorParser(TestUsingMemoryBasedSheerka):
|
|||||||
|
|
||||||
assert IsAQuestionVisitor().visit(expr_node) == expected
|
assert IsAQuestionVisitor().visit(expr_node) == expected
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("expression, expected", [
|
||||||
|
("a", [EXPR("a")]),
|
||||||
|
("a and b and c", [AND(EXPR("a"), EXPR("b"), EXPR("c"))]),
|
||||||
|
("a or b or c", [EXPR("a"),
|
||||||
|
EXPR("b"),
|
||||||
|
EXPR("c")]),
|
||||||
|
("a and b or c", [AND(EXPR("a"), EXPR("b")), EXPR("c")]),
|
||||||
|
("a or b and c", [EXPR("a"),
|
||||||
|
AND(EXPR("b"), EXPR("c"))]),
|
||||||
|
("(a or b) and c", [AND(EXPR("a"), EXPR("c")),
|
||||||
|
AND(EXPR("b"), EXPR("c"))]),
|
||||||
|
("a or (b or c) and d", [EXPR("a"),
|
||||||
|
AND(EXPR("b"), EXPR("d")),
|
||||||
|
AND(EXPR("c"), EXPR("d"))]),
|
||||||
|
|
||||||
|
("not a", [NOT(EXPR("a"))]),
|
||||||
|
("not (a and b)", [NOT(AND(EXPR("a"), EXPR("b")))]),
|
||||||
|
("not (a or b)", [AND(NOT(EXPR("a")), NOT(EXPR("b")))]),
|
||||||
|
|
||||||
|
("(a or b) and not (c or d)", [AND(EXPR("a"), NOT(EXPR("c")), NOT(EXPR("d"))),
|
||||||
|
AND(EXPR("b"), NOT(EXPR("c")), NOT(EXPR("d")))]),
|
||||||
|
("(a or b) or not (c or d)", [EXPR("a"),
|
||||||
|
EXPR("b"),
|
||||||
|
AND(NOT(EXPR("c")), NOT(EXPR("d")))]),
|
||||||
|
|
||||||
|
("(a and b) and not (c or d)", [AND(EXPR("a"), EXPR("b"), NOT(EXPR("c")), NOT(EXPR("d")))]),
|
||||||
|
("(a and b) or not (c or d)", [AND(EXPR("a"), EXPR("b")),
|
||||||
|
AND(NOT(EXPR("c")), NOT(EXPR("d")))]),
|
||||||
|
|
||||||
|
("a and (b and c)", [AND(EXPR("a"), EXPR("b"), EXPR("c"))]),
|
||||||
|
("a or (b or c)", [EXPR("a"),
|
||||||
|
EXPR("b"),
|
||||||
|
EXPR("c")]),
|
||||||
|
])
|
||||||
|
def test_i_can_compile_disjunction(self, expression, expected):
|
||||||
|
sheerka, context, parser = self.init_parser()
|
||||||
|
resolved_expected = [get_expr_node_from_test_node(expression, e) for e in expected]
|
||||||
|
|
||||||
|
expr_node = parser.parse(context, ParserInput(expression)).body.body
|
||||||
|
|
||||||
|
with DoNotCompareStartStopContextManager():
|
||||||
|
res = compile_disjunctions(expr_node)
|
||||||
|
assert res == resolved_expected
|
||||||
|
|
||||||
# @pytest.mark.parametrize("expression, expected", [
|
# @pytest.mark.parametrize("expression, expected", [
|
||||||
# ("foo", "foo"),
|
# ("foo", "foo"),
|
||||||
# ("one two", "one two"),
|
# ("one two", "one two"),
|
||||||
|
|||||||
@@ -258,6 +258,23 @@ class TestSequenceNodeParser(TestUsingMemoryBasedSheerka):
|
|||||||
assert sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
assert sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||||
compare_with_test_object(lexer_nodes, expected_array)
|
compare_with_test_object(lexer_nodes, expected_array)
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("concept", [
|
||||||
|
Concept("foo x", body="1").def_var("x"),
|
||||||
|
Concept("foo"),
|
||||||
|
])
|
||||||
|
def test_i_can_parse_token_concepts(self, concept):
|
||||||
|
concepts_map = {
|
||||||
|
"foo": concept,
|
||||||
|
}
|
||||||
|
|
||||||
|
sheerka, context, parser = self.init_parser(concepts_map, create_new=True, use_sheerka=True)
|
||||||
|
res = parser.parse(context, ParserInput(f"c:{concept.name}:"))
|
||||||
|
|
||||||
|
assert res.status
|
||||||
|
concept_found = res.body.body[0].concept
|
||||||
|
assert concept_found.get_hints().is_evaluated
|
||||||
|
assert not concept_found.get_hints().is_instance
|
||||||
|
|
||||||
@pytest.mark.parametrize("text", [
|
@pytest.mark.parametrize("text", [
|
||||||
"foo",
|
"foo",
|
||||||
f"foo one",
|
f"foo one",
|
||||||
|
|||||||
@@ -709,6 +709,65 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
|
|||||||
|
|
||||||
self.compare_results(res, expected_sequences, cmap, expression)
|
self.compare_results(res, expected_sequences, cmap, expression)
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("expression, expected", [
|
||||||
|
("suffixed2 a b", ['a', 'b', "suffixed2"]),
|
||||||
|
("suffixed3 a b c", ['a', 'b', 'c', "suffixed3"]),
|
||||||
|
("a b prefixed2", ['a', 'b', "prefixed2"]),
|
||||||
|
("a b c prefixed3", ['a', 'b', 'c', "prefixed3"]),
|
||||||
|
("start2 a b stop", ['a', 'b', "start2"]),
|
||||||
|
("start3 a b c stop", ['a', 'b', 'c', "start3"]),
|
||||||
|
])
|
||||||
|
def test_i_can_post_fix_when_multiple_parameters_are_expected(self, expression, expected):
|
||||||
|
concepts_map = {
|
||||||
|
"a": Concept("a"),
|
||||||
|
"b": Concept("b"),
|
||||||
|
"c": Concept("c"),
|
||||||
|
"suffixed2": Concept("suffixed2 x y").def_var("x").def_var("y"),
|
||||||
|
"suffixed3": Concept("suffixed3 x y z").def_var("x").def_var("y").def_var("z"),
|
||||||
|
"prefixed2": Concept("x y prefixed2").def_var("x").def_var("y"),
|
||||||
|
"prefixed3": Concept("x y z prefixed3").def_var("x").def_var("y").def_var("z"),
|
||||||
|
"start2": Concept("start2 x y stop").def_var("x").def_var("y"),
|
||||||
|
"start3": Concept("start3 x y z stop").def_var("x").def_var("y").def_var("z"),
|
||||||
|
}
|
||||||
|
sheerka, context, parser = self.init_parser(concepts_map, None)
|
||||||
|
|
||||||
|
res = parser.infix_to_postfix(context, ParserInput(expression))
|
||||||
|
expected_array = compute_expected_array(concepts_map, expression, expected)
|
||||||
|
|
||||||
|
assert len(res) == 1
|
||||||
|
transformed_out = get_test_obj(res[0].out, expected_array)
|
||||||
|
assert transformed_out == expected_array
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("expression, expected", [
|
||||||
|
("suffixed3 x y z", ['x', 'y', 'z', "suffixed3"]),
|
||||||
|
("suffixed3 a y z", ['a', 'y', 'z', "suffixed3"]),
|
||||||
|
("suffixed3 x a z", ['x ', 'a', ' z', "suffixed3"]), # this one was not managed by the second chance
|
||||||
|
("suffixed3 x y a", ['x', 'y', 'a', "suffixed3"]),
|
||||||
|
("x y z prefixed3", ['x', 'y', 'z', "prefixed3"]),
|
||||||
|
("a y z prefixed3", ['a', 'y', 'z', "prefixed3"]),
|
||||||
|
("x a z prefixed3", ['x ', 'a', ' z', "prefixed3"]),
|
||||||
|
("x y a prefixed3", ['x', 'y', 'a', "prefixed3"]),
|
||||||
|
("start3 x y z stop", ['x', 'y', 'z', "start3"]),
|
||||||
|
("start3 a y z stop", ['a', 'y', 'z', "start3"]),
|
||||||
|
("start3 x a z stop", ['x ', 'a', ' z ', "start3"]),
|
||||||
|
("start3 x y a stop", ['x', 'y', 'a', "start3"]),
|
||||||
|
])
|
||||||
|
def test_i_can_post_fix_when_multiple_parameters_are_expected_but_unrecognized_tokens(self, expression, expected):
|
||||||
|
concepts_map = {
|
||||||
|
"a": Concept("a"),
|
||||||
|
"suffixed3": Concept("suffixed3 x y z").def_var("x").def_var("y").def_var("z"),
|
||||||
|
"prefixed3": Concept("x y z prefixed3").def_var("x").def_var("y").def_var("z"),
|
||||||
|
"start3": Concept("start3 x y z stop").def_var("x").def_var("y").def_var("z"),
|
||||||
|
}
|
||||||
|
sheerka, context, parser = self.init_parser(concepts_map, None)
|
||||||
|
|
||||||
|
res = parser.infix_to_postfix(context, ParserInput(expression))
|
||||||
|
expected_array = compute_expected_array(concepts_map, expression, expected)
|
||||||
|
|
||||||
|
assert len(res) == 1
|
||||||
|
transformed_out = get_test_obj(res[0].out, expected_array)
|
||||||
|
assert transformed_out == expected_array
|
||||||
|
|
||||||
@pytest.mark.parametrize("expression, expected", [
|
@pytest.mark.parametrize("expression, expected", [
|
||||||
("(", ("(", 0)),
|
("(", ("(", 0)),
|
||||||
("one plus ( 1 + ", ("(", 4)),
|
("one plus ( 1 + ", ("(", 4)),
|
||||||
@@ -1080,6 +1139,28 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
|
|||||||
assert isinstance(concept_plus_b[0].body.body, PythonNode)
|
assert isinstance(concept_plus_b[0].body.body, PythonNode)
|
||||||
assert concept_suffixed_a == cmap["two"]
|
assert concept_suffixed_a == cmap["two"]
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("text, expected", [
|
||||||
|
("suffixed3 a b c", [("x", "a"), ("y", "b"), ("z", "c")]),
|
||||||
|
("a b c prefixed3", [("x", "a"), ("y", "b"), ("z", "c")]),
|
||||||
|
("start3 a b c stop", [("x", "a"), ("y", "b"), ("z", "c")]),
|
||||||
|
])
|
||||||
|
def test_i_can_parse_when_multiple_parameters_are_expected(self, text, expected):
|
||||||
|
concepts_map = {
|
||||||
|
"a": Concept("a"),
|
||||||
|
"b": Concept("b"),
|
||||||
|
"c": Concept("c"),
|
||||||
|
"suffixed3": Concept("suffixed3 x y z").def_var("x").def_var("y").def_var("z"),
|
||||||
|
"prefixed3": Concept("x y z prefixed3").def_var("x").def_var("y").def_var("z"),
|
||||||
|
"start3": Concept("start3 x y z stop").def_var("x").def_var("y").def_var("z"),
|
||||||
|
}
|
||||||
|
sheerka, context, parser = self.init_parser(concepts_map, None)
|
||||||
|
|
||||||
|
res = parser.parse(context, ParserInput(text))
|
||||||
|
lexer_nodes = res.body.body
|
||||||
|
|
||||||
|
assert res.status
|
||||||
|
assert lexer_nodes[0].concept.get_metadata().variables == expected
|
||||||
|
|
||||||
@pytest.mark.parametrize("text", [
|
@pytest.mark.parametrize("text", [
|
||||||
"function(suffixed one)",
|
"function(suffixed one)",
|
||||||
"function(one plus two mult three)",
|
"function(one plus two mult three)",
|
||||||
|
|||||||
@@ -433,6 +433,10 @@ class TestUnrecognizedNodeParser(TestUsingMemoryBasedSheerka):
|
|||||||
compare_with_test_object(actual_nodes, expected_array)
|
compare_with_test_object(actual_nodes, expected_array)
|
||||||
|
|
||||||
def test_i_can_parse_when_multiple_atom_and_sya(self):
|
def test_i_can_parse_when_multiple_atom_and_sya(self):
|
||||||
|
"""
|
||||||
|
Testing that the ambiguity between hello_atom and hello_sya is correctly managed
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
sheerka, context, parser = self.init_parser()
|
sheerka, context, parser = self.init_parser()
|
||||||
expression = "two hello one three"
|
expression = "two hello one three"
|
||||||
nodes = get_input_nodes_from(concepts_map, expression,
|
nodes = get_input_nodes_from(concepts_map, expression,
|
||||||
@@ -440,25 +444,15 @@ class TestUnrecognizedNodeParser(TestUsingMemoryBasedSheerka):
|
|||||||
parser_input = ParserResultConcept("parsers.xxx", source=expression, value=nodes)
|
parser_input = ParserResultConcept("parsers.xxx", source=expression, value=nodes)
|
||||||
|
|
||||||
res = parser.parse(context, parser_input)
|
res = parser.parse(context, parser_input)
|
||||||
assert len(res) == 2
|
assert res.status
|
||||||
assert res[0].status
|
|
||||||
assert res[1].status
|
|
||||||
|
|
||||||
actual_nodes0 = res[0].body.body
|
actual_nodes0 = res.body.body
|
||||||
expected_0 = compute_expected_array(concepts_map, expression, [
|
expected_0 = compute_expected_array(concepts_map, expression, [
|
||||||
CN("two", start=0, end=0),
|
CN("two", start=0, end=0),
|
||||||
CN("hello_atom", source="hello one", start=2, end=4),
|
CN("hello_atom", source="hello one", start=2, end=4),
|
||||||
CN("three", start=6, end=6)])
|
CN("three", start=6, end=6)])
|
||||||
compare_with_test_object(actual_nodes0, expected_0)
|
compare_with_test_object(actual_nodes0, expected_0)
|
||||||
|
|
||||||
actual_nodes1 = res[1].body.body
|
|
||||||
expected_1 = compute_expected_array(concepts_map, expression, [
|
|
||||||
CN("two", start=0, end=0),
|
|
||||||
CNC("hello_sya", "hello one", start=2, end=4, a="one"),
|
|
||||||
CN("three", start=6, end=6)],
|
|
||||||
exclude_body=True)
|
|
||||||
compare_with_test_object(actual_nodes1, expected_1)
|
|
||||||
|
|
||||||
def test_i_can_parse_when_multiple_sya_concepts(self):
|
def test_i_can_parse_when_multiple_sya_concepts(self):
|
||||||
sheerka, context, parser = self.init_parser()
|
sheerka, context, parser = self.init_parser()
|
||||||
expression = "greetings two"
|
expression = "greetings two"
|
||||||
|
|||||||
Reference in New Issue
Block a user