Files
smnp-py/smnp/runtime/evaluators/asterisk.py
2019-07-08 19:33:14 +02:00

123 lines
5.3 KiB
Python

from smnp.ast.node.identifier import IdentifierNode
from smnp.runtime.evaluator import evaluate, Evaluator, EvaluationResult
from smnp.runtime.evaluators.expression import expressionEvaluator
from smnp.type.model import Type
from smnp.type.value import Value
class AsteriskEvaluator(Evaluator):
@classmethod
def evaluator(cls, node, environment):
iterator = expressionEvaluator(doAssert=True)(node.iterator, environment).value #TODO check if it isn't necessary to verify 'result' attr of EvaluatioNResult
return Evaluator.oneOf(
cls._numberIteratorAsteriskEvaluator(iterator),
cls._listIteratorAsteriskEvaluator(iterator)
)(node, environment).value #TODO check if it isn't necessary to verify 'result' attr of EvaluatioNResult
@classmethod
def _numberIteratorAsteriskEvaluator(cls, evaluatedIterator):
def evaluator(node, environment):
if evaluatedIterator.type == Type.INTEGER:
results = []
automaticVariable = cls._automaticNamedVariable(node.iterator, environment, "_")
for i in range(evaluatedIterator.value):
environment.scopes[-1][automaticVariable] = Value(Type.INTEGER, i + 1)
result = evaluate(node.statement, environment).value #TODO check if it isn't necessary to verify 'result' attr of EvaluatioNResult
if result is not None and result.type != Type.VOID:
results.append(result)
del environment.scopes[-1][automaticVariable]
return EvaluationResult.OK(Value(Type.LIST, results).decompose())
return EvaluationResult.FAIL()
return evaluator
@classmethod
def _automaticNamedVariable(cls, iteratorNode, environment, prefix=''):
if type(iteratorNode) == IdentifierNode:
return cls._automaticVariableName(environment, prefix, iteratorNode.value, False)
else:
return cls._automaticVariableName(environment, prefix, '', True)
@classmethod
def _automaticVariableName(cls, environment, prefix='', suffix='', startWithNumber=False):
number = 1 if startWithNumber else ''
variableName = lambda x: f"{prefix}{x}{suffix}"
while environment.findVariableScope(variableName(number)) is not None:
if number == '':
number = 1
else:
number += 1
return variableName(number)
@classmethod
def _listIteratorAsteriskEvaluator(cls, evaluatedIterator):
def evaluator(node, environment):
if evaluatedIterator.type == Type.LIST:
results = []
automaticVariableKey = cls._automaticNamedVariable(node.iterator, environment, "_")
automaticVariableValue = cls._automaticNamedVariable(node.iterator, environment, "__")
for i, v in enumerate(evaluatedIterator.value):
environment.scopes[-1][automaticVariableKey] = Value(Type.INTEGER, i + 1)
environment.scopes[-1][automaticVariableValue] = v
result = evaluate(node.statement, environment).value # TODO check if it isn't necessary to verify 'result' attr of EvaluatioNResult
if result is not None and result.type != Type.VOID:
results.append(result)
del environment.scopes[-1][automaticVariableKey]
del environment.scopes[-1][automaticVariableValue]
return EvaluationResult.OK(Value(Type.LIST, results).decompose())
return EvaluationResult.FAIL()
return evaluator
#
# def evaluateAsterisk(asterisk, environment):
# iterator = evaluate(asterisk.iterator, environment)
# if iterator.type == Type.INTEGER:
# evaluateAsteriskForNumber(asterisk, environment, iterator)
#
# if iterator.type == Type.LIST:
# evaluateAsteriskForList(asterisk, environment, iterator)
#
#
#
# def evaluateAsteriskForNumber(asterisk, environment, count):
# for i in range(count.value):
# if type(asterisk.iterator) == IdentifierNode:
# environment.scopes[-1][f"_{asterisk.iterator.identifier}"] = Value(Type.INTEGER, i+1)
# else:
# environment.scopes[-1]["_"] = Value(Type.INTEGER, i+1)
#
# evaluate(asterisk.statement, environment)
#
# if type(asterisk.iterator) == IdentifierNode:
# del environment.scopes[-1][f"_{asterisk.iterator.identifier}"]
# else:
# del environment.scopes[-1]["_"]
#
#
# def evaluateAsteriskForList(asterisk, environment, list):
# for i, v in enumerate(list.value):
# if type(asterisk.iterator) == IdentifierNode:
# environment.scopes[-1][f"_{asterisk.iterator.identifier}"] = Value(Type.INTEGER, i+1)
# environment.scopes[-1][f"{asterisk.iterator.identifier}_"] = v
# else:
# environment.scopes[-1]["_"] = Value(Type.INTEGER, i+1)
# environment.scopes[-1]["__"] = v
#
# evaluate(asterisk.statement, environment)
#
# if type(asterisk.iterator) == IdentifierNode:
# del environment.scopes[-1][f"_{asterisk.iterator.identifier}"]
# del environment.scopes[-1][f"{asterisk.iterator.identifier}_"]
# else:
# del environment.scopes[-1]["_"]
# del environment.scopes[-1]["__"]