Fixed #18 : Parsing and evaluating Python
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
from core.BuiltinConcepts import BuiltinConcepts
|
||||
from core.ErrorContext import ErrorContext
|
||||
from core.ExecutionContext import ExecutionContext, ExecutionContextActions
|
||||
from core.error import ErrorContext
|
||||
from core.ExecutionContext import ExecutionContext, ContextActions
|
||||
from core.ReturnValue import ReturnValue
|
||||
from evaluators.base_evaluator import EvaluatorEvalResult, EvaluatorMatchResult, OneReturnValueEvaluator
|
||||
from parsers.ParserInput import ParserInput
|
||||
@@ -10,7 +10,7 @@ class CreateParserInput(OneReturnValueEvaluator):
|
||||
NAME = "CreateParserInput"
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(self.NAME, ExecutionContextActions.BEFORE_EVALUATION, 50)
|
||||
super().__init__(self.NAME, ContextActions.BEFORE_PARSING, 50)
|
||||
|
||||
def matches(self, context: ExecutionContext, return_value: ReturnValue) -> EvaluatorMatchResult:
|
||||
if return_value.status and \
|
||||
@@ -26,5 +26,5 @@ class CreateParserInput(OneReturnValueEvaluator):
|
||||
return EvaluatorEvalResult([new_ret_val], [return_value])
|
||||
else:
|
||||
error = ErrorContext(self.NAME, context, parser_input)
|
||||
new_ret_val = ReturnValue(self.NAME, False, error, parents=[return_value])
|
||||
return EvaluatorEvalResult([new_ret_val], [return_value])
|
||||
error_ret_val = ReturnValue(self.NAME, False, error, parents=[return_value])
|
||||
return EvaluatorEvalResult([error_ret_val], [return_value])
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
from core.BuiltinConcepts import BuiltinConcepts
|
||||
from core.ExecutionContext import ExecutionContext, ContextActions
|
||||
from core.ReturnValue import ReturnValue
|
||||
from core.error import ErrorContext
|
||||
from evaluators.base_evaluator import EvaluatorEvalResult, EvaluatorMatchResult, OneReturnValueEvaluator
|
||||
|
||||
|
||||
class PythonEvaluator(OneReturnValueEvaluator):
|
||||
NAME = "PythonEvaluator"
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(self.NAME, ContextActions.EVALUATION, 50)
|
||||
|
||||
def matches(self, context: ExecutionContext, return_value: ReturnValue) -> EvaluatorMatchResult:
|
||||
return EvaluatorMatchResult(return_value.status and
|
||||
context.sheerka.isinstance(return_value.value, BuiltinConcepts.PYTHON_CODE))
|
||||
|
||||
def eval(self, context: ExecutionContext,
|
||||
evaluation_context: object,
|
||||
return_value: ReturnValue) -> EvaluatorEvalResult:
|
||||
|
||||
sheerka = context.sheerka
|
||||
fragment = return_value.value.pf
|
||||
|
||||
evaluated = sheerka.evaluate_python(context, fragment)
|
||||
if isinstance(evaluated, ErrorContext):
|
||||
return EvaluatorEvalResult([ReturnValue(self.name, False, evaluated, parents=[return_value])],
|
||||
[])
|
||||
else:
|
||||
return EvaluatorEvalResult([ReturnValue(self.name, True, evaluated, parents=[return_value])],
|
||||
[return_value])
|
||||
@@ -0,0 +1,69 @@
|
||||
import ast
|
||||
from dataclasses import dataclass
|
||||
|
||||
from common.utils import encode_concept
|
||||
from core.BuiltinConcepts import BuiltinConcepts
|
||||
from core.ExecutionContext import ExecutionContext, ContextActions
|
||||
from core.ReturnValue import ReturnValue
|
||||
from core.error import ErrorContext, ErrorObj
|
||||
from core.python_fragment import PythonFragment
|
||||
from evaluators.base_evaluator import EvaluatorEvalResult, EvaluatorMatchResult, OneReturnValueEvaluator
|
||||
from parsers.tokenizer import TokenKind
|
||||
|
||||
|
||||
@dataclass()
|
||||
class PythonErrorNode(ErrorObj):
|
||||
source: str
|
||||
exception: Exception
|
||||
|
||||
def get_error_msg(self) -> str:
|
||||
return repr(self.exception)
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, PythonErrorNode):
|
||||
return False
|
||||
|
||||
return self.source == other.source and self.exception == other.exception
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.source, self.exception))
|
||||
|
||||
|
||||
class PythonParser(OneReturnValueEvaluator):
|
||||
NAME = "PythonParser"
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(self.NAME, ContextActions.PARSING, 80)
|
||||
|
||||
def matches(self, context: ExecutionContext, return_value: ReturnValue) -> EvaluatorMatchResult:
|
||||
return EvaluatorMatchResult(return_value.status and
|
||||
context.sheerka.isinstance(return_value.value, BuiltinConcepts.PARSER_INPUT))
|
||||
|
||||
def eval(self, context: ExecutionContext,
|
||||
evaluation_context: object,
|
||||
return_value: ReturnValue) -> EvaluatorEvalResult:
|
||||
parser_input = return_value.value.body
|
||||
|
||||
tracker = {} # to keep track of concept tokens (c:xxx:)
|
||||
python_switcher = {TokenKind.CONCEPT: lambda t: encode_concept(t.value),
|
||||
TokenKind.RULE: lambda t: encode_concept(t.value, "R")}
|
||||
source_code = parser_input.as_text(python_switcher, tracker).lstrip() # right side spaces must be kept
|
||||
|
||||
try:
|
||||
ast_tree = ast.parse(source_code, f"<user input>", 'eval')
|
||||
except:
|
||||
try:
|
||||
ast_tree = ast.parse(source_code, f"<user input>", 'exec')
|
||||
except Exception as error:
|
||||
error_context = ErrorContext(self.NAME, context, PythonErrorNode(parser_input.as_text(), error))
|
||||
error_ret_val = ReturnValue(self.NAME, False, error_context, [return_value])
|
||||
return EvaluatorEvalResult([error_ret_val], [])
|
||||
|
||||
# Successfully parsed some python code
|
||||
python_code = context.sheerka.newn(BuiltinConcepts.PYTHON_CODE,
|
||||
pf=PythonFragment(source_code,
|
||||
ast_tree,
|
||||
parser_input.original_text,
|
||||
tracker))
|
||||
new = ReturnValue(self.NAME, True, python_code, parents=[return_value])
|
||||
return EvaluatorEvalResult([new], [return_value])
|
||||
@@ -1,6 +1,6 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
from core.ExecutionContext import ExecutionContext, ExecutionContextActions
|
||||
from core.ExecutionContext import ExecutionContext, ContextActions
|
||||
from core.ReturnValue import ReturnValue
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ class BaseEvaluator:
|
||||
Base class to evaluate ReturnValues
|
||||
"""
|
||||
|
||||
def __init__(self, name, step: ExecutionContextActions, priority: int, enabled=True):
|
||||
def __init__(self, name, step: ContextActions, priority: int, enabled=True):
|
||||
self.name = name
|
||||
self.step = step
|
||||
self.priority = priority
|
||||
|
||||
Reference in New Issue
Block a user