Fixed #49 : working

This commit is contained in:
2021-03-18 11:49:48 +01:00
parent 27bc6c4ba1
commit 36515aebb7
5 changed files with 153 additions and 63 deletions
+81 -24
View File
@@ -6,7 +6,7 @@ from typing import Union, Set, List
from cache.Cache import Cache
from cache.ListIfNeededCache import ListIfNeededCache
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept
from core.builtin_helpers import is_a_question, ensure_evaluated, expect_one
from core.builtin_helpers import is_a_question, ensure_evaluated, expect_one, evaluate
from core.concept import Concept
from core.global_symbols import EVENT_RULE_PRECEDENCE_MODIFIED, RULE_COMPARISON_CONTEXT, NotFound, ErrorObj, \
EVENT_RULE_CREATED, EVENT_RULE_DELETED
@@ -14,7 +14,7 @@ from core.rule import Rule, ACTION_TYPE_PRINT
from core.sheerka.Sheerka import RECOGNIZED_BY_NAME, RECOGNIZED_BY_ID
from core.sheerka.services.sheerka_service import BaseService, FailedToCompileError
from core.tokenizer import Keywords, TokenKind, Token, IterParser
from core.utils import index_tokens, COLORS, get_text_from_tokens, unstr_concept
from core.utils import index_tokens, COLORS, get_text_from_tokens
from evaluators.ConceptEvaluator import ConceptEvaluator
from evaluators.PythonEvaluator import PythonEvaluator, Expando
from parsers.BaseExpressionParser import AndNode, ExpressionVisitor, VariableNode, ComparisonNode, FunctionNode
@@ -1134,22 +1134,34 @@ class ReteConditionExprVisitor(ExpressionVisitor):
self.variables[target] = var_name
return var_name
def init_or_get_variable_from_name(self, node, conditions):
def init_or_get_variable_from_name(self, node: VariableNode, conditions):
if node.attributes:
left = node.attributes[:-1]
right = [node.attributes[-1]]
while left:
var_name = node.name + "." + ".".join(left)
if var_name in self.variables:
return V(self.variables[var_name]), ".".join(right)
right.insert(0, left.pop())
if node.name not in self.variables:
var_name = self.add_variable(node.name)
conditions.append(Condition(V(var_name), "__name__", node.name))
return V(self.variables[node.name])
return V(self.variables[node.name]), node.attributes_str
def init_or_get_variable_from_attr(self, node, conditions):
def init_or_get_variable_from_attr(self, node: VariableNode, conditions):
path = f"{node.name}.{node.attributes_str}"
if path in self.variables:
return self.variables[path]
root = self.init_or_get_variable_from_name(node, conditions)
root, attr = self.init_or_get_variable_from_name(node, conditions)
var_name = self.add_variable(path)
variable = V(var_name)
conditions.append(Condition(root, node.attributes_str, variable))
conditions.append(Condition(root, attr, variable))
return variable
def get_conditions(self, expr_node):
@@ -1161,9 +1173,9 @@ class ReteConditionExprVisitor(ExpressionVisitor):
def visit_VariableNode(self, expr_node):
conditions = []
var_name = self.init_or_get_variable_from_name(expr_node, conditions)
var_name, attr = self.init_or_get_variable_from_name(expr_node, conditions)
if expr_node.attributes_str is not None:
conditions.append(Condition(var_name, expr_node.attributes_str, True))
conditions.append(Condition(var_name, attr, True))
return conditions
def visit_AndNode(self, expr_node: AndNode):
@@ -1176,29 +1188,74 @@ class ReteConditionExprVisitor(ExpressionVisitor):
def visit_ComparisonNode(self, expr_node: ComparisonNode):
if isinstance(expr_node.left, VariableNode):
conditions = []
left = self.init_or_get_variable_from_name(expr_node.left, conditions)
attr = expr_node.left.attributes_str or "__self__"
right = eval(get_text_from_tokens(expr_node.right.tokens))
conditions.append(Condition(left, attr, right))
left, attr = self.init_or_get_variable_from_name(expr_node.left, conditions)
res = evaluate(self.context,
expr_node.right.get_source(),
evaluators="all", # TODO: all is too much
desc=None,
eval_body=False,
eval_where=False,
is_question=False,
expect_success=False,
stm=None)
res = expect_one(self.context, res)
if not res.status:
return FailedToCompileError([f"Cannot recognize '{expr_node.right.get_source()}'"])
value = res.value
if (isinstance(value, Expando) and value.get_name() == "sheerka" or
isinstance(value, Concept) and value.id == self.context.sheerka.id):
conditions.append(Condition(left, attr, "__sheerka__"))
else:
conditions.append(Condition(left, attr, res.value))
return conditions
else:
raise FailedToCompileError([expr_node])
def visit_FunctionNode(self, expr_node: FunctionNode):
if expr_node.first.value == "recognize(":
return self.function_recognize(expr_node.parameters[0].value, expr_node.parameters[1].value)
return self.function_recognize_concept(expr_node.parameters[0].value,
expr_node.parameters[1].value,
[p.value for p in expr_node.parameters[2:]])
def function_recognize(self, source, target):
def function_recognize_concept(self, variable_path, concept_to_recognize, parameters):
"""
Creates Rete conditions to recognize a concept
:param variable_path: variable holding the information
:param concept_to_recognize: concept to recognize
:param parameters: concept variables values
:return:
"""
concept_as_str = concept_to_recognize.get_source()
if not concept_as_str:
return FailedToCompileError([f"Missing concept in for {variable_path}"])
res = evaluate(self.context,
concept_as_str,
evaluators="all", # TODO: all is too much
desc=None,
eval_body=False,
eval_where=False,
is_question=False,
expect_success=False,
stm=None)
res = expect_one(self.context, res)
if not res.status:
return FailedToCompileError([f"Unknown concept {concept_as_str}"])
concept_found = res.body
conditions = []
body_var = self.init_or_get_variable_from_attr(source, conditions)
conditions.append(Condition(body_var, "__is_concept__", True))
if isinstance(target, VariableNode):
conditions.append(Condition(body_var, "name", target.name))
variable = self.init_or_get_variable_from_attr(variable_path, conditions)
conditions.append(Condition(variable, "__is_concept__", True))
if concept_found.get_hint(BuiltinConcepts.RECOGNIZED_BY) == RECOGNIZED_BY_NAME:
conditions.append(Condition(variable, "name", concept_found.name))
elif concept_found.get_hint(BuiltinConcepts.RECOGNIZED_BY) == RECOGNIZED_BY_ID:
conditions.append(Condition(variable, "id", concept_found.id))
else:
concept_key, concept_id = unstr_concept(target.value)
if concept_id:
conditions.append(Condition(body_var, "id", concept_id))
elif concept_key:
conditions.append(Condition(body_var, "name", concept_key))
conditions.append(Condition(variable, "key", concept_found.key))
return conditions