Enable evaluating asterisk
This commit is contained in:
@@ -122,7 +122,7 @@ class Environment():
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return self.scopesToString() + self.functionsToString() + self.methodsToString() + self.customFunctionsToString() + self.customMethodsToString()
|
||||
return f"{self.scopesToString()}\n{self.functionsToString()}\n{self.methodsToString()}\n{self.customFunctionsToString()}\n{self.customMethodsToString()}"
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
@@ -16,7 +16,7 @@ def main():
|
||||
|
||||
ast = parse(tokens)
|
||||
|
||||
#ast.print()
|
||||
ast.print()
|
||||
|
||||
env = createEnvironment()
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from smnp.error.runtime import RuntimeException
|
||||
from smnp.runtime.evaluator import Evaluator
|
||||
from smnp.runtime.evaluators.expression import expressionEvaluator
|
||||
|
||||
@@ -7,6 +8,9 @@ class AssignmentEvaluator(Evaluator):
|
||||
@classmethod
|
||||
def evaluator(cls, node, environment):
|
||||
target = node.target.value
|
||||
if target.startswith("_"):
|
||||
raise RuntimeException("Usage of variables with names starting with '_' is not allowed", node.target.pos)
|
||||
|
||||
value = expressionEvaluator(doAssert=True)(node.value, environment).value #TODO check if it isn't necessary to verify 'result' attr of EvaluatioNResult
|
||||
scopeOfExistingVariable = environment.findVariableScope(target)
|
||||
if scopeOfExistingVariable is None:
|
||||
|
||||
@@ -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)
|
||||
|
||||
if type(asterisk.iterator) == IdentifierNode:
|
||||
del environment.scopes[-1][f"_{asterisk.iterator.identifier}"]
|
||||
@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:
|
||||
del environment.scopes[-1]["_"]
|
||||
number += 1
|
||||
|
||||
return variableName(number)
|
||||
|
||||
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
|
||||
@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)
|
||||
|
||||
evaluate(asterisk.statement, environment)
|
||||
del environment.scopes[-1][automaticVariableKey]
|
||||
del environment.scopes[-1][automaticVariableValue]
|
||||
|
||||
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.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]["__"]
|
||||
|
||||
@@ -5,9 +5,13 @@ class BlockEvaluator(Evaluator):
|
||||
|
||||
@classmethod
|
||||
def evaluator(cls, node, environment):
|
||||
environment.scopes.append({})
|
||||
|
||||
for child in node.children:
|
||||
evaluate(child, environment)
|
||||
|
||||
environment.scopes.pop(-1)
|
||||
|
||||
#
|
||||
# def evaluateBlock(block, environment):
|
||||
# environment.scopes.append({})
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from smnp.ast.node.access import AccessNode
|
||||
from smnp.ast.node.assignment import AssignmentNode
|
||||
from smnp.ast.node.asterisk import AsteriskNode
|
||||
from smnp.ast.node.identifier import IdentifierNode
|
||||
from smnp.ast.node.integer import IntegerLiteralNode
|
||||
from smnp.ast.node.invocation import FunctionCallNode
|
||||
@@ -22,6 +23,7 @@ def expressionEvaluator(doAssert=False):
|
||||
|
||||
from smnp.runtime.evaluators.access import AccessEvaluator
|
||||
from smnp.runtime.evaluators.assignment import AssignmentEvaluator
|
||||
from smnp.runtime.evaluators.asterisk import AsteriskEvaluator
|
||||
result = Evaluator.oneOf(
|
||||
Evaluator.forNodes(FunctionCallEvaluator.evaluate, FunctionCallNode),
|
||||
Evaluator.forNodes(StringEvaluator.evaluate, StringLiteralNode),
|
||||
@@ -30,7 +32,8 @@ def expressionEvaluator(doAssert=False):
|
||||
Evaluator.forNodes(IdentifierEvaluator.evaluate, IdentifierNode),
|
||||
Evaluator.forNodes(ListEvaluator.evaluate, ListNode),
|
||||
Evaluator.forNodes(AccessEvaluator.evaluate, AccessNode),
|
||||
Evaluator.forNodes(AssignmentEvaluator.evaluate, AssignmentNode)
|
||||
Evaluator.forNodes(AssignmentEvaluator.evaluate, AssignmentNode),
|
||||
Evaluator.forNodes(AsteriskEvaluator.evaluate, AsteriskNode)
|
||||
)(node, environment)
|
||||
|
||||
if doAssert and result.result and result.value.type == Type.VOID:
|
||||
|
||||
Reference in New Issue
Block a user