Working on #98 : Persist attribute value when global_truth is set to true
This commit is contained in:
+9
-10
@@ -13,7 +13,7 @@ PROPERTIES_FOR_DIGEST = ("name", "key",
|
|||||||
"definition", "definition_type",
|
"definition", "definition_type",
|
||||||
"is_builtin", "is_unique",
|
"is_builtin", "is_unique",
|
||||||
"where", "pre", "post", "body", "ret",
|
"where", "pre", "post", "body", "ret",
|
||||||
"desc", "props", "variables")
|
"desc", "props", "variables", "parameters")
|
||||||
PROPERTIES_TO_SERIALIZE = PROPERTIES_FOR_DIGEST + tuple(["id"])
|
PROPERTIES_TO_SERIALIZE = PROPERTIES_FOR_DIGEST + tuple(["id"])
|
||||||
PROPERTIES_FOR_NEW = ("where", "pre", "post", "body", "desc")
|
PROPERTIES_FOR_NEW = ("where", "pre", "post", "body", "desc")
|
||||||
VARIABLE_PREFIX = "__var__"
|
VARIABLE_PREFIX = "__var__"
|
||||||
@@ -73,6 +73,7 @@ class ConceptMetadata:
|
|||||||
id: str # unique identifier for a concept. The id will never be modified (but the key can)
|
id: str # unique identifier for a concept. The id will never be modified (but the key can)
|
||||||
props: dict # hashmap of properties, values
|
props: dict # hashmap of properties, values
|
||||||
variables: list # list of concept variables(tuple), with their default values
|
variables: list # list of concept variables(tuple), with their default values
|
||||||
|
parameters: list # list of variables that are part of the name of the concept
|
||||||
full_serialization: bool = False # If True, the full object will be serialized, rather than just the diff
|
full_serialization: bool = False # If True, the full object will be serialized, rather than just the diff
|
||||||
all_attributes: List[str] = None # list of instance attributes
|
all_attributes: List[str] = None # list of instance attributes
|
||||||
|
|
||||||
@@ -163,7 +164,8 @@ class Concept:
|
|||||||
desc,
|
desc,
|
||||||
id,
|
id,
|
||||||
props or {},
|
props or {},
|
||||||
variables or []
|
variables or [],
|
||||||
|
[]
|
||||||
)
|
)
|
||||||
|
|
||||||
self._metadata = metadata
|
self._metadata = metadata
|
||||||
@@ -241,8 +243,8 @@ class Concept:
|
|||||||
# It's just to control what I put in the default value of properties
|
# It's just to control what I put in the default value of properties
|
||||||
# You can allow more type if it's REALLY needed.
|
# You can allow more type if it's REALLY needed.
|
||||||
# - str are for standard definition
|
# - str are for standard definition
|
||||||
# - list of concepts is used by ISA
|
# - Concept when properly set
|
||||||
assert default_value is None or isinstance(default_value, str)
|
assert default_value is None or isinstance(default_value, (str, Concept))
|
||||||
|
|
||||||
self._metadata.variables.append((var_name, default_value))
|
self._metadata.variables.append((var_name, default_value))
|
||||||
|
|
||||||
@@ -330,7 +332,6 @@ class Concept:
|
|||||||
if token.value in variables:
|
if token.value in variables:
|
||||||
key += VARIABLE_PREFIX + str(variables.index(token.value))
|
key += VARIABLE_PREFIX + str(variables.index(token.value))
|
||||||
else:
|
else:
|
||||||
# value = token.value[1:-1] if token.type == TokenKind.STRING else token.value
|
|
||||||
key += token.value.value if token.type == TokenKind.KEYWORD else token.value
|
key += token.value.value if token.type == TokenKind.KEYWORD else token.value
|
||||||
first = False
|
first = False
|
||||||
|
|
||||||
@@ -421,6 +422,8 @@ class Concept:
|
|||||||
self.def_var(name, value)
|
self.def_var(name, value)
|
||||||
elif prop == "props":
|
elif prop == "props":
|
||||||
self._metadata.props = core.utils.sheerka_deepcopy(other.get_metadata().props)
|
self._metadata.props = core.utils.sheerka_deepcopy(other.get_metadata().props)
|
||||||
|
elif prop == "parameters":
|
||||||
|
self._metadata.parameters = other.get_metadata().parameters.copy()
|
||||||
else:
|
else:
|
||||||
setattr(self._metadata, prop, getattr(other.get_metadata(), prop))
|
setattr(self._metadata, prop, getattr(other.get_metadata(), prop))
|
||||||
|
|
||||||
@@ -522,11 +525,7 @@ class Concept:
|
|||||||
return NotInit
|
return NotInit
|
||||||
|
|
||||||
def values(self):
|
def values(self):
|
||||||
try:
|
values = {k: getattr(self, k) if hasattr(self, k) else NotInit for k in get_concept_attrs(self)}
|
||||||
values = {k: getattr(self, k) for k in get_concept_attrs(self)}
|
|
||||||
except AttributeError as err:
|
|
||||||
print(f"{err}, {self=}")
|
|
||||||
raise err
|
|
||||||
|
|
||||||
for prop_name in AllConceptParts:
|
for prop_name in AllConceptParts:
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ from sdp.sheerkaDataProvider import Event
|
|||||||
|
|
||||||
BASE_NODE_PARSER_CLASS = "parsers.BaseNodeParser.BaseNodeParser"
|
BASE_NODE_PARSER_CLASS = "parsers.BaseNodeParser.BaseNodeParser"
|
||||||
EXIT_COMMANDS = ("quit", "exit", "bye")
|
EXIT_COMMANDS = ("quit", "exit", "bye")
|
||||||
|
CONTEXT_HINT_COMMANDS = (("global_truth(", "global_truth"),
|
||||||
|
("question(", "question"),
|
||||||
|
("eval", "eval"))
|
||||||
EXECUTE_STEPS = [
|
EXECUTE_STEPS = [
|
||||||
BuiltinConcepts.BEFORE_PARSING,
|
BuiltinConcepts.BEFORE_PARSING,
|
||||||
BuiltinConcepts.PARSING,
|
BuiltinConcepts.PARSING,
|
||||||
@@ -493,7 +496,7 @@ class Sheerka(Concept):
|
|||||||
c.get_hints().recognized_by = rec_by
|
c.get_hints().recognized_by = rec_by
|
||||||
c.get_hints().is_instance = is_inst
|
c.get_hints().is_instance = is_inst
|
||||||
if is_eval is None:
|
if is_eval is None:
|
||||||
c.get_hints().is_evaluated = len(c.get_metadata().variables) > 0
|
c.get_hints().is_evaluated = len(c.get_metadata().parameters) > 0
|
||||||
else:
|
else:
|
||||||
c.get_hints().is_evaluated = is_eval
|
c.get_hints().is_evaluated = is_eval
|
||||||
return c
|
return c
|
||||||
@@ -581,7 +584,12 @@ class Sheerka(Concept):
|
|||||||
# otherwise, create another instance
|
# otherwise, create another instance
|
||||||
concept = self.builtin_cache[key]() if key in self.builtin_cache else Concept()
|
concept = self.builtin_cache[key]() if key in self.builtin_cache else Concept()
|
||||||
concept.update_from(template, update_value=False)
|
concept.update_from(template, update_value=False)
|
||||||
# concept.freeze_definition_hash()
|
|
||||||
|
# set the default values is needed
|
||||||
|
for var_name, var_value in concept.get_metadata().variables:
|
||||||
|
if isinstance(var_value, Concept):
|
||||||
|
concept.set_value(var_name, var_value)
|
||||||
|
# Note that the concept is not considered as evaluated. The body may need to be computed
|
||||||
|
|
||||||
if len(kwargs) == 0:
|
if len(kwargs) == 0:
|
||||||
return concept
|
return concept
|
||||||
|
|||||||
@@ -295,7 +295,7 @@ class SheerkaConceptManager(BaseService):
|
|||||||
# 'props' : {<key>: <value>} of properties to add/update,
|
# 'props' : {<key>: <value>} of properties to add/update,
|
||||||
# 'variables': {<key>: <value>} of variables to add/update,
|
# 'variables': {<key>: <value>} of variables to add/update,
|
||||||
# }
|
# }
|
||||||
# if the <key> already exists, the entry is updated, otherwise a new value is created
|
# for variables, if the <key> already exists, the entry is updated, otherwise a new value is created
|
||||||
# for props, if the <key> already exists, a new entry is added to the set
|
# for props, if the <key> already exists, a new entry is added to the set
|
||||||
#
|
#
|
||||||
# to_remove = {
|
# to_remove = {
|
||||||
@@ -391,9 +391,10 @@ class SheerkaConceptManager(BaseService):
|
|||||||
sheerka.publish(context, EVENT_CONCEPT_DELETED, concept)
|
sheerka.publish(context, EVENT_CONCEPT_DELETED, concept)
|
||||||
return sheerka.ret(self.NAME, True, sheerka.new(BuiltinConcepts.SUCCESS))
|
return sheerka.ret(self.NAME, True, sheerka.new(BuiltinConcepts.SUCCESS))
|
||||||
|
|
||||||
def set_attr(self, concept, attribute, value):
|
def set_attr(self, context, concept, attribute, value):
|
||||||
"""
|
"""
|
||||||
Modifies an attribute of a concept (concept.values)
|
Modifies an attribute of a concept (concept.values)
|
||||||
|
:param context:
|
||||||
:param concept:
|
:param concept:
|
||||||
:param attribute:
|
:param attribute:
|
||||||
:param value:
|
:param value:
|
||||||
@@ -402,8 +403,16 @@ class SheerkaConceptManager(BaseService):
|
|||||||
ensure_concept(concept)
|
ensure_concept(concept)
|
||||||
|
|
||||||
attr = attribute.str_id if isinstance(attribute, Concept) else attribute
|
attr = attribute.str_id if isinstance(attribute, Concept) else attribute
|
||||||
|
old_value = concept.get_value(attr)
|
||||||
|
|
||||||
if (old_value := concept.get_value(attr)) is not NotInit:
|
if context.in_context(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED):
|
||||||
|
old_value = self.sheerka.get_by_id(concept.id).get_value(attr)
|
||||||
|
else:
|
||||||
|
old_value = concept.get_value(attr)
|
||||||
|
|
||||||
|
# Caution, creating a list when a set_attr is called for the second time is not always
|
||||||
|
# what is expected
|
||||||
|
if old_value is not NotInit:
|
||||||
if old_value == value:
|
if old_value == value:
|
||||||
return self.sheerka.ret(self.NAME, True, self.sheerka.new(BuiltinConcepts.SUCCESS))
|
return self.sheerka.ret(self.NAME, True, self.sheerka.new(BuiltinConcepts.SUCCESS))
|
||||||
|
|
||||||
@@ -413,6 +422,13 @@ class SheerkaConceptManager(BaseService):
|
|||||||
else:
|
else:
|
||||||
value = [old_value, value]
|
value = [old_value, value]
|
||||||
|
|
||||||
|
if context.in_context(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED):
|
||||||
|
to_add = {"variables": {attr: value}}
|
||||||
|
res = self.sheerka.modify_concept(context, concept, to_add, modify_source=True)
|
||||||
|
concept.set_value(attr, value)
|
||||||
|
return res
|
||||||
|
else:
|
||||||
|
|
||||||
concept.set_value(attr, value)
|
concept.set_value(attr, value)
|
||||||
return self.sheerka.ret(self.NAME, True, self.sheerka.new(BuiltinConcepts.SUCCESS))
|
return self.sheerka.ret(self.NAME, True, self.sheerka.new(BuiltinConcepts.SUCCESS))
|
||||||
|
|
||||||
@@ -857,6 +873,7 @@ class SheerkaConceptManager(BaseService):
|
|||||||
concept.set_bnf(None)
|
concept.set_bnf(None)
|
||||||
ensure_bnf(context, concept)
|
ensure_bnf(context, concept)
|
||||||
|
|
||||||
|
self.recompute_concept_parameters(context, concept)
|
||||||
concept.init_key()
|
concept.init_key()
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -1252,3 +1269,27 @@ class SheerkaConceptManager(BaseService):
|
|||||||
# update the compiled regex
|
# update the compiled regex
|
||||||
self.compiled_concepts_by_regex.clear()
|
self.compiled_concepts_by_regex.clear()
|
||||||
self.compiled_concepts_by_regex.extend(compiled_by_first_regex)
|
self.compiled_concepts_by_regex.extend(compiled_by_first_regex)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def recompute_concept_parameters(context, concept):
|
||||||
|
concept.get_metadata().parameters.clear()
|
||||||
|
|
||||||
|
if concept.get_metadata().definition_type == DEFINITION_TYPE_DEF:
|
||||||
|
tokens = list(Tokenizer(concept.get_metadata().definition, yield_eof=False))
|
||||||
|
else:
|
||||||
|
tokens = list(Tokenizer(concept.get_metadata().name, yield_eof=False))
|
||||||
|
|
||||||
|
# all variables that appear in the name are concept parameters
|
||||||
|
if len(tokens) > 0:
|
||||||
|
variables = [p[0] for p in concept.get_metadata().variables]
|
||||||
|
for token in [t for t in tokens if t.value in variables]:
|
||||||
|
concept.get_metadata().parameters.append(token.value)
|
||||||
|
|
||||||
|
# for bnf concept, use the visitor to extract parameters
|
||||||
|
if concept.get_bnf():
|
||||||
|
from evaluators.DefConceptEvaluator import ConceptOrRuleVariableVisitor, ParameterVariable
|
||||||
|
visitor = ConceptOrRuleVariableVisitor(context)
|
||||||
|
visitor.visit(concept.get_bnf())
|
||||||
|
for variable in [v for v in visitor.variables if isinstance(v, ParameterVariable)]:
|
||||||
|
if variable.name not in concept.get_metadata().parameters:
|
||||||
|
concept.get_metadata().parameters.append(variable.name)
|
||||||
|
|||||||
@@ -432,9 +432,12 @@ class SheerkaEvaluateConcept(BaseService):
|
|||||||
if default_value is None:
|
if default_value is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if not isinstance(default_value, str):
|
if not isinstance(default_value, (str, Concept)):
|
||||||
raise Exception("Invalid concept init. variable metadata must be a string")
|
raise Exception("Invalid concept init. variable metadata must be a string (or a concept)")
|
||||||
|
|
||||||
|
if isinstance(default_value, Concept):
|
||||||
|
concept.get_compiled()[var_name] = default_value.copy()
|
||||||
|
else:
|
||||||
concept.get_compiled()[var_name] = self.get_asts(context,
|
concept.get_compiled()[var_name] = self.get_asts(context,
|
||||||
self.NAME,
|
self.NAME,
|
||||||
default_value,
|
default_value,
|
||||||
@@ -740,8 +743,6 @@ class SheerkaEvaluateConcept(BaseService):
|
|||||||
# TODO : Validate the POST condition
|
# TODO : Validate the POST condition
|
||||||
#
|
#
|
||||||
|
|
||||||
concept.init_key() # Necessary for old unit tests. To remove someday
|
|
||||||
|
|
||||||
if ConceptParts.BODY in all_metadata_to_eval and not failed_to_evaluate_body:
|
if ConceptParts.BODY in all_metadata_to_eval and not failed_to_evaluate_body:
|
||||||
concept.get_hints().is_evaluated = True
|
concept.get_hints().is_evaluated = True
|
||||||
|
|
||||||
|
|||||||
@@ -74,27 +74,63 @@ class CertainVariable(ConceptEvaluatorVariable):
|
|||||||
return hash(("PossibleVariable", self.name))
|
return hash(("PossibleVariable", self.name))
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(eq=True, frozen=True)
|
||||||
|
class ParameterVariable(ConceptEvaluatorVariable):
|
||||||
|
"""
|
||||||
|
A parameter variable (for BNF concepts) are variables that are mandatory for the resolution of the concept
|
||||||
|
|
||||||
|
example:
|
||||||
|
def concept plus from bnf number=n1 plus number=n2 # n1 and n2 are parameters
|
||||||
|
def concept plus from bnf number plus number # number is a parameter
|
||||||
|
def concept inc from bnf (one|two)=n1 plus 1 # n1 is a parameter
|
||||||
|
def concept inc from bnf (one|two) plus 1 # (one|two) is a parameter (but with no associated variable name)
|
||||||
|
"""
|
||||||
|
is_a_variable: bool # True is the parameter has an associated variable name
|
||||||
|
|
||||||
|
def __hash__(self):
|
||||||
|
return hash(("ParameterVariable", self.name, self.is_a_variable))
|
||||||
|
|
||||||
|
|
||||||
class ConceptOrRuleVariableVisitor(ParsingExpressionVisitor):
|
class ConceptOrRuleVariableVisitor(ParsingExpressionVisitor):
|
||||||
"""
|
"""
|
||||||
Gets the concepts referenced by BNF
|
Gets the concepts referenced by BNF
|
||||||
If a rule_name is given, it will also be considered as a potential property
|
If a rule_name is given, it will also be considered as a potential property
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, context):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
self.context = context
|
||||||
self.variables = []
|
self.variables = []
|
||||||
|
self.counter = 1
|
||||||
|
|
||||||
|
def _get_parameter_name(self, node, prefix):
|
||||||
|
if not node.rule_name:
|
||||||
|
name = f"{prefix}{self.counter}"
|
||||||
|
self.counter += 1
|
||||||
|
is_a_variable = False
|
||||||
|
else:
|
||||||
|
name = node.rule_name
|
||||||
|
is_a_variable = True
|
||||||
|
return name, is_a_variable
|
||||||
|
|
||||||
def visit_ConceptExpression(self, node):
|
def visit_ConceptExpression(self, node):
|
||||||
if node.rule_name:
|
if isinstance(node.concept, Concept):
|
||||||
self.variables.append(CertainVariable(node.rule_name))
|
if self.context.sheerka.isaset(self.context, node.concept):
|
||||||
elif isinstance(node.concept, Concept):
|
parameter_name, is_a_variable = self._get_parameter_name(node, "__ConceptExpression__")
|
||||||
self.variables.append(CertainVariable(node.concept.name))
|
self.variables.append(ParameterVariable(parameter_name, is_a_variable))
|
||||||
else:
|
else:
|
||||||
self.variables.append(CertainVariable(node.concept))
|
self.variables.append(CertainVariable(node.rule_name or node.concept.name))
|
||||||
|
else:
|
||||||
|
self.variables.append(CertainVariable(node.rule_name or node.concept))
|
||||||
|
|
||||||
def visit_VariableExpression(self, node):
|
def visit_VariableExpression(self, node):
|
||||||
self.variables.append(MandatoryVariable(node.rule_name))
|
self.variables.append(MandatoryVariable(node.rule_name))
|
||||||
|
|
||||||
|
def visit_OrderedChoice(self, node):
|
||||||
|
parameter_name, is_a_variable = self._get_parameter_name(node, "__OrderedChoice__")
|
||||||
|
self.variables.append(ParameterVariable(parameter_name, is_a_variable))
|
||||||
|
self.visit_children(node)
|
||||||
|
|
||||||
def visit_all(self, node):
|
def visit_all(self, node):
|
||||||
if node.rule_name:
|
if node.rule_name:
|
||||||
self.variables.append(CertainVariable(node.rule_name))
|
self.variables.append(CertainVariable(node.rule_name))
|
||||||
@@ -127,7 +163,8 @@ class DefConceptEvaluator(OneReturnValueEvaluator):
|
|||||||
# validate the node
|
# validate the node
|
||||||
variables_found = set()
|
variables_found = set()
|
||||||
mandatory_variables = set() # these variable MUST have a match in the name (if the name is not None)
|
mandatory_variables = set() # these variable MUST have a match in the name (if the name is not None)
|
||||||
certain_variables = []
|
parameter_variables = [] # BNF variables known as concept parameter. Use a list to keep the order
|
||||||
|
certain_variables = [] # names that we know for sure that there are variables
|
||||||
skip_variables_resolution = False
|
skip_variables_resolution = False
|
||||||
|
|
||||||
concept = Concept(str(def_concept_node.name))
|
concept = Concept(str(def_concept_node.name))
|
||||||
@@ -164,6 +201,12 @@ class DefConceptEvaluator(OneReturnValueEvaluator):
|
|||||||
|
|
||||||
# try to find what can be a property
|
# try to find what can be a property
|
||||||
for p in self.get_variables(context, part_ret_val, name_to_use):
|
for p in self.get_variables(context, part_ret_val, name_to_use):
|
||||||
|
if isinstance(p, ParameterVariable):
|
||||||
|
parameter_variables.append(p.name)
|
||||||
|
if p.is_a_variable:
|
||||||
|
variables_found.add(p.name)
|
||||||
|
certain_variables.append(p.name)
|
||||||
|
else:
|
||||||
variables_found.add(p.name)
|
variables_found.add(p.name)
|
||||||
if isinstance(p, MandatoryVariable):
|
if isinstance(p, MandatoryVariable):
|
||||||
mandatory_variables.add(p.name)
|
mandatory_variables.add(p.name)
|
||||||
@@ -174,6 +217,7 @@ class DefConceptEvaluator(OneReturnValueEvaluator):
|
|||||||
for name_part in [name_part for name_part in name_to_use if str(name_part).isalnum()]:
|
for name_part in [name_part for name_part in name_to_use if str(name_part).isalnum()]:
|
||||||
if name_part in variables_found:
|
if name_part in variables_found:
|
||||||
concept.def_var(name_part, None)
|
concept.def_var(name_part, None)
|
||||||
|
concept.get_metadata().parameters.append(name_part)
|
||||||
|
|
||||||
# check that all mandatory variables are defined in the name
|
# check that all mandatory variables are defined in the name
|
||||||
# KSI: 2021-02-17
|
# KSI: 2021-02-17
|
||||||
@@ -190,6 +234,10 @@ class DefConceptEvaluator(OneReturnValueEvaluator):
|
|||||||
if p not in concept.values():
|
if p not in concept.values():
|
||||||
concept.def_var(p, None)
|
concept.def_var(p, None)
|
||||||
|
|
||||||
|
for p in parameter_variables:
|
||||||
|
if p not in concept.get_metadata().parameters:
|
||||||
|
concept.get_metadata().parameters.append(p)
|
||||||
|
|
||||||
# initialize the key
|
# initialize the key
|
||||||
key_source = def_concept_node.definition.tokens if \
|
key_source = def_concept_node.definition.tokens if \
|
||||||
def_concept_node.definition_type == DEFINITION_TYPE_DEF else \
|
def_concept_node.definition_type == DEFINITION_TYPE_DEF else \
|
||||||
@@ -251,7 +299,7 @@ class DefConceptEvaluator(OneReturnValueEvaluator):
|
|||||||
# case of BNF
|
# case of BNF
|
||||||
#
|
#
|
||||||
if isinstance(ret_value.value, ParserResultConcept) and isinstance(ret_value.value.value, ParsingExpression):
|
if isinstance(ret_value.value, ParserResultConcept) and isinstance(ret_value.value.value, ParsingExpression):
|
||||||
visitor = ConceptOrRuleVariableVisitor()
|
visitor = ConceptOrRuleVariableVisitor(context)
|
||||||
visitor.visit(ret_value.value.value)
|
visitor.visit(ret_value.value.value)
|
||||||
debugger.debug_var("names", visitor.variables, hint="from BNF")
|
debugger.debug_var("names", visitor.variables, hint="from BNF")
|
||||||
return visitor.variables
|
return visitor.variables
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ class BnfDefinitionParser(BaseParser):
|
|||||||
"""
|
"""
|
||||||
Parser used to transform literal into ParsingExpression
|
Parser used to transform literal into ParsingExpression
|
||||||
example :
|
example :
|
||||||
a | b, c -> Sequence(OrderedChoice(a, b) ,c)
|
a | b c -> Sequence(OrderedChoice(a, b), c)
|
||||||
|
|
||||||
'|' (pipe) is used for OrderedChoice
|
'|' (pipe) is used for OrderedChoice
|
||||||
',' (comma) is used for Sequence
|
' ' space is used for Sequence
|
||||||
'?' (question mark) is used for Optional
|
'?' (question mark) is used for Optional
|
||||||
'*' (star) is used for ZeroOrMore
|
'*' (star) is used for ZeroOrMore
|
||||||
'+' (plus) is used for OneOrMore
|
'+' (plus) is used for OneOrMore
|
||||||
|
|||||||
@@ -1165,6 +1165,9 @@ class ParsingExpressionVisitor:
|
|||||||
if hasattr(self, "visit_all"):
|
if hasattr(self, "visit_all"):
|
||||||
self.visit_all(parsing_expression)
|
self.visit_all(parsing_expression)
|
||||||
|
|
||||||
|
self.visit_children(parsing_expression)
|
||||||
|
|
||||||
|
def visit_children(self, parsing_expression):
|
||||||
for node in self.get_nodes(parsing_expression):
|
for node in self.get_nodes(parsing_expression):
|
||||||
if isinstance(node, Concept):
|
if isinstance(node, Concept):
|
||||||
res = self.visit(ConceptExpression(node.key or node.name))
|
res = self.visit(ConceptExpression(node.key or node.name))
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ class SequenceNodeParser(BaseNodeParser):
|
|||||||
:param concept:
|
:param concept:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
return len(concept.get_metadata().variables) == 0 \
|
return len(concept.get_metadata().parameters) == 0 \
|
||||||
and concept.get_metadata().definition_type != DEFINITION_TYPE_BNF
|
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):
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ class SyaConceptParserHelper:
|
|||||||
self.expected = temp
|
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) # and add it to the list of tokens eaten
|
||||||
|
|
||||||
def is_matched(self):
|
def is_matched(self):
|
||||||
return len(self.expected) == 0
|
return len(self.expected) == 0
|
||||||
@@ -554,7 +554,7 @@ class InFixToPostFix:
|
|||||||
|
|
||||||
def nb_expected_parameters(expected):
|
def nb_expected_parameters(expected):
|
||||||
"""
|
"""
|
||||||
Count the number of successive variables that are expected
|
Count the number of successive variables that are still expected
|
||||||
:param expected:
|
:param expected:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
@@ -1228,10 +1228,10 @@ class SyaNodeParser(BaseNodeParser):
|
|||||||
:param concept:
|
:param concept:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
# We only concepts that has parameter (refuse atoms)
|
# We only considers concepts that has parameter variables (refuse atoms)
|
||||||
# Bnf definitions are not supposed to be managed by this parser either
|
# Bnf definitions are not supposed to be managed by this parser either
|
||||||
return len(
|
return (concept.get_metadata().definition_type != DEFINITION_TYPE_BNF and
|
||||||
concept.get_metadata().variables) > 0 and concept.get_metadata().definition_type != DEFINITION_TYPE_BNF
|
len(concept.get_metadata().parameters) > 0)
|
||||||
|
|
||||||
def infix_to_postfix(self, context, parser_input: ParserInput):
|
def infix_to_postfix(self, context, parser_input: ParserInput):
|
||||||
"""
|
"""
|
||||||
@@ -1368,6 +1368,14 @@ class SyaNodeParser(BaseNodeParser):
|
|||||||
concept = sheerka.new_from_template(item.concept, item.concept.key)
|
concept = sheerka.new_from_template(item.concept, item.concept.key)
|
||||||
concept_metadata = []
|
concept_metadata = []
|
||||||
for param_index in reversed(range(len(concept.get_metadata().variables))):
|
for param_index in reversed(range(len(concept.get_metadata().variables))):
|
||||||
|
param_name = concept.get_metadata().variables[param_index][0]
|
||||||
|
|
||||||
|
if param_name not in concept.get_metadata().parameters:
|
||||||
|
# This is not a real concept parameter, but a concept variable
|
||||||
|
# just copy its default value
|
||||||
|
concept_metadata.append(concept.get_metadata().variables[param_index])
|
||||||
|
continue
|
||||||
|
|
||||||
inner_item = self.postfix_to_item(sheerka, postfixed)
|
inner_item = self.postfix_to_item(sheerka, postfixed)
|
||||||
if inner_item.start < start:
|
if inner_item.start < start:
|
||||||
start = inner_item.start
|
start = inner_item.start
|
||||||
@@ -1376,7 +1384,6 @@ class SyaNodeParser(BaseNodeParser):
|
|||||||
has_unrecognized |= isinstance(inner_item, (UnrecognizedTokensNode, SourceCodeWithConceptNode)) or \
|
has_unrecognized |= isinstance(inner_item, (UnrecognizedTokensNode, SourceCodeWithConceptNode)) or \
|
||||||
hasattr(inner_item, "has_unrecognized") and inner_item.has_unrecognized
|
hasattr(inner_item, "has_unrecognized") and inner_item.has_unrecognized
|
||||||
|
|
||||||
param_name = concept.get_metadata().variables[param_index][0]
|
|
||||||
param_value = inner_item.concept if hasattr(inner_item, "concept") else \
|
param_value = inner_item.concept if hasattr(inner_item, "concept") else \
|
||||||
[inner_item.return_value] if isinstance(inner_item, SourceCodeNode) else \
|
[inner_item.return_value] if isinstance(inner_item, SourceCodeNode) else \
|
||||||
inner_item
|
inner_item
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from dataclasses import dataclass
|
|||||||
from prompt_toolkit.completion import Completer, Completion
|
from prompt_toolkit.completion import Completer, Completion
|
||||||
|
|
||||||
from core.concept import Concept
|
from core.concept import Concept
|
||||||
from core.sheerka.Sheerka import EXIT_COMMANDS
|
from core.sheerka.Sheerka import EXIT_COMMANDS, CONTEXT_HINT_COMMANDS
|
||||||
from core.sheerka.services.SheerkaConceptManager import SheerkaConceptManager
|
from core.sheerka.services.SheerkaConceptManager import SheerkaConceptManager
|
||||||
from core.sheerka.services.SheerkaFunctionsParametersHistory import SheerkaFunctionsParametersHistory
|
from core.sheerka.services.SheerkaFunctionsParametersHistory import SheerkaFunctionsParametersHistory
|
||||||
from core.tokenizer import Tokenizer, TokenKind, LexerError
|
from core.tokenizer import Tokenizer, TokenKind, LexerError
|
||||||
@@ -154,6 +154,9 @@ class SheerkaPromptCompleter(Completer):
|
|||||||
"builtin",
|
"builtin",
|
||||||
["context"]))
|
["context"]))
|
||||||
|
|
||||||
|
for name, display in CONTEXT_HINT_COMMANDS:
|
||||||
|
self.builtins.append(CompletionDesc(name, display, "context"))
|
||||||
|
|
||||||
self.exit_commands = [CompletionDesc(c, c, "command") for c in EXIT_COMMANDS]
|
self.exit_commands = [CompletionDesc(c, c, "command") for c in EXIT_COMMANDS]
|
||||||
self.globals = {k: v.method for k, v in self.sheerka.sheerka_methods.items()}
|
self.globals = {k: v.method for k, v in self.sheerka.sheerka_methods.items()}
|
||||||
|
|
||||||
@@ -313,11 +316,12 @@ class SheerkaPromptCompleter(Completer):
|
|||||||
function_name = name + "("
|
function_name = name + "("
|
||||||
signature = inspect.signature(function)
|
signature = inspect.signature(function)
|
||||||
params_count = len([p for p in signature.parameters if p not in skip_params])
|
params_count = len([p for p in signature.parameters if p not in skip_params])
|
||||||
|
|
||||||
if params_count == 0:
|
if params_count == 0:
|
||||||
function_name += ")"
|
function_name += ")"
|
||||||
|
|
||||||
return CompletionDesc(function_name, name, meta_display)
|
return CompletionDesc(function_name, name, meta_display)
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def inside_function(text, pos):
|
def inside_function(text, pos):
|
||||||
bracket_count = 0
|
bracket_count = 0
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from core.concept import Concept, DEFINITION_TYPE_BNF, DEFINITION_TYPE_DEF, free
|
|||||||
from core.rule import Rule, ACTION_TYPE_PRINT, ACTION_TYPE_EXEC
|
from core.rule import Rule, ACTION_TYPE_PRINT, ACTION_TYPE_EXEC
|
||||||
from core.sheerka.ExecutionContext import ExecutionContext
|
from core.sheerka.ExecutionContext import ExecutionContext
|
||||||
from core.sheerka.Sheerka import Sheerka
|
from core.sheerka.Sheerka import Sheerka
|
||||||
|
from core.sheerka.services.SheerkaConceptManager import SheerkaConceptManager
|
||||||
from core.sheerka.services.SheerkaRuleManager import SheerkaRuleManager
|
from core.sheerka.services.SheerkaRuleManager import SheerkaRuleManager
|
||||||
from parsers.BnfDefinitionParser import BnfDefinitionParser
|
from parsers.BnfDefinitionParser import BnfDefinitionParser
|
||||||
from parsers.BnfNodeParser import StrMatch
|
from parsers.BnfNodeParser import StrMatch
|
||||||
@@ -47,6 +48,7 @@ class InitTestHelper:
|
|||||||
raise Exception(f"Error in bnf definition '{c.get_metadata().definition}'",
|
raise Exception(f"Error in bnf definition '{c.get_metadata().definition}'",
|
||||||
self.sheerka.get_errors(self.context, res))
|
self.sheerka.get_errors(self.context, res))
|
||||||
|
|
||||||
|
self._update_concept_parameters(c)
|
||||||
if create_new:
|
if create_new:
|
||||||
self.sheerka.create_new_concept(self.context, c)
|
self.sheerka.create_new_concept(self.context, c)
|
||||||
else:
|
else:
|
||||||
@@ -99,6 +101,12 @@ class InitTestHelper:
|
|||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def _update_concept_parameters(self, concept):
|
||||||
|
if concept.get_metadata().parameters:
|
||||||
|
return
|
||||||
|
|
||||||
|
SheerkaConceptManager.recompute_concept_parameters(self.context, concept)
|
||||||
|
|
||||||
|
|
||||||
class BaseTest:
|
class BaseTest:
|
||||||
def get_sheerka(self, **kwargs) -> Sheerka:
|
def get_sheerka(self, **kwargs) -> Sheerka:
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from cache.CacheManager import ConceptNotFound
|
|||||||
from core.builtin_concepts import BuiltinConcepts
|
from core.builtin_concepts import BuiltinConcepts
|
||||||
from core.builtin_helpers import ensure_bnf
|
from core.builtin_helpers import ensure_bnf
|
||||||
from core.concept import PROPERTIES_TO_SERIALIZE, Concept, DEFINITION_TYPE_DEF, get_concept_attrs, \
|
from core.concept import PROPERTIES_TO_SERIALIZE, Concept, DEFINITION_TYPE_DEF, get_concept_attrs, \
|
||||||
DEFINITION_TYPE_BNF
|
DEFINITION_TYPE_BNF, ConceptParts
|
||||||
from core.global_symbols import NotInit, NotFound, SyaAssociativity, CONCEPT_COMPARISON_CONTEXT
|
from core.global_symbols import NotInit, NotFound, SyaAssociativity, CONCEPT_COMPARISON_CONTEXT
|
||||||
from core.sheerka.services.SheerkaConceptManager import SheerkaConceptManager, NoModificationFound, ForbiddenAttribute, \
|
from core.sheerka.services.SheerkaConceptManager import SheerkaConceptManager, NoModificationFound, ForbiddenAttribute, \
|
||||||
UnknownAttribute, CannotRemoveMeta, ValueNotFound, ConceptIsReferenced, NoFirstTokenError
|
UnknownAttribute, CannotRemoveMeta, ValueNotFound, ConceptIsReferenced, NoFirstTokenError
|
||||||
@@ -494,13 +494,13 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
|
|||||||
to_add = {"meta": {"name": "b bar c d"},
|
to_add = {"meta": {"name": "b bar c d"},
|
||||||
"variables": {"c": None, "d": None}}
|
"variables": {"c": None, "d": None}}
|
||||||
|
|
||||||
to_remove = {"variables": ["a"]}
|
res = sheerka.modify_concept(context, foo, to_add)
|
||||||
|
|
||||||
res = sheerka.modify_concept(context, foo, to_add, to_remove)
|
|
||||||
new_concept = res.body.body
|
new_concept = res.body.body
|
||||||
|
|
||||||
assert res.status
|
assert res.status
|
||||||
assert new_concept.key == "__var__0 bar __var__1 __var__2"
|
assert new_concept.key == "__var__1 bar __var__2 __var__3"
|
||||||
|
assert new_concept.get_metadata().parameters == ["b", "c", "d"]
|
||||||
|
assert new_concept.get_metadata().variables == [("a", None), ("b", None), ("c", None), ("d", None)]
|
||||||
|
|
||||||
def test_key_is_modified_when_modifying_the_definition(self):
|
def test_key_is_modified_when_modifying_the_definition(self):
|
||||||
sheerka, context, foo = self.init_concepts(
|
sheerka, context, foo = self.init_concepts(
|
||||||
@@ -790,13 +790,101 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
|
|||||||
prop = Concept("property")
|
prop = Concept("property")
|
||||||
bar = Concept("bar")
|
bar = Concept("bar")
|
||||||
|
|
||||||
res = sheerka.set_attr(foo, prop, bar)
|
res = sheerka.set_attr(context, foo, prop, bar)
|
||||||
assert res.status
|
assert res.status
|
||||||
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
|
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
|
||||||
|
|
||||||
assert sheerka.get_attr(foo, prop) == bar
|
assert sheerka.get_attr(foo, prop) == bar
|
||||||
|
|
||||||
def test_i_setting_twice_the_same_property_creates_a_list(self):
|
def test_i_can_get_and_set_attribute_when_global_truth_is_set(self):
|
||||||
|
sheerka, context, foo, adjective, color, red, brightness, dark = self.init_test(cache_only=False).with_concepts(
|
||||||
|
"foo",
|
||||||
|
"adjective",
|
||||||
|
"color",
|
||||||
|
"red",
|
||||||
|
"brightness",
|
||||||
|
"dark",
|
||||||
|
create_new=True).unpack()
|
||||||
|
service = sheerka.services[SheerkaConceptManager.NAME]
|
||||||
|
global_truth_context = self.get_context(sheerka, global_truth=True)
|
||||||
|
|
||||||
|
color_instance = sheerka.new("color", body=sheerka.new("red"))
|
||||||
|
sheerka.set_attr(context, color_instance, brightness, sheerka.new("dark"))
|
||||||
|
sheerka.set_isa(context, color_instance, sheerka.new(adjective))
|
||||||
|
|
||||||
|
adjective_instance = sheerka.new("adjective")
|
||||||
|
adjective_instance.set_value(ConceptParts.BODY, color_instance)
|
||||||
|
|
||||||
|
foo_instance = sheerka.new("foo")
|
||||||
|
res = sheerka.set_attr(global_truth_context, foo_instance, sheerka.new("adjective"), adjective_instance)
|
||||||
|
assert res.status
|
||||||
|
assert sheerka.isinstance(res.body, BuiltinConcepts.NEW_CONCEPT)
|
||||||
|
|
||||||
|
# foo.adjective is modified
|
||||||
|
resolved_adjective = sheerka.get_attr(foo_instance, sheerka.new("adjective"))
|
||||||
|
assert sheerka.isinstance(resolved_adjective, "adjective")
|
||||||
|
resolved_color = resolved_adjective.body
|
||||||
|
assert sheerka.isinstance(resolved_color, "color")
|
||||||
|
assert sheerka.isa(resolved_color, adjective)
|
||||||
|
assert sheerka.get_attr(resolved_color, brightness) == dark
|
||||||
|
assert resolved_color.body == red
|
||||||
|
|
||||||
|
# foo default variable value is modified
|
||||||
|
adjective_from_default_var = foo_instance.get_metadata().variables[0][1]
|
||||||
|
assert sheerka.isinstance(adjective_from_default_var, "adjective")
|
||||||
|
color_from_default_var = resolved_adjective.body
|
||||||
|
assert sheerka.isinstance(color_from_default_var, "color")
|
||||||
|
assert sheerka.isa(color_from_default_var, adjective)
|
||||||
|
assert sheerka.get_attr(color_from_default_var, brightness) == dark
|
||||||
|
assert color_from_default_var.body == red
|
||||||
|
|
||||||
|
# new instance are update
|
||||||
|
new_instance = sheerka.new("foo")
|
||||||
|
resolved_adjective = sheerka.get_attr(new_instance, sheerka.new("adjective"))
|
||||||
|
assert sheerka.isinstance(resolved_adjective, "adjective")
|
||||||
|
resolved_color = resolved_adjective.body
|
||||||
|
assert sheerka.isinstance(resolved_color, "color")
|
||||||
|
assert sheerka.isa(resolved_color, adjective)
|
||||||
|
assert sheerka.get_attr(resolved_color, brightness) == dark
|
||||||
|
assert resolved_color.body == red
|
||||||
|
# No need to check the default variable value since the attribute is updated
|
||||||
|
|
||||||
|
# make sure it's persisted in DB
|
||||||
|
sheerka.om.commit(context)
|
||||||
|
from_db = sheerka.om.current_sdp().get(service.CONCEPTS_BY_ID_ENTRY, foo.id)
|
||||||
|
# concepts values are never persisted in DB.
|
||||||
|
# only check the default value of the variable
|
||||||
|
adjective_from_default_var = from_db.get_metadata().variables[0][1]
|
||||||
|
assert sheerka.isinstance(adjective_from_default_var, "adjective")
|
||||||
|
color_from_default_var = resolved_adjective.body
|
||||||
|
assert sheerka.isinstance(color_from_default_var, "color")
|
||||||
|
assert sheerka.isa(color_from_default_var, adjective)
|
||||||
|
assert sheerka.get_attr(color_from_default_var, brightness) == dark
|
||||||
|
assert color_from_default_var.body == red
|
||||||
|
|
||||||
|
# check that we can access the values
|
||||||
|
assert foo_instance.values() == {'c:adjective|1002:': adjective_instance}
|
||||||
|
assert new_instance.values() == {'c:adjective|1002:': adjective_instance}
|
||||||
|
assert from_db.values() == {'c:adjective|1002:': NotInit}
|
||||||
|
assert foo.values() == {'c:adjective|1002:': NotInit}
|
||||||
|
|
||||||
|
def test_i_can_set_attr_twice_is_the_second_time_global_truth_is_true(self):
|
||||||
|
sheerka, context, foo, prop, value = self.init_test(cache_only=False).with_concepts(
|
||||||
|
"foo",
|
||||||
|
"prop",
|
||||||
|
"value",
|
||||||
|
create_new=True).unpack()
|
||||||
|
global_truth_context = self.get_context(sheerka, global_truth=True)
|
||||||
|
|
||||||
|
foo_instance = sheerka.new("foo")
|
||||||
|
sheerka.set_attr(context, foo_instance, prop, value)
|
||||||
|
|
||||||
|
sheerka.set_attr(global_truth_context, foo_instance, prop, value)
|
||||||
|
|
||||||
|
new_instance = sheerka.new("foo")
|
||||||
|
assert sheerka.get_attr(new_instance, prop) == value
|
||||||
|
|
||||||
|
def test_setting_twice_the_same_property_creates_a_list(self):
|
||||||
sheerka, context = self.init_concepts()
|
sheerka, context = self.init_concepts()
|
||||||
foo = Concept("foo")
|
foo = Concept("foo")
|
||||||
prop = Concept("property")
|
prop = Concept("property")
|
||||||
@@ -804,22 +892,22 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
|
|||||||
baz = Concept("baz")
|
baz = Concept("baz")
|
||||||
qux = Concept("qux")
|
qux = Concept("qux")
|
||||||
|
|
||||||
res = sheerka.set_attr(foo, prop, bar)
|
res = sheerka.set_attr(context, foo, prop, bar)
|
||||||
assert res.status
|
assert res.status
|
||||||
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
|
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
|
||||||
assert sheerka.get_attr(foo, prop) == bar
|
assert sheerka.get_attr(foo, prop) == bar
|
||||||
|
|
||||||
res = sheerka.set_attr(foo, prop, bar) # again, same value as no effect
|
res = sheerka.set_attr(context, foo, prop, bar) # again, same value as no effect
|
||||||
assert res.status
|
assert res.status
|
||||||
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
|
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
|
||||||
assert sheerka.get_attr(foo, prop) == bar
|
assert sheerka.get_attr(foo, prop) == bar
|
||||||
|
|
||||||
res = sheerka.set_attr(foo, prop, baz)
|
res = sheerka.set_attr(context, foo, prop, baz)
|
||||||
assert res.status
|
assert res.status
|
||||||
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
|
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
|
||||||
assert sheerka.get_attr(foo, prop) == [bar, baz]
|
assert sheerka.get_attr(foo, prop) == [bar, baz]
|
||||||
|
|
||||||
res = sheerka.set_attr(foo, prop, qux)
|
res = sheerka.set_attr(context, foo, prop, qux)
|
||||||
assert res.status
|
assert res.status
|
||||||
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
|
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
|
||||||
assert sheerka.get_attr(foo, prop) == [bar, baz, qux]
|
assert sheerka.get_attr(foo, prop) == [bar, baz, qux]
|
||||||
@@ -1241,7 +1329,7 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
|
|||||||
prop = Concept("property")
|
prop = Concept("property")
|
||||||
bar = Concept("bar")
|
bar = Concept("bar")
|
||||||
|
|
||||||
sheerka.set_attr(foo, prop, bar)
|
sheerka.set_attr(context, foo, prop, bar)
|
||||||
assert sheerka.smart_get_attr(foo, prop) == bar
|
assert sheerka.smart_get_attr(foo, prop) == bar
|
||||||
|
|
||||||
def test_i_can_smart_get_attr_when_simple_isa(self):
|
def test_i_can_smart_get_attr_when_simple_isa(self):
|
||||||
@@ -1256,7 +1344,7 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
|
|||||||
color_instance = sheerka.new(color, body=red)
|
color_instance = sheerka.new(color, body=red)
|
||||||
adjective_instance = sheerka.new(adjective, body=color_instance)
|
adjective_instance = sheerka.new(adjective, body=color_instance)
|
||||||
table_instance = sheerka.new(table)
|
table_instance = sheerka.new(table)
|
||||||
sheerka.set_attr(table_instance, adjective, adjective_instance)
|
sheerka.set_attr(context, table_instance, adjective, adjective_instance)
|
||||||
|
|
||||||
assert sheerka.smart_get_attr(table_instance, color) == color_instance
|
assert sheerka.smart_get_attr(table_instance, color) == color_instance
|
||||||
assert sheerka.objvalue(sheerka.smart_get_attr(table_instance, color)) == red
|
assert sheerka.objvalue(sheerka.smart_get_attr(table_instance, color)) == red
|
||||||
@@ -1276,7 +1364,7 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
|
|||||||
color_instance = sheerka.new(color, body=reddish_instance)
|
color_instance = sheerka.new(color, body=reddish_instance)
|
||||||
adjective_instance = sheerka.new(adjective, body=color_instance)
|
adjective_instance = sheerka.new(adjective, body=color_instance)
|
||||||
table_instance = sheerka.new(table)
|
table_instance = sheerka.new(table)
|
||||||
sheerka.set_attr(table_instance, adjective, adjective_instance)
|
sheerka.set_attr(context, table_instance, adjective, adjective_instance)
|
||||||
|
|
||||||
assert sheerka.smart_get_attr(table_instance, reddish_instance) == reddish_instance
|
assert sheerka.smart_get_attr(table_instance, reddish_instance) == reddish_instance
|
||||||
assert sheerka.objvalue(sheerka.smart_get_attr(table_instance, color)) == red
|
assert sheerka.objvalue(sheerka.smart_get_attr(table_instance, color)) == red
|
||||||
@@ -1296,12 +1384,12 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
|
|||||||
# add red color
|
# add red color
|
||||||
red_color_instance = sheerka.new(color, body=red)
|
red_color_instance = sheerka.new(color, body=red)
|
||||||
red_adjective_instance = sheerka.new(adjective, body=red_color_instance)
|
red_adjective_instance = sheerka.new(adjective, body=red_color_instance)
|
||||||
sheerka.set_attr(table_instance, adjective, red_adjective_instance)
|
sheerka.set_attr(context, table_instance, adjective, red_adjective_instance)
|
||||||
|
|
||||||
# add blue color
|
# add blue color
|
||||||
blue_color_instance = sheerka.new(color, body=blue)
|
blue_color_instance = sheerka.new(color, body=blue)
|
||||||
blue_adjective_instance = sheerka.new(adjective, body=blue_color_instance)
|
blue_adjective_instance = sheerka.new(adjective, body=blue_color_instance)
|
||||||
sheerka.set_attr(table_instance, adjective, blue_adjective_instance)
|
sheerka.set_attr(context, table_instance, adjective, blue_adjective_instance)
|
||||||
|
|
||||||
res = sheerka.smart_get_attr(table_instance, color)
|
res = sheerka.smart_get_attr(table_instance, color)
|
||||||
assert res == [red_color_instance, blue_color_instance]
|
assert res == [red_color_instance, blue_color_instance]
|
||||||
@@ -1317,7 +1405,7 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
|
|||||||
|
|
||||||
color_instance = sheerka.new(color, body=red)
|
color_instance = sheerka.new(color, body=red)
|
||||||
table_instance = sheerka.new(table)
|
table_instance = sheerka.new(table)
|
||||||
sheerka.set_attr(table_instance, color, color_instance)
|
sheerka.set_attr(context, table_instance, color, color_instance)
|
||||||
|
|
||||||
assert sheerka.smart_get_attr(table_instance, adjective) == color_instance
|
assert sheerka.smart_get_attr(table_instance, adjective) == color_instance
|
||||||
|
|
||||||
@@ -1336,9 +1424,9 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
|
|||||||
|
|
||||||
table_instance = sheerka.new(table)
|
table_instance = sheerka.new(table)
|
||||||
color_instance = sheerka.new(color, body=red)
|
color_instance = sheerka.new(color, body=red)
|
||||||
sheerka.set_attr(table_instance, color, color_instance)
|
sheerka.set_attr(context, table_instance, color, color_instance)
|
||||||
size_instance = sheerka.new(size, body=large)
|
size_instance = sheerka.new(size, body=large)
|
||||||
sheerka.set_attr(table_instance, size, size_instance)
|
sheerka.set_attr(context, table_instance, size, size_instance)
|
||||||
|
|
||||||
assert sheerka.smart_get_attr(table_instance, adjective) == [color_instance, size_instance]
|
assert sheerka.smart_get_attr(table_instance, adjective) == [color_instance, size_instance]
|
||||||
|
|
||||||
@@ -1355,8 +1443,8 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
|
|||||||
color_instance = sheerka.new(color, body=red)
|
color_instance = sheerka.new(color, body=red)
|
||||||
adjective_instance = sheerka.new(adjective, body=color_instance)
|
adjective_instance = sheerka.new(adjective, body=color_instance)
|
||||||
table_instance = sheerka.new(table)
|
table_instance = sheerka.new(table)
|
||||||
sheerka.set_attr(table_instance, adjective, adjective_instance)
|
sheerka.set_attr(context, table_instance, adjective, adjective_instance)
|
||||||
sheerka.set_attr(table_instance, color, blue) # set direct color value
|
sheerka.set_attr(context, table_instance, color, blue) # set direct color value
|
||||||
|
|
||||||
assert sheerka.smart_get_attr(table_instance, color) == blue
|
assert sheerka.smart_get_attr(table_instance, color) == blue
|
||||||
|
|
||||||
@@ -1372,8 +1460,8 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
|
|||||||
|
|
||||||
color_instance = sheerka.new(color, body=red)
|
color_instance = sheerka.new(color, body=red)
|
||||||
table_instance = sheerka.new(table)
|
table_instance = sheerka.new(table)
|
||||||
sheerka.set_attr(table_instance, color, color_instance)
|
sheerka.set_attr(context, table_instance, color, color_instance)
|
||||||
sheerka.set_attr(table_instance, adjective, blue) # set direct color value
|
sheerka.set_attr(context, table_instance, adjective, blue) # set direct color value
|
||||||
|
|
||||||
assert sheerka.smart_get_attr(table_instance, adjective) == blue
|
assert sheerka.smart_get_attr(table_instance, adjective) == blue
|
||||||
|
|
||||||
@@ -1397,7 +1485,7 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
|
|||||||
color_instance = sheerka.new(color, body=red)
|
color_instance = sheerka.new(color, body=red)
|
||||||
adjective_instance = sheerka.new(adjective, body=color_instance)
|
adjective_instance = sheerka.new(adjective, body=color_instance)
|
||||||
table_instance = sheerka.new(table)
|
table_instance = sheerka.new(table)
|
||||||
sheerka.set_attr(table_instance, adjective, adjective_instance)
|
sheerka.set_attr(context, table_instance, adjective, adjective_instance)
|
||||||
|
|
||||||
res = sheerka.smart_get_attr(table_instance, color)
|
res = sheerka.smart_get_attr(table_instance, color)
|
||||||
assert sheerka.isinstance(res, BuiltinConcepts.NOT_FOUND)
|
assert sheerka.isinstance(res, BuiltinConcepts.NOT_FOUND)
|
||||||
@@ -1417,7 +1505,7 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
|
|||||||
table_instance = sheerka.new(table)
|
table_instance = sheerka.new(table)
|
||||||
color_instance = sheerka.new(color, body=red)
|
color_instance = sheerka.new(color, body=red)
|
||||||
adjective_instance = sheerka.new(adjective, body=color_instance)
|
adjective_instance = sheerka.new(adjective, body=color_instance)
|
||||||
sheerka.set_attr(table_instance, adjective, adjective_instance)
|
sheerka.set_attr(context, table_instance, adjective, adjective_instance)
|
||||||
|
|
||||||
res = sheerka.smart_get_attr(table_instance, size)
|
res = sheerka.smart_get_attr(table_instance, size)
|
||||||
assert sheerka.isinstance(res, BuiltinConcepts.NOT_FOUND)
|
assert sheerka.isinstance(res, BuiltinConcepts.NOT_FOUND)
|
||||||
|
|||||||
@@ -533,7 +533,7 @@ class TestSheerkaDebugManager(TestUsingMemoryBasedSheerka):
|
|||||||
def test_i_can_inspect_object_with_concept(self):
|
def test_i_can_inspect_object_with_concept(self):
|
||||||
sheerka, context, foo = self.init_concepts("foo")
|
sheerka, context, foo = self.init_concepts("foo")
|
||||||
foo.values() # freeze known attributes
|
foo.values() # freeze known attributes
|
||||||
sheerka.set_attr(foo, "new_var", "var_value")
|
sheerka.set_attr(context, foo, "new_var", "var_value")
|
||||||
|
|
||||||
dummy = DummyObj(foo, "value")
|
dummy = DummyObj(foo, "value")
|
||||||
res = sheerka.inspect(context, dummy)
|
res = sheerka.inspect(context, dummy)
|
||||||
@@ -542,7 +542,7 @@ class TestSheerkaDebugManager(TestUsingMemoryBasedSheerka):
|
|||||||
def test_i_can_inspect_object_with_concept_when_as_bag(self):
|
def test_i_can_inspect_object_with_concept_when_as_bag(self):
|
||||||
sheerka, context, foo = self.init_concepts("foo")
|
sheerka, context, foo = self.init_concepts("foo")
|
||||||
foo.values() # freeze known attributes
|
foo.values() # freeze known attributes
|
||||||
sheerka.set_attr(foo, "new_var", "var_value")
|
sheerka.set_attr(context, foo, "new_var", "var_value")
|
||||||
|
|
||||||
dummy = DummyObj(foo, "value")
|
dummy = DummyObj(foo, "value")
|
||||||
res = sheerka.inspect(context, dummy, as_bag=True)
|
res = sheerka.inspect(context, dummy, as_bag=True)
|
||||||
@@ -557,7 +557,7 @@ class TestSheerkaDebugManager(TestUsingMemoryBasedSheerka):
|
|||||||
def test_i_can_inspect_object_with_concept_when_values(self):
|
def test_i_can_inspect_object_with_concept_when_values(self):
|
||||||
sheerka, context, foo = self.init_concepts("foo")
|
sheerka, context, foo = self.init_concepts("foo")
|
||||||
foo.values() # freeze known attributes
|
foo.values() # freeze known attributes
|
||||||
sheerka.set_attr(foo, "new_var", "var_value")
|
sheerka.set_attr(context, foo, "new_var", "var_value")
|
||||||
|
|
||||||
dummy = DummyObj(foo, "value")
|
dummy = DummyObj(foo, "value")
|
||||||
res = sheerka.inspect(context, dummy, values=True)
|
res = sheerka.inspect(context, dummy, values=True)
|
||||||
@@ -629,7 +629,7 @@ class TestSheerkaDebugManager(TestUsingMemoryBasedSheerka):
|
|||||||
def test_i_can_inspect_when_a_property_does_not_exist(self):
|
def test_i_can_inspect_when_a_property_does_not_exist(self):
|
||||||
sheerka, context, foo = self.init_concepts("foo")
|
sheerka, context, foo = self.init_concepts("foo")
|
||||||
foo.values() # freeze known attributes
|
foo.values() # freeze known attributes
|
||||||
sheerka.set_attr(foo, "new_var", "var_value")
|
sheerka.set_attr(context, foo, "new_var", "var_value")
|
||||||
|
|
||||||
dummy = DummyObj(foo, "value")
|
dummy = DummyObj(foo, "value")
|
||||||
res = sheerka.inspect(context, dummy, "#type#", "fake", "a", "b")
|
res = sheerka.inspect(context, dummy, "#type#", "fake", "a", "b")
|
||||||
@@ -641,7 +641,7 @@ class TestSheerkaDebugManager(TestUsingMemoryBasedSheerka):
|
|||||||
def test_i_can_inspect_when_properties_are_specified_several_times(self):
|
def test_i_can_inspect_when_properties_are_specified_several_times(self):
|
||||||
sheerka, context, foo = self.init_concepts("foo")
|
sheerka, context, foo = self.init_concepts("foo")
|
||||||
foo.values() # freeze known attributes
|
foo.values() # freeze known attributes
|
||||||
sheerka.set_attr(foo, "new_var", "var_value")
|
sheerka.set_attr(context, foo, "new_var", "var_value")
|
||||||
|
|
||||||
dummy = DummyObj(foo, "value")
|
dummy = DummyObj(foo, "value")
|
||||||
res = sheerka.inspect(context, dummy, "#type#", "a", "b", "a")
|
res = sheerka.inspect(context, dummy, "#type#", "a", "b", "a")
|
||||||
|
|||||||
@@ -314,7 +314,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
|||||||
|
|
||||||
def test_i_can_evaluate_when_variable_asts_is_a_list(self):
|
def test_i_can_evaluate_when_variable_asts_is_a_list(self):
|
||||||
sheerka = self.get_sheerka()
|
sheerka = self.get_sheerka()
|
||||||
foo = Concept("foo", body="1")
|
foo = Concept("foo", body="1").init_key()
|
||||||
|
|
||||||
concept = Concept("to_eval").def_var("prop")
|
concept = Concept("to_eval").def_var("prop")
|
||||||
concept.get_compiled()["prop"] = [foo, DoNotResolve("1")]
|
concept.get_compiled()["prop"] = [foo, DoNotResolve("1")]
|
||||||
@@ -467,14 +467,6 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
|
|||||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
|
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
|
||||||
assert sheerka.isinstance(evaluated, BuiltinConcepts.CONCEPT_EVAL_ERROR)
|
assert sheerka.isinstance(evaluated, BuiltinConcepts.CONCEPT_EVAL_ERROR)
|
||||||
|
|
||||||
def test_key_is_initialized_by_evaluation(self):
|
|
||||||
sheerka = self.get_sheerka()
|
|
||||||
|
|
||||||
concept = Concept("foo")
|
|
||||||
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
|
|
||||||
|
|
||||||
assert evaluated.key == concept.init_key().key
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("where_clause, expected, expected_prop, expected_body", [
|
@pytest.mark.parametrize("where_clause, expected, expected_prop, expected_body", [
|
||||||
("True", True, None, NotInit),
|
("True", True, None, NotInit),
|
||||||
("False", False, ConceptParts.WHERE, NotInit),
|
("False", False, ConceptParts.WHERE, NotInit),
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ class TestSheerkaMemory(TestUsingMemoryBasedSheerka):
|
|||||||
instantiated_foo = sheerka.new(foo, x="value1")
|
instantiated_foo = sheerka.new(foo, x="value1")
|
||||||
instantiated_one = ensure_evaluated(context, sheerka.new(inner_value))
|
instantiated_one = ensure_evaluated(context, sheerka.new(inner_value))
|
||||||
instantiated_value = sheerka.new(value, x=instantiated_one)
|
instantiated_value = sheerka.new(value, x=instantiated_one)
|
||||||
sheerka.set_attr(instantiated_foo, prop, instantiated_value)
|
sheerka.set_attr(context, instantiated_foo, prop, instantiated_value)
|
||||||
|
|
||||||
sheerka.add_to_memory(context, "foo", instantiated_foo)
|
sheerka.add_to_memory(context, "foo", instantiated_foo)
|
||||||
sheerka.om.commit(context)
|
sheerka.om.commit(context)
|
||||||
|
|||||||
@@ -64,10 +64,10 @@ def test_i_can_serialize():
|
|||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
concept = Concept(
|
concept = Concept(
|
||||||
name="concept_name",
|
name="concept_name a",
|
||||||
is_builtin=True,
|
is_builtin=True,
|
||||||
is_unique=True,
|
is_unique=True,
|
||||||
key="concept_key",
|
key=None,
|
||||||
body="definition of the body",
|
body="definition of the body",
|
||||||
where="definition of the where",
|
where="definition of the where",
|
||||||
pre="definition of the pre",
|
pre="definition of the pre",
|
||||||
@@ -78,6 +78,8 @@ def test_i_can_serialize():
|
|||||||
desc="this this the desc",
|
desc="this this the desc",
|
||||||
id="123456"
|
id="123456"
|
||||||
).def_var("a", "10").def_var("b", None)
|
).def_var("a", "10").def_var("b", None)
|
||||||
|
concept.get_metadata().parameters = ["a"]
|
||||||
|
concept.init_key()
|
||||||
|
|
||||||
to_dict = concept.to_dict()
|
to_dict = concept.to_dict()
|
||||||
assert to_dict == {
|
assert to_dict == {
|
||||||
@@ -88,14 +90,15 @@ def test_i_can_serialize():
|
|||||||
'id': '123456',
|
'id': '123456',
|
||||||
'is_builtin': True,
|
'is_builtin': True,
|
||||||
'is_unique': True,
|
'is_unique': True,
|
||||||
'key': 'concept_key',
|
'key': 'concept_name __var__0',
|
||||||
'name': 'concept_name',
|
'name': 'concept_name a',
|
||||||
'post': 'definition of the post',
|
'post': 'definition of the post',
|
||||||
'pre': 'definition of the pre',
|
'pre': 'definition of the pre',
|
||||||
'ret': "concept to return",
|
'ret': "concept to return",
|
||||||
'props': {},
|
'props': {},
|
||||||
'variables': [('a', "10"), ('b', None)],
|
'variables': [('a', "10"), ('b', None)],
|
||||||
'where': 'definition of the where'
|
'where': 'definition of the where',
|
||||||
|
'parameters': ['a'],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -302,3 +305,33 @@ def test_i_can_manage_instance_attributes():
|
|||||||
assert foo.values() == {"x": "value for x", "y": "value for y"}
|
assert foo.values() == {"x": "value for x", "y": "value for y"}
|
||||||
assert foo.get_all_attributes() == ["x", "y"]
|
assert foo.get_all_attributes() == ["x", "y"]
|
||||||
assert ALL_ATTRIBUTES == {"foo_id": ["x"]}
|
assert ALL_ATTRIBUTES == {"foo_id": ["x"]}
|
||||||
|
|
||||||
|
|
||||||
|
def test_i_can_init_key_and_compute_parameters():
|
||||||
|
concept = Concept("foo x").def_var("x").init_key()
|
||||||
|
assert concept.key == "foo __var__0"
|
||||||
|
|
||||||
|
concept = Concept("foo").def_var("x").init_key()
|
||||||
|
assert concept.key == "foo"
|
||||||
|
|
||||||
|
concept = Concept("foo a b").def_var("a").def_var("b").init_key()
|
||||||
|
assert concept.key == "foo __var__0 __var__1"
|
||||||
|
|
||||||
|
concept = Concept("foo a b").def_var("b").def_var("a").init_key()
|
||||||
|
assert concept.key == "foo __var__1 __var__0"
|
||||||
|
|
||||||
|
concept = Concept("foo a b").def_var("a").init_key()
|
||||||
|
assert concept.key == "foo __var__0 b"
|
||||||
|
|
||||||
|
concept = Concept("foo a b").def_var("b").init_key()
|
||||||
|
assert concept.key == "foo a __var__0"
|
||||||
|
|
||||||
|
concept = Concept("foo a").def_var("a").def_var("b").init_key()
|
||||||
|
assert concept.key == "foo __var__0"
|
||||||
|
|
||||||
|
concept = Concept("foo b").def_var("a").def_var("b").init_key()
|
||||||
|
assert concept.key == "foo __var__1"
|
||||||
|
|
||||||
|
concept = Concept("plus", definition_type=DEFINITION_TYPE_DEF, definition="a plus b").def_var("a").def_var("b")
|
||||||
|
concept.init_key()
|
||||||
|
assert concept.key == "__var__0 plus __var__1"
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
|
|||||||
assert result.value.get_value(ConceptParts.POST) == 4
|
assert result.value.get_value(ConceptParts.POST) == 4
|
||||||
assert result.value.get_value("a") == 5
|
assert result.value.get_value("a") == 5
|
||||||
assert result.value.get_value("b") == 6
|
assert result.value.get_value("b") == 6
|
||||||
assert result.value.key == "foo"
|
|
||||||
assert result.parents == [item]
|
assert result.parents == [item]
|
||||||
|
|
||||||
def test_body_is_returned_when_defined_and_requested(self):
|
def test_body_is_returned_when_defined_and_requested(self):
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from core.concept import VARIABLE_PREFIX, Concept, DEFINITION_TYPE_BNF, DEFINITI
|
|||||||
from core.sheerka.services.SheerkaConceptManager import NoFirstTokenError
|
from core.sheerka.services.SheerkaConceptManager import NoFirstTokenError
|
||||||
from core.sheerka.services.SheerkaExecute import ParserInput
|
from core.sheerka.services.SheerkaExecute import ParserInput
|
||||||
from core.tokenizer import Tokenizer
|
from core.tokenizer import Tokenizer
|
||||||
from evaluators.DefConceptEvaluator import DefConceptEvaluator, PossibleVariable, CertainVariable
|
from evaluators.DefConceptEvaluator import DefConceptEvaluator, PossibleVariable, CertainVariable, ParameterVariable
|
||||||
from parsers.BaseParser import BaseParser
|
from parsers.BaseParser import BaseParser
|
||||||
from parsers.BnfDefinitionParser import BnfDefinitionParser
|
from parsers.BnfDefinitionParser import BnfDefinitionParser
|
||||||
from parsers.BnfNodeParser import Sequence, StrMatch, ZeroOrMore, ConceptExpression, VariableExpression
|
from parsers.BnfNodeParser import Sequence, StrMatch, ZeroOrMore, ConceptExpression, VariableExpression
|
||||||
@@ -200,7 +200,7 @@ class TestDefConceptEvaluator(TestUsingMemoryBasedSheerka):
|
|||||||
def_ret_val = DefConceptParser().parse(context, ParserInput(text))
|
def_ret_val = DefConceptParser().parse(context, ParserInput(text))
|
||||||
concept_definition = def_ret_val.value.body.definition
|
concept_definition = def_ret_val.value.body.definition
|
||||||
|
|
||||||
expected = [CertainVariable("unit"), CertainVariable("one"), CertainVariable("two")]
|
expected = [ParameterVariable("unit", True), CertainVariable("one"), CertainVariable("two")]
|
||||||
assert DefConceptEvaluator.get_variables(context, concept_definition, []) == expected
|
assert DefConceptEvaluator.get_variables(context, concept_definition, []) == expected
|
||||||
|
|
||||||
def test_i_can_recognize_variables_when_referencing_other_concepts(self):
|
def test_i_can_recognize_variables_when_referencing_other_concepts(self):
|
||||||
@@ -326,6 +326,84 @@ class TestDefConceptEvaluator(TestUsingMemoryBasedSheerka):
|
|||||||
assert evaluated.body.body.key == "foo2 __var__0"
|
assert evaluated.body.body.key == "foo2 __var__0"
|
||||||
assert evaluated.body.body.get_metadata().variables == [("x", None)]
|
assert evaluated.body.body.get_metadata().variables == [("x", None)]
|
||||||
|
|
||||||
|
def test_i_can_eval_when_bnf_with_implicit_variables_from_named_ordered_choice(self):
|
||||||
|
sheerka, context, one, two = self.init_concepts("one", "two", create_new=True)
|
||||||
|
text = "def concept plus from bnf (one|two)=n1 'plus' (one|two)=n2 as n1 + n2"
|
||||||
|
def_ret_val = DefConceptParser().parse(context, ParserInput(text))
|
||||||
|
evaluated = DefConceptEvaluator().eval(context, def_ret_val)
|
||||||
|
|
||||||
|
assert evaluated.status
|
||||||
|
assert context.sheerka.isinstance(evaluated.body, BuiltinConcepts.NEW_CONCEPT)
|
||||||
|
|
||||||
|
created_concept = evaluated.body.body
|
||||||
|
assert created_concept.get_metadata().name == "plus"
|
||||||
|
assert created_concept.get_metadata().key == "plus"
|
||||||
|
assert created_concept.get_metadata().definition == "(one|two)=n1 'plus' (one|two)=n2"
|
||||||
|
assert created_concept.get_metadata().definition_type == "bnf"
|
||||||
|
assert created_concept.get_metadata().variables == [('n1', None), ('one', None), ('two', None), ('n2', None)]
|
||||||
|
assert created_concept.get_metadata().parameters == ['n1', 'n2']
|
||||||
|
|
||||||
|
def test_i_can_eval_when_bnf_with_implicit_variables_from_unamed_ordered_choice(self):
|
||||||
|
sheerka, context, one, two, three = self.init_concepts("one", "two", "three", create_new=True)
|
||||||
|
text = "def concept choice from bnf (one|two) 'or' (two|three) 'or' (two|three)=c3"
|
||||||
|
def_ret_val = DefConceptParser().parse(context, ParserInput(text))
|
||||||
|
evaluated = DefConceptEvaluator().eval(context, def_ret_val)
|
||||||
|
|
||||||
|
assert evaluated.status
|
||||||
|
assert context.sheerka.isinstance(evaluated.body, BuiltinConcepts.NEW_CONCEPT)
|
||||||
|
|
||||||
|
created_concept = evaluated.body.body
|
||||||
|
assert created_concept.get_metadata().name == "choice"
|
||||||
|
assert created_concept.get_metadata().key == "choice"
|
||||||
|
assert created_concept.get_metadata().definition == "(one|two) 'or' (two|three) 'or' (two|three)=c3"
|
||||||
|
assert created_concept.get_metadata().definition_type == "bnf"
|
||||||
|
assert created_concept.get_metadata().variables == [('one', None), ('two', None), ('three', None), ('c3', None)]
|
||||||
|
assert created_concept.get_metadata().parameters == ['__OrderedChoice__1', '__OrderedChoice__2', "c3"]
|
||||||
|
|
||||||
|
def test_i_can_eval_when_bnf_with_implicit_variables_from_unordered_choice(self):
|
||||||
|
# as it's not possible to directly defined UnorderedChoice, we test isa concept
|
||||||
|
sheerka, context, one, two, number = self.init_concepts("one", "two", "number", create_new=True)
|
||||||
|
global_truth_context = self.get_context(global_truth=True)
|
||||||
|
sheerka.set_isa(global_truth_context, one, number)
|
||||||
|
sheerka.set_isa(global_truth_context, two, number)
|
||||||
|
|
||||||
|
text = "def concept plus from bnf number=n1 'plus' number=n2 as n1 + n2"
|
||||||
|
def_ret_val = DefConceptParser().parse(context, ParserInput(text))
|
||||||
|
evaluated = DefConceptEvaluator().eval(context, def_ret_val)
|
||||||
|
|
||||||
|
assert evaluated.status
|
||||||
|
assert context.sheerka.isinstance(evaluated.body, BuiltinConcepts.NEW_CONCEPT)
|
||||||
|
|
||||||
|
created_concept = evaluated.body.body
|
||||||
|
assert created_concept.get_metadata().name == "plus"
|
||||||
|
assert created_concept.get_metadata().key == "plus"
|
||||||
|
assert created_concept.get_metadata().definition == "number=n1 'plus' number=n2"
|
||||||
|
assert created_concept.get_metadata().definition_type == "bnf"
|
||||||
|
assert created_concept.get_metadata().variables == [('n1', None), ('n2', None)]
|
||||||
|
assert created_concept.get_metadata().parameters == ['n1', 'n2']
|
||||||
|
|
||||||
|
def test_i_can_eval_when_bnf_with_implicit_variables_from_unamed_unordered_choice(self):
|
||||||
|
# as it's not possible to directly defined UnorderedChoice, we test isa concept
|
||||||
|
sheerka, context, one, two, number = self.init_concepts("one", "two", "number", create_new=True)
|
||||||
|
global_truth_context = self.get_context(global_truth=True)
|
||||||
|
sheerka.set_isa(global_truth_context, one, number)
|
||||||
|
sheerka.set_isa(global_truth_context, two, number)
|
||||||
|
|
||||||
|
text = "def concept plus from bnf number 'plus' number as number[0] + number[1]"
|
||||||
|
def_ret_val = DefConceptParser().parse(context, ParserInput(text))
|
||||||
|
evaluated = DefConceptEvaluator().eval(context, def_ret_val)
|
||||||
|
|
||||||
|
assert evaluated.status
|
||||||
|
assert context.sheerka.isinstance(evaluated.body, BuiltinConcepts.NEW_CONCEPT)
|
||||||
|
|
||||||
|
created_concept = evaluated.body.body
|
||||||
|
assert created_concept.get_metadata().name == "plus"
|
||||||
|
assert created_concept.get_metadata().key == "plus"
|
||||||
|
assert created_concept.get_metadata().definition == "number 'plus' number"
|
||||||
|
assert created_concept.get_metadata().definition_type == "bnf"
|
||||||
|
assert created_concept.get_metadata().variables == [('number', None)]
|
||||||
|
assert created_concept.get_metadata().parameters == ['number']
|
||||||
|
|
||||||
def test_i_can_eval_when_bnf_concept_with_regex(self):
|
def test_i_can_eval_when_bnf_concept_with_regex(self):
|
||||||
context = self.get_context()
|
context = self.get_context()
|
||||||
def_ret_val = DefConceptParser().parse(context, ParserInput("def concept hello a from bnf r'[a-z]+'=a 'hello'"))
|
def_ret_val = DefConceptParser().parse(context, ParserInput("def concept hello a from bnf r'[a-z]+'=a 'hello'"))
|
||||||
@@ -339,6 +417,8 @@ class TestDefConceptEvaluator(TestUsingMemoryBasedSheerka):
|
|||||||
assert created_concept.get_metadata().key == "hello __var__0"
|
assert created_concept.get_metadata().key == "hello __var__0"
|
||||||
assert created_concept.get_metadata().definition == "r'[a-z]+'=a 'hello'"
|
assert created_concept.get_metadata().definition == "r'[a-z]+'=a 'hello'"
|
||||||
assert created_concept.get_metadata().definition_type == "bnf"
|
assert created_concept.get_metadata().definition_type == "bnf"
|
||||||
|
assert created_concept.get_metadata().variables == [('a', None)]
|
||||||
|
assert created_concept.get_metadata().parameters == ['a']
|
||||||
|
|
||||||
def test_i_can_eval_when_bnf_concept_with_variable(self):
|
def test_i_can_eval_when_bnf_concept_with_variable(self):
|
||||||
context = self.get_context()
|
context = self.get_context()
|
||||||
@@ -355,6 +435,8 @@ class TestDefConceptEvaluator(TestUsingMemoryBasedSheerka):
|
|||||||
assert created_concept.get_metadata().definition_type == "bnf"
|
assert created_concept.get_metadata().definition_type == "bnf"
|
||||||
assert created_concept.get_metadata().variables == [("x", None)]
|
assert created_concept.get_metadata().variables == [("x", None)]
|
||||||
assert created_concept._bnf == Sequence(StrMatch("hello"), VariableExpression("x"))
|
assert created_concept._bnf == Sequence(StrMatch("hello"), VariableExpression("x"))
|
||||||
|
assert created_concept.get_metadata().variables == [('x', None)]
|
||||||
|
assert created_concept.get_metadata().parameters == ['x']
|
||||||
|
|
||||||
def test_i_can_eval_when_auto_eval_is_true(self):
|
def test_i_can_eval_when_auto_eval_is_true(self):
|
||||||
sheerka, context = self.init_test().unpack()
|
sheerka, context = self.init_test().unpack()
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ as:
|
|||||||
expected.get_metadata().id = "1001"
|
expected.get_metadata().id = "1001"
|
||||||
expected.get_metadata().desc = None
|
expected.get_metadata().desc = None
|
||||||
expected.get_metadata().variables = [("a", None), ("b", None)]
|
expected.get_metadata().variables = [("a", None), ("b", None)]
|
||||||
|
expected.get_metadata().parameters = ["a", "b"]
|
||||||
expected.init_key()
|
expected.init_key()
|
||||||
|
|
||||||
sheerka = self.get_sheerka(cache_only=False)
|
sheerka = self.get_sheerka(cache_only=False)
|
||||||
@@ -134,6 +135,7 @@ as:
|
|||||||
res = sheerka.evaluate_user_input("def concept a xx b as a plus b")
|
res = sheerka.evaluate_user_input("def concept a xx b as a plus b")
|
||||||
expected = Concept(name="a xx b", body="a plus b").def_var("a").def_var("b").init_key()
|
expected = Concept(name="a xx b", body="a plus b").def_var("a").def_var("b").init_key()
|
||||||
expected.get_metadata().id = "1001"
|
expected.get_metadata().id = "1001"
|
||||||
|
expected.get_metadata().parameters = ["a", "b"]
|
||||||
|
|
||||||
assert len(res) == 1
|
assert len(res) == 1
|
||||||
assert res[0].status
|
assert res[0].status
|
||||||
@@ -1392,17 +1394,32 @@ as:
|
|||||||
"set_isa(color, adjective)",
|
"set_isa(color, adjective)",
|
||||||
"def concept what is the x of y pre is_question() as smart_get_attr(y, x)",
|
"def concept what is the x of y pre is_question() as smart_get_attr(y, x)",
|
||||||
"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",
|
|
||||||
]
|
]
|
||||||
sheerka = self.init_scenario(init, global_truth=True)
|
sheerka = self.init_scenario(init, global_truth=True)
|
||||||
|
|
||||||
|
res = sheerka.evaluate_user_input("eval a red short")
|
||||||
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
|
||||||
assert res[0].status
|
assert res[0].status
|
||||||
assert res[0].value == "red"
|
assert res[0].value == "red"
|
||||||
|
|
||||||
res = sheerka.evaluate_user_input("eval a blue short")
|
sheerka.evaluate_user_input("eval a blue short")
|
||||||
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
|
||||||
assert res[0].status
|
assert res[0].status
|
||||||
assert res[0].value == "blue"
|
assert res[0].value == "blue"
|
||||||
|
|
||||||
|
def test_i_can_access_a_concept_after_a_global_set_attr(self):
|
||||||
|
init = [
|
||||||
|
"def concept foo",
|
||||||
|
"def concept color",
|
||||||
|
"def concept red",
|
||||||
|
"global_truth(set_attr(foo, color, red))"
|
||||||
|
]
|
||||||
|
|
||||||
|
sheerka = self.init_scenario(init)
|
||||||
|
res = sheerka.evaluate_user_input("inspect(foo)")
|
||||||
|
|
||||||
|
assert len(res) == 1
|
||||||
|
assert res[0].status
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ name : foo
|
|||||||
key : foo
|
key : foo
|
||||||
definition: None
|
definition: None
|
||||||
type : None
|
type : None
|
||||||
hash : 16f7fbb8bc509b8c652edaf3d0c0457d15a37f0a862fbe03fa357b0c77249c46
|
hash : 632c9ac7f3a08777918aeee4bb53712caedc634a863ae39a641f69055ae2e238
|
||||||
body : 1
|
body : 1
|
||||||
where : None
|
where : None
|
||||||
pre : None
|
pre : None
|
||||||
@@ -45,7 +45,7 @@ name : foo
|
|||||||
key : foo
|
key : foo
|
||||||
definition: None
|
definition: None
|
||||||
type : None
|
type : None
|
||||||
hash : 7036cd5ffa9294d2e1dc9bf9c9bbe2783ace5cf7f423bfce9b28c8d33c0d1d0c
|
hash : 23a1a8bc5966982471aa19b8452e22d414a55d704431866e198570913d47fd7d
|
||||||
body : 2
|
body : 2
|
||||||
where : None
|
where : None
|
||||||
pre : None
|
pre : None
|
||||||
@@ -71,7 +71,7 @@ name : foo
|
|||||||
key : foo
|
key : foo
|
||||||
definition: None
|
definition: None
|
||||||
type : None
|
type : None
|
||||||
hash : 16f7fbb8bc509b8c652edaf3d0c0457d15a37f0a862fbe03fa357b0c77249c46
|
hash : 632c9ac7f3a08777918aeee4bb53712caedc634a863ae39a641f69055ae2e238
|
||||||
body : 1
|
body : 1
|
||||||
where : None
|
where : None
|
||||||
pre : None
|
pre : None
|
||||||
@@ -84,7 +84,7 @@ name : foo
|
|||||||
key : foo
|
key : foo
|
||||||
definition: None
|
definition: None
|
||||||
type : None
|
type : None
|
||||||
hash : e8dd1af1b6bc0eca0fb4a87a6fabb16655caa4b7a6ea9dbbd1f887757e6caf89
|
hash : 60e442c59940a2616a3783d2e34f428f4a5ae456a88539bba9a5e87cf77060a6
|
||||||
body : 2
|
body : 2
|
||||||
where : True
|
where : True
|
||||||
pre : None
|
pre : None
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from core.concept import Concept, DEFINITION_TYPE_DEF
|
|||||||
from core.sheerka.services.SheerkaExecute import ParserInput
|
from core.sheerka.services.SheerkaExecute import ParserInput
|
||||||
from parsers.SequenceNodeParser import SequenceNodeParser
|
from parsers.SequenceNodeParser import SequenceNodeParser
|
||||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||||
from tests.parsers.parsers_utils import compute_expected_array, CN, CNC, SCN, get_test_obj, compare_with_test_object, \
|
from tests.parsers.parsers_utils import compute_expected_array, CN, SCN, get_test_obj, compare_with_test_object, \
|
||||||
UTN
|
UTN
|
||||||
|
|
||||||
|
|
||||||
@@ -275,6 +275,26 @@ class TestSequenceNodeParser(TestUsingMemoryBasedSheerka):
|
|||||||
assert concept_found.get_hints().is_evaluated
|
assert concept_found.get_hints().is_evaluated
|
||||||
assert not concept_found.get_hints().is_instance
|
assert not concept_found.get_hints().is_instance
|
||||||
|
|
||||||
|
def test_i_can_parse_when_variable_is_not_a_parameter(self):
|
||||||
|
concepts_map = {
|
||||||
|
"foo": Concept("foo").def_var("a"), # 'a' is not a parameter (but a property like its color for ex)
|
||||||
|
}
|
||||||
|
|
||||||
|
text, expected = "foo", ["foo"]
|
||||||
|
sheerka, context, parser = self.init_parser(concepts_map, create_new=True, use_sheerka=True)
|
||||||
|
res = parser.parse(context, ParserInput(text))
|
||||||
|
wrapper = res.body
|
||||||
|
lexer_nodes = res.body.body
|
||||||
|
|
||||||
|
assert res.status
|
||||||
|
|
||||||
|
expected_array = compute_expected_array(concepts_map, text, expected)
|
||||||
|
assert sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||||
|
compare_with_test_object(lexer_nodes, expected_array)
|
||||||
|
assert not lexer_nodes[0].concept.get_hints().is_evaluated
|
||||||
|
assert lexer_nodes[0].concept.get_hints().use_copy
|
||||||
|
assert lexer_nodes[0].concept.get_hints().is_instance
|
||||||
|
|
||||||
@pytest.mark.parametrize("text", [
|
@pytest.mark.parametrize("text", [
|
||||||
"foo",
|
"foo",
|
||||||
f"foo one",
|
f"foo one",
|
||||||
|
|||||||
@@ -1114,6 +1114,33 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
|
|||||||
# check metadata
|
# check metadata
|
||||||
assert expected_concept.get_metadata().variables == [("a", "twenty one")]
|
assert expected_concept.get_metadata().variables == [("a", "twenty one")]
|
||||||
|
|
||||||
|
def test_i_can_parse_when_all_variables_are_not_parameters(self):
|
||||||
|
my_map = {
|
||||||
|
"foo": Concept("foo a").def_var("a", "'default_a'").def_var("b", "'default_b'"), # 'b' is not a parameter
|
||||||
|
"bar": Concept("bar b").def_var("a", "'default_a'").def_var("b", "'default_b'"), # 'a' is not a parameter
|
||||||
|
"baz": Concept("baz")
|
||||||
|
}
|
||||||
|
sheerka, context, parser = self.init_parser(my_map)
|
||||||
|
|
||||||
|
text = "foo baz"
|
||||||
|
res = parser.parse(context, ParserInput(text))
|
||||||
|
assert res.status
|
||||||
|
assert len(res.body.body) == 1
|
||||||
|
|
||||||
|
expected_concept = res.body.body[0].concept
|
||||||
|
assert sheerka.isinstance(expected_concept.get_compiled()["a"], "baz")
|
||||||
|
assert "b" not in expected_concept.get_compiled()
|
||||||
|
assert expected_concept.get_metadata().variables == [("a", "baz"), ("b", "'default_b'")]
|
||||||
|
|
||||||
|
text = "bar baz"
|
||||||
|
res = parser.parse(context, ParserInput(text))
|
||||||
|
assert res.status
|
||||||
|
assert len(res.body.body) == 1
|
||||||
|
expected_concept = res.body.body[0].concept
|
||||||
|
assert sheerka.isinstance(expected_concept.get_compiled()["b"], "baz")
|
||||||
|
assert "a" not in expected_concept.get_compiled()
|
||||||
|
assert expected_concept.get_metadata().variables == [("a", "'default_a'"), ("b", "baz")]
|
||||||
|
|
||||||
def test_i_can_parse_sequences(self):
|
def test_i_can_parse_sequences(self):
|
||||||
sheerka, context, parser = self.init_parser()
|
sheerka, context, parser = self.init_parser()
|
||||||
|
|
||||||
@@ -1335,6 +1362,19 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
|
|||||||
assert not res.status
|
assert not res.status
|
||||||
assert sheerka.isinstance(res.body, BuiltinConcepts.IS_EMPTY)
|
assert sheerka.isinstance(res.body, BuiltinConcepts.IS_EMPTY)
|
||||||
|
|
||||||
|
def test_i_cannot_parse_concept_when_variable_is_not_a_parameter(self):
|
||||||
|
my_map = {
|
||||||
|
"foo": Concept("foo").def_var("a") # 'a' is not a parameter (but a property like its color for ex)
|
||||||
|
}
|
||||||
|
sheerka, context, parser = self.init_parser(my_map)
|
||||||
|
|
||||||
|
text = "foo"
|
||||||
|
res = parser.parse(context, ParserInput(text))
|
||||||
|
|
||||||
|
assert not res.status
|
||||||
|
assert sheerka.isinstance(res.body, BuiltinConcepts.NOT_FOR_ME)
|
||||||
|
assert res.body.body == text
|
||||||
|
|
||||||
@pytest.mark.parametrize("expression, expected", [
|
@pytest.mark.parametrize("expression, expected", [
|
||||||
("function(", ([], "function(")),
|
("function(", ([], "function(")),
|
||||||
("before the function(", (["before the "], "function(")),
|
("before the function(", (["before the "], "function(")),
|
||||||
|
|||||||
Reference in New Issue
Block a user