Managing concept properties in ConceptEvaluator

This commit is contained in:
2019-11-16 18:11:29 +01:00
parent 3a1dea19e8
commit 7fa509555d
13 changed files with 808 additions and 57 deletions
+30 -8
View File
@@ -1,4 +1,4 @@
from core.builtin_concepts import ParserResultConcept
from core.builtin_concepts import ParserResultConcept, BuiltinConcepts
from core.concept import Concept, ConceptParts
from evaluators.BaseEvaluator import OneReturnValueEvaluator
import logging
@@ -9,6 +9,8 @@ log = logging.getLogger(__name__)
class ConceptEvaluator(OneReturnValueEvaluator):
evaluation_steps = [BuiltinConcepts.EVALUATION, BuiltinConcepts.AFTER_EVALUATION]
def __init__(self):
super().__init__("Concept Evaluator", 50)
@@ -31,12 +33,32 @@ class ConceptEvaluator(OneReturnValueEvaluator):
# TODO; check pre
# if pre is not true, return Concept with a false value
if ConceptParts.BODY in concept.codes:
body = concept.codes[ConceptParts.BODY]
if body is None:
return None # nothing to do
# Evaluate the properties
for prop in concept.props:
sub_context = context.push(self.name, f"Evaluating property '{prop}'", concept)
res = self.evaluate_parsing(sheerka, sub_context, concept.codes[prop])
if res.status:
concept.set_prop(prop, res.value)
else:
return sheerka.ret(
self.name,
False,
sheerka.new(BuiltinConcepts.PROPERTY_EVAL_ERROR, body=prop, concept=concept, error=res.value),
parents=[return_value])
return sheerka.ret(self.name, True, body.value, parents=[return_value])
else:
# Evaluate body
if ConceptParts.BODY not in concept.codes:
return sheerka.ret(self.name, True, concept, parents=[return_value])
body = concept.codes[ConceptParts.BODY]
if body is None:
return None # seems weird
sub_context = context.push(self.name, "Evaluating body", concept)
res = self.evaluate_parsing(sheerka, sub_context, body)
return sheerka.ret(self.name, res.status, res.value, parents=[return_value])
def evaluate_parsing(self, sheerka, context, parsing_result):
res = sheerka.chain_process(context, parsing_result, self.evaluation_steps)
res = sheerka.expect_one(context, res)
return res
+1 -1
View File
@@ -19,7 +19,7 @@ class DuplicateConceptEvaluator(AllReturnValuesEvaluator):
only_parsers = True
for ret in return_values:
if sheerka.isinstance(ret.value, BuiltinConcepts.PARSING):
if sheerka.isinstance(ret.value, BuiltinConcepts.AFTER_EVALUATION):
if ret.status:
parsing = True
elif ret.who == "Evaluators:Add new Concept":
+62
View File
@@ -0,0 +1,62 @@
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept
from evaluators.BaseEvaluator import AllReturnValuesEvaluator, BaseEvaluator
import logging
from parsers.BaseParser import BaseParser
log = logging.getLogger(__name__)
class MultipleSameSuccessEvaluator(AllReturnValuesEvaluator):
"""
Used to filter the responses
It has a low priority to let other evaluators try to resolve the errors
"""
def __init__(self):
super().__init__("Parsers Evaluator", 10)
self.success = []
def matches(self, context, return_values):
sheerka = context.sheerka
after_evaluation = False
nb_successful_evaluators = 0
only_parsers_in_error = True
unlisted = False
for ret in return_values:
if sheerka.isinstance(ret.value, BuiltinConcepts.AFTER_EVALUATION):
if ret.status:
after_evaluation = True
elif ret.who.startswith(BaseEvaluator.PREFIX):
if ret.status:
nb_successful_evaluators += 1
self.success.append(ret.value)
elif ret.who.startswith(BaseParser.PREFIX):
if ret.status:
only_parsers_in_error = False
else:
unlisted = True
return after_evaluation and nb_successful_evaluators > 1 and only_parsers_in_error and not unlisted
def eval(self, context, return_values):
reference = self.get_value(self.success[0])
for return_value in self.success[1:]:
actual = self.get_value(return_value)
if actual != reference:
return None
sheerka = context.sheerka
return sheerka.ret(self.name, True, reference, parents=return_values)
@staticmethod
def get_value(obj):
if not isinstance(obj, Concept):
return obj
return obj if obj.body is None else obj.body
@@ -1,5 +1,4 @@
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept
from evaluators.BaseEvaluator import AllReturnValuesEvaluator
import logging
@@ -8,7 +7,7 @@ from parsers.BaseParser import BaseParser
log = logging.getLogger(__name__)
class ParsersEvaluator(AllReturnValuesEvaluator):
class OneSuccessEvaluator(AllReturnValuesEvaluator):
"""
Used to filter the responses
It has a low priority to let other evaluators try to resolve the errors
@@ -20,13 +19,13 @@ class ParsersEvaluator(AllReturnValuesEvaluator):
def matches(self, context, return_values):
sheerka = context.sheerka
after_parsing = False
after_evaluation = False
nb_successful_evaluators = 0
only_parsers = True
for ret in return_values:
if sheerka.isinstance(ret.value, BuiltinConcepts.AFTER_PARSING):
if sheerka.isinstance(ret.value, BuiltinConcepts.AFTER_EVALUATION):
if ret.status:
after_parsing = True
after_evaluation = True
elif ret.who.startswith(self.PREFIX):
if ret.status:
nb_successful_evaluators += 1
@@ -35,7 +34,7 @@ class ParsersEvaluator(AllReturnValuesEvaluator):
if not ret.who.startswith(BaseParser.PREFIX):
only_parsers = False
return after_parsing and nb_successful_evaluators == 1 and only_parsers
return after_evaluation and nb_successful_evaluators == 1 and only_parsers
def eval(self, context, return_values):
sheerka = context.sheerka
+11 -3
View File
@@ -13,8 +13,8 @@ class PythonEvaluator(OneReturnValueEvaluator):
def matches(self, context, return_value):
return return_value.status and \
isinstance(return_value.value, ParserResultConcept) and \
isinstance(return_value.value.value, PythonNode)
isinstance(return_value.value, ParserResultConcept) and \
isinstance(return_value.value.value, PythonNode)
def eval(self, context, return_value):
sheerka = context.sheerka
@@ -23,10 +23,18 @@ class PythonEvaluator(OneReturnValueEvaluator):
try:
log.debug(f"Evaluating python node {node}")
compiled = compile(node.ast_, "<string>", "eval")
evaluated = eval(compiled, {}, {"sheerka": context.sheerka})
evaluated = eval(compiled, {}, self.get_locals(context))
return sheerka.ret(self.name, True, evaluated, parents=[return_value])
except Exception as error:
error = sheerka.new(BuiltinConcepts.ERROR, body=error)
return sheerka.ret(self.name, False, error, parents=[return_value])
else:
return sheerka.ret(self.name, False, sheerka.new(BuiltinConcepts.ERROR), parents=[return_value])
@staticmethod
def get_locals(context):
my_locals = {"sheerka": context.sheerka}
if context.obj:
for prop_name, prop_value in context.obj.props.items():
my_locals[prop_name] = prop_value.value
return my_locals