Files
smnp-py/smnp/runtime/evaluator.py
Bartłomiej Pluta 41f385de09 Fix return statement
2019-07-12 22:25:26 +02:00

98 lines
3.3 KiB
Python

from smnp.ast.node.block import Block
from smnp.ast.node.condition import IfElse
from smnp.ast.node.function import FunctionDefinition
from smnp.ast.node.imports import Import
from smnp.ast.node.program import Program
from smnp.ast.node.ret import Return
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
from smnp.runtime.evaluators.condition import IfElseStatementEvaluator
from smnp.runtime.evaluators.block import BlockEvaluator
from smnp.runtime.evaluators.imports import ImportEvaluator
from smnp.runtime.evaluators.function import FunctionDefinitionEvaluator
from smnp.runtime.evaluators.function import ReturnEvaluator
result = Evaluator.oneOf(
Evaluator.forNodes(ProgramEvaluator.evaluate, Program),
Evaluator.forNodes(IfElseStatementEvaluator.evaluate, IfElse),
Evaluator.forNodes(BlockEvaluator.evaluate, Block),
Evaluator.forNodes(ImportEvaluator.evaluate, Import),
Evaluator.forNodes(FunctionDefinitionEvaluator.evaluate, FunctionDefinition),
Evaluator.forNodes(ReturnEvaluator.evaluate, Return),
#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