Enable evaluating asterisk

This commit is contained in:
Bartłomiej Pluta
2019-07-08 19:33:14 +02:00
parent 63c020fbb9
commit 21cbf2bcbd
6 changed files with 120 additions and 35 deletions

View File

@@ -1,48 +1,122 @@
from smnp.ast.node.identifier import IdentifierNode
from smnp.runtime.evaluator import evaluate
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
def evaluateAsterisk(asterisk, environment):
iterator = evaluate(asterisk.iterator, environment)
if iterator.type == Type.INTEGER:
evaluateAsteriskForNumber(asterisk, environment, iterator)
class AsteriskEvaluator(Evaluator):
if iterator.type == Type.LIST:
evaluateAsteriskForList(asterisk, environment, iterator)
@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]
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)
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:
environment.scopes[-1]["_"] = Value(Type.INTEGER, i+1)
return cls._automaticVariableName(environment, prefix, '', True)
evaluate(asterisk.statement, environment)
@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
if type(asterisk.iterator) == IdentifierNode:
del environment.scopes[-1][f"_{asterisk.iterator.identifier}"]
else:
del environment.scopes[-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)
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
del environment.scopes[-1][automaticVariableKey]
del environment.scopes[-1][automaticVariableValue]
evaluate(asterisk.statement, environment)
return EvaluationResult.OK(Value(Type.LIST, results).decompose())
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]["__"]
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]["__"]