Improved PythonEvaluator when dealing with concept class
This commit is contained in:
@@ -57,8 +57,8 @@ class PythonEvaluator(OneReturnValueEvaluator):
|
||||
|
||||
# Do not evaluate if the ast refers to a concept (leave it to ConceptEvaluator)
|
||||
if isinstance(node.ast_, ast.Expression) and isinstance(node.ast_.body, ast.Name):
|
||||
c = context.sheerka.get_by_key(node.ast_.body.id)
|
||||
if not context.sheerka.isinstance(c, BuiltinConcepts.UNKNOWN_CONCEPT):
|
||||
c = context.sheerka.resolve(node.ast_.body.id)
|
||||
if c is not None:
|
||||
context.log("It's a simple concept. Not for me.", self.name)
|
||||
not_for_me = context.sheerka.new(BuiltinConcepts.NOT_FOR_ME, body=node)
|
||||
return sheerka.ret(self.name, False, not_for_me, parents=[return_value])
|
||||
@@ -91,54 +91,11 @@ class PythonEvaluator(OneReturnValueEvaluator):
|
||||
"BuiltinConcepts": core.builtin_concepts.BuiltinConcepts,
|
||||
}
|
||||
|
||||
# has to tbe the first, to allow override
|
||||
method_from_sheerka = self.update_globals_with_sheerka_methods(my_locals, context)
|
||||
|
||||
if context.obj:
|
||||
context.log(f"Concept '{context.obj}' is in context. Adding it and its properties to locals.", self.name)
|
||||
|
||||
for prop_name in context.obj.variables():
|
||||
prop_value = context.obj.get_value(prop_name)
|
||||
if isinstance(prop_value, Concept):
|
||||
my_locals[prop_name] = context.sheerka.objvalue(prop_value)
|
||||
else:
|
||||
my_locals[prop_name] = prop_value
|
||||
|
||||
my_locals["self"] = context.obj.body
|
||||
|
||||
node_concept = core.ast.nodes.python_to_concept(node.ast_)
|
||||
unreferenced_names_visitor = UnreferencedNamesVisitor(context.sheerka)
|
||||
unreferenced_names_visitor.visit(node_concept)
|
||||
|
||||
for name in unreferenced_names_visitor.names:
|
||||
context.log(f"Resolving '{name}'.", self.name)
|
||||
|
||||
if name in node.concepts:
|
||||
context.log(f"Using value from node.", self.name)
|
||||
concept = node.concepts[name]
|
||||
return_concept = False
|
||||
|
||||
else:
|
||||
c_key, c_id, return_concept = self.resolve_name(name)
|
||||
|
||||
if c_key in my_locals:
|
||||
context.log(f"Using value from property.", self.name)
|
||||
continue
|
||||
|
||||
context.log(f"Instantiating new concept with {c_key=}, {c_id=}.", self.name)
|
||||
new = context.sheerka.new
|
||||
concept = new((None, c_id)) if c_id else new(c_key)
|
||||
if context.sheerka.isinstance(concept, BuiltinConcepts.UNKNOWN_CONCEPT):
|
||||
context.log(f"({c_key=}, {c_id=}) is not a concept. Skipping.", self.name)
|
||||
continue
|
||||
|
||||
context.log(f"Evaluating '{concept}'", self.name)
|
||||
with context.push(self.name, desc=f"Evaluating '{concept}'", obj=concept) as sub_context:
|
||||
sub_context.local_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||
evaluated = context.sheerka.evaluate_concept(sub_context, concept)
|
||||
sub_context.add_values(return_values=evaluated)
|
||||
|
||||
if evaluated.key == concept.key:
|
||||
my_locals[name] = evaluated if return_concept else context.sheerka.objvalue(evaluated)
|
||||
self.update_globals_with_context(my_locals, context)
|
||||
self.update_globals_with_node(my_locals, context, node)
|
||||
|
||||
if self.locals: # when exta values are given. Add them
|
||||
my_locals.update(self.locals)
|
||||
@@ -163,6 +120,77 @@ class PythonEvaluator(OneReturnValueEvaluator):
|
||||
|
||||
return methods_from_sheerka # to allow access using prefix "sheerka."
|
||||
|
||||
def update_globals_with_context(self, my_locals, context):
|
||||
if context.obj:
|
||||
context.log(f"Concept '{context.obj}' is in context. Adding it and its properties to locals.", self.name)
|
||||
|
||||
for prop_name in context.obj.variables():
|
||||
prop_value = context.obj.get_value(prop_name)
|
||||
if isinstance(prop_value, Concept):
|
||||
my_locals[prop_name] = context.sheerka.objvalue(prop_value)
|
||||
else:
|
||||
my_locals[prop_name] = prop_value
|
||||
|
||||
my_locals["self"] = context.obj.body
|
||||
|
||||
def update_globals_with_node(self, my_locals, context, node):
|
||||
node_concept = core.ast.nodes.python_to_concept(node.ast_)
|
||||
unreferenced_names_visitor = UnreferencedNamesVisitor(context.sheerka)
|
||||
unreferenced_names_visitor.visit(node_concept)
|
||||
|
||||
for name in unreferenced_names_visitor.names:
|
||||
context.log(f"Resolving '{name}'.", self.name)
|
||||
|
||||
if name in node.concepts:
|
||||
context.log(f"Using value from node.", self.name)
|
||||
concept = self.resolve_concept(context, node.concepts[name])
|
||||
|
||||
elif name in my_locals:
|
||||
context.log(f"Using value from property.", self.name)
|
||||
continue
|
||||
|
||||
else:
|
||||
context.log(f"Instantiating new concept with {name}.", self.name)
|
||||
concept = self.resolve_concept(context, name)
|
||||
|
||||
if concept is None:
|
||||
context.log(f"Concept '{name}' is not found or cannot be instantiated. Skipping.", self.name)
|
||||
continue
|
||||
|
||||
if concept.metadata.is_evaluated:
|
||||
context.log(f"Concept {name} is already evaluated.", self.name)
|
||||
|
||||
else:
|
||||
context.log(f"Evaluating '{concept}'", self.name)
|
||||
with context.push(self.name, desc=f"Evaluating '{concept}'", obj=concept) as sub_context:
|
||||
sub_context.local_hints.add(BuiltinConcepts.EVAL_BODY_REQUESTED)
|
||||
evaluated = context.sheerka.evaluate_concept(sub_context, concept)
|
||||
sub_context.add_values(return_values=evaluated)
|
||||
|
||||
if evaluated.key != concept.key:
|
||||
context.log(f"Error while evaluating '{name}'. Skipping.", self.name)
|
||||
continue
|
||||
concept = evaluated
|
||||
|
||||
my_locals[name] = context.sheerka.objvalue(concept)
|
||||
|
||||
@staticmethod
|
||||
def resolve_concept(context, concept_hint):
|
||||
if isinstance(concept_hint, Concept):
|
||||
return concept_hint
|
||||
|
||||
concept = context.sheerka.resolve(concept_hint)
|
||||
if concept is None:
|
||||
return None
|
||||
new_instance = context.sheerka.new_from_template(concept, concept.key)
|
||||
if isinstance(concept_hint, tuple):
|
||||
# It's means that it comes from PythonParser which have found a concept token (c:xxx:)
|
||||
# So a concept was explicitly required, not its value
|
||||
# We mark the concept as already evaluated, so it's body will not be evaluated
|
||||
new_instance.metadata.is_evaluated = True
|
||||
|
||||
return new_instance
|
||||
|
||||
@staticmethod
|
||||
def resolve_name(to_resolve):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user