Files
Sheerka-Old/evaluators/AddConceptEvaluator.py
T

78 lines
2.8 KiB
Python

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 []