from core.builtin_concepts import ParserResultConcept, ReturnValueConcept from core.concept import Concept from evaluators.BaseEvaluator import OneReturnValueEvaluator from parsers.DefaultParser import DefConceptNode import logging from parsers.PythonParser import PythonGetNamesVisitor, PythonNode log = logging.getLogger(__name__) class AddConceptEvaluator(OneReturnValueEvaluator): """ Used to add a new concept """ NAME = "AddNewConcept" def __init__(self): super().__init__(self.NAME, 50) def matches(self, context, return_value): return return_value.status and \ isinstance(return_value.value, ParserResultConcept) and \ isinstance(return_value.value.value, DefConceptNode) def eval(self, context, return_value): log.debug("Adding a new concept") def_concept_node = return_value.value.value sheerka = context.sheerka # validate the node props_found = set() concept = Concept(def_concept_node.name) for prop in ("where", "pre", "post", "body"): # put back the sources part_ret_val = getattr(def_concept_node, prop) if not isinstance(part_ret_val, ReturnValueConcept) or not part_ret_val.status: continue # not quite sure that it's possible # update the parts source = self.get_source(part_ret_val) setattr(concept, prop, source) # try to find what can be a property for p in self.get_props(part_ret_val): props_found.add(p) # Auto discovered properties must be referenced in the name # Note that with this method, the variables will be created in the order of appearance for token in def_concept_node.name.tokens: if token.value in props_found: concept.set_prop(token.value, None) # finish initialisation concept.init_key(def_concept_node.name.tokens) concept.add_codes(def_concept_node.get_codes()) ret = sheerka.create_new_concept(context, concept) return sheerka.ret(self.name, ret.status, ret.value, parents=[return_value]) @staticmethod def get_source(ret_value): return ret_value.value.source if isinstance(ret_value.value, ParserResultConcept) \ else ret_value.value.name @staticmethod def get_props(ret_value): if isinstance(ret_value.value, ParserResultConcept) and isinstance(ret_value.value.value, PythonNode): get_names_visitor = PythonGetNamesVisitor() get_names_visitor.visit(ret_value.value.value.ast_) return get_names_visitor.names if isinstance(ret_value.value, Concept): return list(ret_value.value.props.keys()) return []