Create working PoC of loop statement
This commit is contained in:
@@ -7,7 +7,7 @@ from smnp.program.interpreter import Interpreter
|
||||
def main():
|
||||
try:
|
||||
#stdLibraryEnv = loadStandardLibrary()
|
||||
Interpreter.interpretFile(sys.argv[1], printTokens=False, printAst=True, execute=True, baseEnvironment=None)
|
||||
Interpreter.interpretFile(sys.argv[1], printTokens=False, printAst=False, execute=True, baseEnvironment=None)
|
||||
#draft()
|
||||
#tokens = tokenize(['function a(b...) { x+y}'])
|
||||
#FunctionDefinitionParser(tokens).node.print()
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
from smnp.error.runtime import RuntimeException
|
||||
from smnp.runtime.evaluator import Evaluator
|
||||
from smnp.runtime.evaluators.expression import expressionEvaluator
|
||||
|
||||
@@ -7,11 +6,8 @@ class AssignmentEvaluator(Evaluator):
|
||||
|
||||
@classmethod
|
||||
def evaluator(cls, node, environment):
|
||||
target = node.target.value
|
||||
if target.startswith("_"):
|
||||
raise RuntimeException("Declaration and assignation 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
|
||||
target = node.left.value
|
||||
value = expressionEvaluator(doAssert=True)(node.right, environment).value #TODO check if it isn't necessary to verify 'result' attr of EvaluatioNResult
|
||||
scopeOfExistingVariable = environment.findVariableScope(target)
|
||||
if scopeOfExistingVariable is None:
|
||||
environment.scopes[-1][target] = value
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from smnp.ast.node.factor import NotOperator, Power
|
||||
from smnp.ast.node.identifier import FunctionCall
|
||||
from smnp.ast.node.factor import NotOperator, Power, Loop
|
||||
from smnp.ast.node.identifier import FunctionCall, Assignment
|
||||
from smnp.ast.node.unit import MinusOperator, Access
|
||||
from smnp.error.runtime import RuntimeException
|
||||
from smnp.runtime.evaluator import Evaluator
|
||||
@@ -10,17 +10,21 @@ def expressionEvaluator(doAssert=False):
|
||||
def evaluateExpression(node, environment):
|
||||
from smnp.runtime.evaluators.function import FunctionCallEvaluator
|
||||
from smnp.runtime.evaluators.minus import MinusEvaluator
|
||||
|
||||
from smnp.runtime.evaluators.atom import AtomEvaluator
|
||||
from smnp.runtime.evaluators.access import AccessEvaluator
|
||||
from smnp.runtime.evaluators.negation import NotEvaluator
|
||||
from smnp.runtime.evaluators.power import PowerEvaluator
|
||||
|
||||
from smnp.runtime.evaluators.loop import LoopEvaluator
|
||||
from smnp.runtime.evaluators.assignment import AssignmentEvaluator
|
||||
result = Evaluator.oneOf(
|
||||
Evaluator.forNodes(FunctionCallEvaluator.evaluate, FunctionCall),
|
||||
Evaluator.forNodes(MinusEvaluator.evaluate, MinusOperator),
|
||||
Evaluator.forNodes(AccessEvaluator.evaluate, Access),
|
||||
Evaluator.forNodes(NotEvaluator.evaluate, NotOperator),
|
||||
Evaluator.forNodes(PowerEvaluator.evaluate, Power),
|
||||
Evaluator.forNodes(LoopEvaluator.evaluate, Loop),
|
||||
Evaluator.forNodes(AssignmentEvaluator.evaluate, Assignment),
|
||||
AtomEvaluator.evaluate
|
||||
)(node, environment)
|
||||
|
||||
|
||||
109
smnp/runtime/evaluators/loop.py
Normal file
109
smnp/runtime/evaluators/loop.py
Normal file
@@ -0,0 +1,109 @@
|
||||
from smnp.ast.node.none import NoneNode
|
||||
from smnp.error.runtime import RuntimeException
|
||||
from smnp.runtime.evaluator import Evaluator, evaluate
|
||||
from smnp.runtime.evaluators.expression import expressionEvaluator
|
||||
from smnp.type.model import Type
|
||||
|
||||
|
||||
class LoopEvaluator(Evaluator):
|
||||
|
||||
@classmethod
|
||||
def evaluator(cls, node, environment):
|
||||
iterator = expressionEvaluator(doAssert=True)(node.left, environment).value
|
||||
parameters = [ identifier.value for identifier in node.parameters ] if type(node.parameters) != NoneNode() else []
|
||||
|
||||
try:
|
||||
output = {
|
||||
Type.INTEGER: cls.numberEvaluator,
|
||||
Type.BOOL: cls.boolEvaluator,
|
||||
Type.LIST: cls.listEvaluator,
|
||||
Type.MAP: cls.mapEvaluator
|
||||
}[iterator.type](node, environment, iterator, parameters)
|
||||
except KeyError:
|
||||
raise RuntimeException(f"The {iterator.type.name.lower()} type cannot stand as an iterator for loop statement", node.left.pos)
|
||||
|
||||
return Type.list(output)
|
||||
|
||||
@classmethod
|
||||
def numberEvaluator(cls, node, environment, evaluatedIterator, parameters):
|
||||
output = []
|
||||
|
||||
environment.scopes.append({})
|
||||
|
||||
if len(parameters) > 1:
|
||||
raise RuntimeException(f"Loop with numeric iterator can handle only one parameter", node.parameters.pos)
|
||||
|
||||
for i in range(evaluatedIterator.value):
|
||||
if len(parameters) > 0:
|
||||
environment.scopes[-1][parameters[0]] = Type.integer(i)
|
||||
|
||||
output.append(evaluate(node.right, environment).value)
|
||||
|
||||
environment.scopes.pop(-1)
|
||||
|
||||
return output
|
||||
|
||||
@classmethod
|
||||
def boolEvaluator(cls, node, environment, evaluatedIterator, parameters):
|
||||
output = []
|
||||
|
||||
environment.scopes.append({})
|
||||
|
||||
if len(parameters) > 0:
|
||||
raise RuntimeException(f"Loop with logic iterator can't' handle any parameters", node.parameters.pos)
|
||||
|
||||
condition = evaluatedIterator
|
||||
while condition.value:
|
||||
output.append(evaluate(node.right, environment).value)
|
||||
condition = expressionEvaluator(doAssert=True)(node.left, environment).value
|
||||
|
||||
environment.scopes.pop(-1)
|
||||
|
||||
return output
|
||||
|
||||
@classmethod
|
||||
def listEvaluator(cls, node, environment, evaluatedIterator, parameters):
|
||||
output = []
|
||||
|
||||
if len(parameters) > 2:
|
||||
raise RuntimeException(f"Loop with list iterator can handle only two parameters", node.parameters.pos)
|
||||
|
||||
for i, value in enumerate(evaluatedIterator.value):
|
||||
if len(parameters) == 1:
|
||||
environment.scopes[-1][parameters[0]] = value
|
||||
if len(parameters) == 2:
|
||||
environment.scopes[-1][parameters[0]] = Type.integer(i)
|
||||
environment.scopes[-1][parameters[1]] = value
|
||||
|
||||
output.append(evaluate(node.right, environment).value)
|
||||
|
||||
environment.scopes.pop(-1)
|
||||
|
||||
return output
|
||||
|
||||
|
||||
@classmethod
|
||||
def mapEvaluator(cls, node, environment, evaluatedIterator, parameters):
|
||||
output = []
|
||||
|
||||
if len(parameters) > 3:
|
||||
raise RuntimeException(f"Loop with map iterator can handle only three parameters", node.parameters.pos)
|
||||
|
||||
i = 0
|
||||
for key, value in evaluatedIterator.value.items():
|
||||
if len(parameters) == 1:
|
||||
environment.scopes[-1][parameters[0]] = value
|
||||
if len(parameters) == 2:
|
||||
environment.scopes[-1][parameters[0]] = key
|
||||
environment.scopes[-1][parameters[1]] = value
|
||||
if len(parameters) == 3:
|
||||
environment.scopes[-1][parameters[0]] = Type.integer(i)
|
||||
environment.scopes[-1][parameters[1]] = key
|
||||
environment.scopes[-1][parameters[2]] = value
|
||||
i += 1
|
||||
|
||||
output.append(evaluate(node.right, environment).value)
|
||||
|
||||
environment.scopes.pop(-1)
|
||||
|
||||
return output
|
||||
@@ -73,6 +73,7 @@ class Type(Enum):
|
||||
def void():
|
||||
return Value(Type.VOID, None)
|
||||
|
||||
|
||||
def _failStringify(t):
|
||||
raise RuntimeException(f"Not able to interpret {t.name}'", None)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user