Fix evaluator to make use of new parser

This commit is contained in:
Bartłomiej Pluta
2019-07-01 19:30:50 +02:00
parent c266e5b28e
commit 3573ca4e76
3 changed files with 47 additions and 34 deletions

View File

@@ -58,7 +58,7 @@ def sample(args, env):
def _sample(list):
return list[int(random.uniform(0, len(list)))]
def doPrint(args, env):
def doPrint(args, env):
print("".join([objectString(arg) for arg in args]))
def semitonesList(list):

View File

@@ -45,8 +45,8 @@ def evaluateNote(note, environment):
def evaluateFunctionDefinition(definition, environment):
name = definition.name
params = list([p for p in definition.parameters.children if not isinstance(p, CommaNode)])
body = definition.body.children
params = list([p for p in flatListNode(definition.parameters) if not isinstance(p, CommaNode)])
body = definition.body
if not isinstance(definition.parent, Program):
raise RuntimeException(name.pos, f"Functions can be defined only on the top level of script")
@@ -60,19 +60,32 @@ def evaluateFunctionDefinition(definition, environment):
environment.customFunctions[name.identifier] = {
'params': params,
'body': body
'body': flatListNode(body)
}
def flatListNode(listNode):
if len(listNode.children[0].children) == 1:
return []
return _flatListNode(listNode.children[0], [])
def evaluateFunctionCall(functionCall, environment):
def _flatListNode(listItemNode, list = []):
if len(listItemNode.children) == 2:
child1 = listItemNode.children[0]
child2 = listItemNode.children[1]
list.append(child1)
_flatListNode(child2, list)
return list
def evaluateFunctionCall(functionCall, environment):
funcName = functionCall.identifier.identifier
arguments = evaluateList(functionCall.arguments, environment)
arguments = evaluateList(functionCall.arguments, environment)
for name, function in environment.customFunctions.items():
if funcName == name:
if len(function['params']) != len(arguments):
raise RuntimeException(functionCall.pos, f"Calling '{funcName}' requires {len(function['params'])} and {len(arguments)} was passed")
environment.scopes.append({ function['params'][i].identifier: v for i, v in enumerate(arguments) })
returnValue = None
for node in function['body']:
returnValue = None
for node in function['body']:
if not isinstance(node, ReturnNode):
evaluate(node, environment)
else:
@@ -92,12 +105,12 @@ def evaluateComma(comma, environment):
def evaluateBlock(block, environment):
environment.scopes.append({})
for node in block.children:
for node in flatListNode(block):
evaluate(node, environment)
environment.scopes.pop(-1)
def evaluateList(list, environment):
return [evaluate(e, environment) for e in list if not isinstance(e, CommaNode)]
return [evaluate(e, environment) for e in flatListNode(list) if not isinstance(e, CommaNode)]
def evaluateAssignment(assignment, environment):
target = assignment.target.identifier
@@ -165,9 +178,9 @@ def evaluate(input, environment):
return evaluateBlock(input, environment)
if isinstance(input, ListNode):
return evaluateList(input, environment)
if isinstance(input, AssignExpression):
if isinstance(input, AssignmentNode):
return evaluateAssignment(input, environment)
if isinstance(input, AsteriskStatementNode):
if isinstance(input, AsteriskNode):
return evaluateAsterisk(input, environment)
if isinstance(input, ColonNode):
return evaluateColon(input, environment)

View File

@@ -132,7 +132,7 @@ def parseList(input, parent):
# list -> expr listTail
if input.hasCurrent():
token = input.current()
expr = rollup(parseExpression)(input, node)
expr = parseExpression(input, node)
item = ListItemNode(expr, node, token.pos)
expr.parent = item
node.append(item)
@@ -281,34 +281,18 @@ def parseReturn(input, parent):
return None
def parseStatement(input, parent):
value = runParsers(input, parent, [
stmt = runParsers(input, parent, [
parseBlock,
parseExpression,
parseFunctionDefinition,
parseReturn
])
return value
def parseExpression(input, parent):
expr = runParsers(input, parent, [
parseIntegerAndPercent,
parseMinus,
parseString,
parseNote,
parseList,
parseIdentifierOrFunctionCallOrAssignment,
])
colon = parseColon(expr, input, parent)
if colon is not None:
return colon
asterisk = parseAsterisk(expr, input, parent)
asterisk = parseAsterisk(stmt, input, parent)
if asterisk is not None:
return asterisk
return expr
return stmt
# asterisk -> expr '*' stmt
def parseAsterisk(expr, input, parent):
@@ -324,6 +308,22 @@ def parseAsterisk(expr, input, parent):
return asterisk
return None
def parseExpression(input, parent):
expr = runParsers(input, parent, [
parseIntegerAndPercent,
parseMinus,
parseString,
parseNote,
parseList,
parseIdentifierOrFunctionCallOrAssignment,
])
colon = parseColon(expr, input, parent)
if colon is not None:
return colon
return expr
# colon -> expr ':' expr
def parseColon(expr1, input, parent):
if input.hasCurrent() and input.current().type == TokenType.COLON: