Enable evaluating asterisk
This commit is contained in:
@@ -122,7 +122,7 @@ class Environment():
|
|||||||
|
|
||||||
|
|
||||||
def __str__(self):
|
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):
|
def __repr__(self):
|
||||||
return self.__str__()
|
return self.__str__()
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ def main():
|
|||||||
|
|
||||||
ast = parse(tokens)
|
ast = parse(tokens)
|
||||||
|
|
||||||
#ast.print()
|
ast.print()
|
||||||
|
|
||||||
env = createEnvironment()
|
env = createEnvironment()
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
from smnp.error.runtime import RuntimeException
|
||||||
from smnp.runtime.evaluator import Evaluator
|
from smnp.runtime.evaluator import Evaluator
|
||||||
from smnp.runtime.evaluators.expression import expressionEvaluator
|
from smnp.runtime.evaluators.expression import expressionEvaluator
|
||||||
|
|
||||||
@@ -7,6 +8,9 @@ class AssignmentEvaluator(Evaluator):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def evaluator(cls, node, environment):
|
def evaluator(cls, node, environment):
|
||||||
target = node.target.value
|
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
|
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)
|
scopeOfExistingVariable = environment.findVariableScope(target)
|
||||||
if scopeOfExistingVariable is None:
|
if scopeOfExistingVariable is None:
|
||||||
|
|||||||
@@ -1,48 +1,122 @@
|
|||||||
from smnp.ast.node.identifier import IdentifierNode
|
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.model import Type
|
||||||
from smnp.type.value import Value
|
from smnp.type.value import Value
|
||||||
|
|
||||||
|
|
||||||
def evaluateAsterisk(asterisk, environment):
|
class AsteriskEvaluator(Evaluator):
|
||||||
iterator = evaluate(asterisk.iterator, environment)
|
|
||||||
if iterator.type == Type.INTEGER:
|
|
||||||
evaluateAsteriskForNumber(asterisk, environment, iterator)
|
|
||||||
|
|
||||||
if iterator.type == Type.LIST:
|
@classmethod
|
||||||
evaluateAsteriskForList(asterisk, environment, iterator)
|
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):
|
return EvaluationResult.OK(Value(Type.LIST, results).decompose())
|
||||||
for i in range(count.value):
|
|
||||||
if type(asterisk.iterator) == IdentifierNode:
|
return EvaluationResult.FAIL()
|
||||||
environment.scopes[-1][f"_{asterisk.iterator.identifier}"] = Value(Type.INTEGER, i+1)
|
|
||||||
|
return evaluator
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _automaticNamedVariable(cls, iteratorNode, environment, prefix=''):
|
||||||
|
if type(iteratorNode) == IdentifierNode:
|
||||||
|
return cls._automaticVariableName(environment, prefix, iteratorNode.value, False)
|
||||||
else:
|
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:
|
return variableName(number)
|
||||||
del environment.scopes[-1][f"_{asterisk.iterator.identifier}"]
|
|
||||||
else:
|
|
||||||
del environment.scopes[-1]["_"]
|
|
||||||
|
|
||||||
|
@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):
|
del environment.scopes[-1][automaticVariableKey]
|
||||||
for i, v in enumerate(list.value):
|
del environment.scopes[-1][automaticVariableValue]
|
||||||
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)
|
return EvaluationResult.OK(Value(Type.LIST, results).decompose())
|
||||||
|
|
||||||
if type(asterisk.iterator) == IdentifierNode:
|
return EvaluationResult.FAIL()
|
||||||
del environment.scopes[-1][f"_{asterisk.iterator.identifier}"]
|
|
||||||
del environment.scopes[-1][f"{asterisk.iterator.identifier}_"]
|
return evaluator
|
||||||
else:
|
|
||||||
del environment.scopes[-1]["_"]
|
#
|
||||||
del environment.scopes[-1]["__"]
|
# 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
|
@classmethod
|
||||||
def evaluator(cls, node, environment):
|
def evaluator(cls, node, environment):
|
||||||
|
environment.scopes.append({})
|
||||||
|
|
||||||
for child in node.children:
|
for child in node.children:
|
||||||
evaluate(child, environment)
|
evaluate(child, environment)
|
||||||
|
|
||||||
|
environment.scopes.pop(-1)
|
||||||
|
|
||||||
#
|
#
|
||||||
# def evaluateBlock(block, environment):
|
# def evaluateBlock(block, environment):
|
||||||
# environment.scopes.append({})
|
# environment.scopes.append({})
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from smnp.ast.node.access import AccessNode
|
from smnp.ast.node.access import AccessNode
|
||||||
from smnp.ast.node.assignment import AssignmentNode
|
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.identifier import IdentifierNode
|
||||||
from smnp.ast.node.integer import IntegerLiteralNode
|
from smnp.ast.node.integer import IntegerLiteralNode
|
||||||
from smnp.ast.node.invocation import FunctionCallNode
|
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.access import AccessEvaluator
|
||||||
from smnp.runtime.evaluators.assignment import AssignmentEvaluator
|
from smnp.runtime.evaluators.assignment import AssignmentEvaluator
|
||||||
|
from smnp.runtime.evaluators.asterisk import AsteriskEvaluator
|
||||||
result = Evaluator.oneOf(
|
result = Evaluator.oneOf(
|
||||||
Evaluator.forNodes(FunctionCallEvaluator.evaluate, FunctionCallNode),
|
Evaluator.forNodes(FunctionCallEvaluator.evaluate, FunctionCallNode),
|
||||||
Evaluator.forNodes(StringEvaluator.evaluate, StringLiteralNode),
|
Evaluator.forNodes(StringEvaluator.evaluate, StringLiteralNode),
|
||||||
@@ -30,7 +32,8 @@ def expressionEvaluator(doAssert=False):
|
|||||||
Evaluator.forNodes(IdentifierEvaluator.evaluate, IdentifierNode),
|
Evaluator.forNodes(IdentifierEvaluator.evaluate, IdentifierNode),
|
||||||
Evaluator.forNodes(ListEvaluator.evaluate, ListNode),
|
Evaluator.forNodes(ListEvaluator.evaluate, ListNode),
|
||||||
Evaluator.forNodes(AccessEvaluator.evaluate, AccessNode),
|
Evaluator.forNodes(AccessEvaluator.evaluate, AccessNode),
|
||||||
Evaluator.forNodes(AssignmentEvaluator.evaluate, AssignmentNode)
|
Evaluator.forNodes(AssignmentEvaluator.evaluate, AssignmentNode),
|
||||||
|
Evaluator.forNodes(AsteriskEvaluator.evaluate, AsteriskNode)
|
||||||
)(node, environment)
|
)(node, environment)
|
||||||
|
|
||||||
if doAssert and result.result and result.value.type == Type.VOID:
|
if doAssert and result.result and result.value.type == Type.VOID:
|
||||||
|
|||||||
Reference in New Issue
Block a user