First implementation of questions management
This commit is contained in:
@@ -1,14 +1,11 @@
|
||||
from core.ast.nodes import python_to_concept
|
||||
import core.utils
|
||||
from core.builtin_concepts import ParserResultConcept, ReturnValueConcept, BuiltinConcepts
|
||||
from core.builtin_helpers import get_names
|
||||
from core.concept import Concept, DEFINITION_TYPE_BNF, DEFINITION_TYPE_DEF
|
||||
from core.tokenizer import TokenKind, Tokenizer
|
||||
from evaluators.BaseEvaluator import OneReturnValueEvaluator
|
||||
from parsers.BaseParser import NotInitializedNode
|
||||
from parsers.BnfNodeParser import ParsingExpression, ParsingExpressionVisitor
|
||||
from parsers.DefaultParser import DefConceptNode, NameNode
|
||||
from parsers.PythonParser import PythonNode
|
||||
import core.utils
|
||||
|
||||
|
||||
class ConceptOrRuleNameVisitor(ParsingExpressionVisitor):
|
||||
@@ -132,30 +129,6 @@ class AddConceptEvaluator(OneReturnValueEvaluator):
|
||||
variables = filter(lambda x: x in concept_name, names)
|
||||
return set(variables)
|
||||
|
||||
#
|
||||
# Case of python code
|
||||
#
|
||||
if isinstance(ret_value.value, ParserResultConcept) and isinstance(ret_value.value.value, PythonNode):
|
||||
if len(concept_name) > 1:
|
||||
# tokens from ParserResult or source from python node
|
||||
variables = set()
|
||||
tokens = ret_value.value.tokens or list(Tokenizer(ret_value.value.value.source))
|
||||
tokens = [t.str_value for t in tokens]
|
||||
for identifier in [i for i in concept_name if str(i).isalnum()]:
|
||||
if identifier in tokens:
|
||||
variables.add(identifier)
|
||||
# python_node = ret_value.value.value
|
||||
# as_concept_node = python_to_concept(python_node.ast_)
|
||||
# names = get_names(sheerka, as_concept_node)
|
||||
# variables = filter(lambda x: x in concept_name, names)
|
||||
return variables
|
||||
|
||||
#
|
||||
# case of concept
|
||||
#
|
||||
if isinstance(ret_value.value, ParserResultConcept) and isinstance(ret_value.value.value, Concept):
|
||||
return set(ret_value.value.value.values.keys())
|
||||
|
||||
#
|
||||
# case of BNF
|
||||
#
|
||||
@@ -164,4 +137,16 @@ class AddConceptEvaluator(OneReturnValueEvaluator):
|
||||
visitor.visit(ret_value.value.value)
|
||||
return set(visitor.names)
|
||||
|
||||
#
|
||||
# other (python code and concept)
|
||||
#
|
||||
if isinstance(ret_value.value, ParserResultConcept) and len(concept_name) > 1:
|
||||
variables = set()
|
||||
tokens = ret_value.value.tokens or list(Tokenizer(ret_value.value.source, yield_eof=False))
|
||||
tokens = [t.str_value for t in tokens]
|
||||
for identifier in [i for i in concept_name if str(i).isalnum()]:
|
||||
if identifier in tokens:
|
||||
variables.add(identifier)
|
||||
return variables
|
||||
|
||||
return []
|
||||
|
||||
@@ -21,11 +21,11 @@ class ConceptEvaluator(OneReturnValueEvaluator):
|
||||
self.return_body = return_body
|
||||
|
||||
# def init_evaluator(self, context, return_values):
|
||||
# if BuiltinConcepts.EVAL_BODY_REQUESTED in context.local_hints:
|
||||
# if BuiltinConcepts.EVAL_BODY_REQUESTED in context.protected_hints:
|
||||
# self.evaluate_body = True
|
||||
#
|
||||
# for r in return_values:
|
||||
# if r.status and context.sheerka.isinstance(r.body, BuiltinConcepts.RETURN_VALUE_REQUESTED):
|
||||
# if r.status and context.sheerka.isinstance(r.body, BuiltinConcepts.RETURN_BODY_REQUESTED):
|
||||
# self.evaluate_body = True
|
||||
# break
|
||||
#
|
||||
|
||||
@@ -2,12 +2,12 @@ from core.builtin_concepts import BuiltinConcepts
|
||||
from evaluators.BaseEvaluator import OneReturnValueEvaluator
|
||||
|
||||
|
||||
class PrepareEvalEvaluator(OneReturnValueEvaluator):
|
||||
class PrepareEvalBodyEvaluator(OneReturnValueEvaluator):
|
||||
"""
|
||||
To parse evaluation requests
|
||||
To recognize when the user input is an (body) evaluation
|
||||
"""
|
||||
|
||||
NAME = "PrepareEval"
|
||||
NAME = "PrepareEvalBody"
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(self.NAME, [BuiltinConcepts.BEFORE_PARSING], 90)
|
||||
@@ -33,8 +33,10 @@ class PrepareEvalEvaluator(OneReturnValueEvaluator):
|
||||
self.name,
|
||||
True, sheerka.new(BuiltinConcepts.USER_INPUT, body=self.text[5:], user_name=context.event.user_id))
|
||||
|
||||
context.global_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||
context.global_hints.add(BuiltinConcepts.EVAL_WHERE_REQUESTED)
|
||||
context.global_hints.add(BuiltinConcepts.RETURN_VALUE_REQUESTED)
|
||||
root = context.get_parents(lambda ec: ec.action == BuiltinConcepts.PROCESS_INPUT)
|
||||
root = root[0] if root else context
|
||||
root.protected_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||
root.protected_hints.add(BuiltinConcepts.EVAL_WHERE_REQUESTED)
|
||||
root.protected_hints.add(BuiltinConcepts.RETURN_BODY_REQUESTED)
|
||||
|
||||
return new_text_to_parse
|
||||
@@ -0,0 +1,45 @@
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from evaluators.BaseEvaluator import OneReturnValueEvaluator
|
||||
|
||||
|
||||
class PrepareEvalQuestionEvaluator(OneReturnValueEvaluator):
|
||||
"""
|
||||
To recognize when the user input is a question
|
||||
"""
|
||||
|
||||
NAME = "PrepareEvalQuestion"
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(self.NAME, [BuiltinConcepts.BEFORE_PARSING], 90)
|
||||
self.question = 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("question(") and text.endswith(")")):
|
||||
return False
|
||||
|
||||
self.question = text[9:-1].strip()
|
||||
if self.question == "":
|
||||
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.question, user_name=context.event.user_id))
|
||||
|
||||
root = context.get_parents(lambda ec: ec.action == BuiltinConcepts.PROCESS_INPUT)
|
||||
root = root[0] if root else context
|
||||
root.protected_hints.add(BuiltinConcepts.EVAL_QUESTION_REQUESTED)
|
||||
root.protected_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||
root.protected_hints.add(BuiltinConcepts.RETURN_BODY_REQUESTED)
|
||||
|
||||
return new_text_to_parse
|
||||
@@ -12,6 +12,9 @@ from core.sheerka.services.SheerkaFilter import Pipe
|
||||
from evaluators.BaseEvaluator import OneReturnValueEvaluator
|
||||
from parsers.PythonParser import PythonNode
|
||||
|
||||
TO_DISABLED = ["breakpoint", "callable", "compile", "delattr", "eval", "exec", "exit", "input", "locals", "open",
|
||||
"print", "quit", "setattr"]
|
||||
|
||||
|
||||
def inject_context(context):
|
||||
"""
|
||||
@@ -95,7 +98,7 @@ class PythonEvaluator(OneReturnValueEvaluator):
|
||||
concepts_entries = None
|
||||
evaluated = BuiltinConcepts.NOT_INITIALIZED
|
||||
errors = []
|
||||
expect_success = BuiltinConcepts.EVAL_UNTIL_SUCCESS_REQUESTED in context.local_hints
|
||||
expect_success = context.in_context(BuiltinConcepts.EVAL_UNTIL_SUCCESS_REQUESTED)
|
||||
for globals_ in all_possible_globals:
|
||||
try:
|
||||
# eval
|
||||
@@ -142,12 +145,13 @@ class PythonEvaluator(OneReturnValueEvaluator):
|
||||
my_globals = {
|
||||
"Concept": core.concept.Concept,
|
||||
"BuiltinConcepts": core.builtin_concepts.BuiltinConcepts,
|
||||
"in_context": context.in_context
|
||||
"in_context": context.in_context,
|
||||
}
|
||||
|
||||
if expression_only:
|
||||
# disable builtin
|
||||
my_globals["__builtins__"] = None
|
||||
# disable some builtin
|
||||
for statement in TO_DISABLED:
|
||||
my_globals[statement] = None
|
||||
|
||||
# has to be the first, to allow override
|
||||
method_from_sheerka = self.update_globals_with_sheerka_methods(my_globals, context, expression_only)
|
||||
@@ -164,17 +168,6 @@ class PythonEvaluator(OneReturnValueEvaluator):
|
||||
|
||||
@staticmethod
|
||||
def update_globals_with_sheerka_methods(my_locals, context, expression_only):
|
||||
# methods_from_sheerka = {}
|
||||
#
|
||||
# # Make sure that methods that need the concept are correctly wrapped
|
||||
# for method_name, method in context.sheerka.sheerka_methods.items():
|
||||
# if expression_only and method.has_side_effect:
|
||||
# continue
|
||||
#
|
||||
# if method_name in context.sheerka.methods_with_context:
|
||||
# methods_from_sheerka[method_name] = inject_context(context)(method.method)
|
||||
# else:
|
||||
# methods_from_sheerka[method_name] = method.method
|
||||
methods_from_sheerka = {}
|
||||
|
||||
# Add all the methods as a direct access
|
||||
@@ -238,6 +231,8 @@ class PythonEvaluator(OneReturnValueEvaluator):
|
||||
elif name in already_known:
|
||||
context.log(f"Already known. Skipping.", self.name)
|
||||
continue
|
||||
elif (concept := context.get_from_short_term_memory(name)) is not None:
|
||||
context.log(f"Using from STM known.", self.name)
|
||||
else:
|
||||
context.log(f"Instantiating new concept with {name}.", self.name)
|
||||
concept = self.resolve_concept(context, name)
|
||||
|
||||
@@ -38,12 +38,13 @@ class ResolveAmbiguityEvaluator(AllReturnValuesEvaluator):
|
||||
parser_results = {id(r.body.body): r.body for r in ret_vals}
|
||||
resolved = resolve_ambiguity(context, [r.body.body for r in ret_vals])
|
||||
if len(resolved) == 0:
|
||||
ret.append(context.sheerka.ret(self.name, True, [], parents=ret_vals))
|
||||
ret.append(context.sheerka.ret(self.name, True, BuiltinConcepts.NO_RESULT, parents=ret_vals))
|
||||
else:
|
||||
for c in resolved:
|
||||
ret.append(context.sheerka.ret(self.name, True, parser_results[id(c)], parents=ret_vals))
|
||||
if len(resolved) < len(ret_vals):
|
||||
for c in resolved:
|
||||
ret.append(context.sheerka.ret(self.name, True, parser_results[id(c)], parents=ret_vals))
|
||||
|
||||
return ret
|
||||
return None if len(ret) == 0 else ret
|
||||
|
||||
@staticmethod
|
||||
def get_source(context, return_value):
|
||||
|
||||
@@ -3,12 +3,12 @@ from core.concept import Concept
|
||||
from evaluators.BaseEvaluator import AllReturnValuesEvaluator
|
||||
|
||||
|
||||
class EvalEvaluator(AllReturnValuesEvaluator):
|
||||
class ReturnBodyEvaluator(AllReturnValuesEvaluator):
|
||||
"""
|
||||
Returns the body of all successful concepts
|
||||
"""
|
||||
|
||||
NAME = "Eval"
|
||||
NAME = "ReturnBody"
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(self.NAME, [BuiltinConcepts.AFTER_EVALUATION], 80)
|
||||
@@ -16,7 +16,7 @@ class EvalEvaluator(AllReturnValuesEvaluator):
|
||||
def matches(self, context, return_values):
|
||||
evaluation_parents = context.get_parents(lambda c: c.action == BuiltinConcepts.PROCESSING)
|
||||
is_root = len(evaluation_parents) <= 1
|
||||
return context.in_context(BuiltinConcepts.RETURN_VALUE_REQUESTED) and is_root
|
||||
return context.in_context(BuiltinConcepts.RETURN_BODY_REQUESTED) and is_root
|
||||
|
||||
def eval(self, context, return_values):
|
||||
sheerka = context.sheerka
|
||||
@@ -26,6 +26,7 @@ class UpdateFunctionsParametersEvaluator(OneReturnValueEvaluator):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(self.NAME, [BuiltinConcepts.AFTER_EVALUATION], 79)
|
||||
self.enabled = False
|
||||
|
||||
def matches(self, context, return_value):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user