Files
smnp-py/smnp/runtime/evaluator.py
2019-07-12 18:59:59 +02:00

83 lines
2.5 KiB
Python

from smnp.ast.node.program import Program
from smnp.error.runtime import RuntimeException
from smnp.type.model import Type
class Evaluator:
@classmethod
def evaluator(cls, node, environment):
pass
@classmethod
def evaluate(cls, node, environment):
result = cls.evaluator(node, environment)
if result is None:
return EvaluationResult.OK(Type.void())
return EvaluationResult.OK(result)
@staticmethod
def forNodes(evaluator, *nodes):
def nodeEvaluator(node, environment):
if type(node) in nodes:
return evaluator(node, environment)
return EvaluationResult.FAIL()
return nodeEvaluator
@staticmethod
def oneOf(*evaluators):
def combinedEvaluator(node, environment):
for evaluator in evaluators:
result = evaluator(node, environment)
if result.result:
return result
return EvaluationResult.FAIL()
return combinedEvaluator
class EvaluationResult():
def __init__(self, result, value):
if result and value is None:
raise RuntimeError("Value musn't be None if result is set to True for EvaluationResult")
if type(value) == EvaluationResult:
raise RuntimeError(f"Nested EvaluationResult detected. Trying to create EvaluationResult with value = {value}")
self.result = result
self.value = value
@staticmethod
def FAIL():
return EvaluationResult(False, None)
@staticmethod
def OK(value):
return EvaluationResult(True, value)
def __str__(self):
return f"{'OK' if self.result else 'FAILED'}[{self.value}]"
def evaluate(node, environment):
from smnp.runtime.evaluators.program import ProgramEvaluator
from smnp.runtime.evaluators.expression import expressionEvaluator
result = Evaluator.oneOf(
Evaluator.forNodes(ProgramEvaluator.evaluate, Program),
#Evaluator.forNodes(ImportEvaluator.evaluate, ImportNode),
#Evaluator.forNodes(FunctionDefinitionEvaluator.evaluate, FunctionDefinitionNode),
#Evaluator.forNodes(ExtendEvaluator.evaluate, ExtendNode),
#Evaluator.forNodes(BlockEvaluator.evaluate, BlockNode),
#Evaluator.forNodes(ReturnEvaluator.evaluate, ReturnNode),
expressionEvaluator()
)(node, environment)
if not result.result:
raise RuntimeException("Cannot evaluate program", node.pos)
return result