Create working PoC of loop statement

This commit is contained in:
Bartłomiej Pluta
2019-07-12 20:36:56 +02:00
parent 94128d9f21
commit 13a6dedba6
5 changed files with 120 additions and 10 deletions

View File

@@ -7,7 +7,7 @@ from smnp.program.interpreter import Interpreter
def main(): def main():
try: try:
#stdLibraryEnv = loadStandardLibrary() #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() #draft()
#tokens = tokenize(['function a(b...) { x+y}']) #tokens = tokenize(['function a(b...) { x+y}'])
#FunctionDefinitionParser(tokens).node.print() #FunctionDefinitionParser(tokens).node.print()

View File

@@ -1,4 +1,3 @@
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,11 +6,8 @@ class AssignmentEvaluator(Evaluator):
@classmethod @classmethod
def evaluator(cls, node, environment): def evaluator(cls, node, environment):
target = node.target.value target = node.left.value
if target.startswith("_"): value = expressionEvaluator(doAssert=True)(node.right, environment).value #TODO check if it isn't necessary to verify 'result' attr of EvaluatioNResult
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
scopeOfExistingVariable = environment.findVariableScope(target) scopeOfExistingVariable = environment.findVariableScope(target)
if scopeOfExistingVariable is None: if scopeOfExistingVariable is None:
environment.scopes[-1][target] = value environment.scopes[-1][target] = value

View File

@@ -1,5 +1,5 @@
from smnp.ast.node.factor import NotOperator, Power from smnp.ast.node.factor import NotOperator, Power, Loop
from smnp.ast.node.identifier import FunctionCall from smnp.ast.node.identifier import FunctionCall, Assignment
from smnp.ast.node.unit import MinusOperator, Access from smnp.ast.node.unit import MinusOperator, Access
from smnp.error.runtime import RuntimeException from smnp.error.runtime import RuntimeException
from smnp.runtime.evaluator import Evaluator from smnp.runtime.evaluator import Evaluator
@@ -10,17 +10,21 @@ def expressionEvaluator(doAssert=False):
def evaluateExpression(node, environment): def evaluateExpression(node, environment):
from smnp.runtime.evaluators.function import FunctionCallEvaluator from smnp.runtime.evaluators.function import FunctionCallEvaluator
from smnp.runtime.evaluators.minus import MinusEvaluator from smnp.runtime.evaluators.minus import MinusEvaluator
from smnp.runtime.evaluators.atom import AtomEvaluator from smnp.runtime.evaluators.atom import AtomEvaluator
from smnp.runtime.evaluators.access import AccessEvaluator from smnp.runtime.evaluators.access import AccessEvaluator
from smnp.runtime.evaluators.negation import NotEvaluator from smnp.runtime.evaluators.negation import NotEvaluator
from smnp.runtime.evaluators.power import PowerEvaluator from smnp.runtime.evaluators.power import PowerEvaluator
from smnp.runtime.evaluators.loop import LoopEvaluator
from smnp.runtime.evaluators.assignment import AssignmentEvaluator
result = Evaluator.oneOf( result = Evaluator.oneOf(
Evaluator.forNodes(FunctionCallEvaluator.evaluate, FunctionCall), Evaluator.forNodes(FunctionCallEvaluator.evaluate, FunctionCall),
Evaluator.forNodes(MinusEvaluator.evaluate, MinusOperator), Evaluator.forNodes(MinusEvaluator.evaluate, MinusOperator),
Evaluator.forNodes(AccessEvaluator.evaluate, Access), Evaluator.forNodes(AccessEvaluator.evaluate, Access),
Evaluator.forNodes(NotEvaluator.evaluate, NotOperator), Evaluator.forNodes(NotEvaluator.evaluate, NotOperator),
Evaluator.forNodes(PowerEvaluator.evaluate, Power), Evaluator.forNodes(PowerEvaluator.evaluate, Power),
Evaluator.forNodes(LoopEvaluator.evaluate, Loop),
Evaluator.forNodes(AssignmentEvaluator.evaluate, Assignment),
AtomEvaluator.evaluate AtomEvaluator.evaluate
)(node, environment) )(node, environment)

View 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

View File

@@ -73,6 +73,7 @@ class Type(Enum):
def void(): def void():
return Value(Type.VOID, None) return Value(Type.VOID, None)
def _failStringify(t): def _failStringify(t):
raise RuntimeException(f"Not able to interpret {t.name}'", None) raise RuntimeException(f"Not able to interpret {t.name}'", None)