Files
boring-lang/boring/interpret.py
2021-02-20 19:58:56 -07:00

76 lines
3.0 KiB
Python

import sys
import copy
from boring import parse
from dataclasses import dataclass
@dataclass
class Environment:
identifiers: dict
class Interpreter:
def handle_identifier(self, env, identifier):
return env.identifiers[identifier.name]
def handle_literal_int(self, env, literal_int):
return literal_int.value
def handle_function_call(self, env, function_call):
new_env = copy.deepcopy(env)
function_definition = new_env.identifiers[function_call.name.name]
assert len(function_definition.arguments) == len(function_call.arguments)
for i, argument in enumerate(function_definition.arguments):
new_env.identifiers[argument.name.name] = self.handle_expression(env, function_call.arguments[i])
return self.handle_block(new_env, function_definition.block)
def handle_operation(self, env, operation):
if operation.op == parse.Operator.plus:
return self.handle_expression(env, operation.left) + self.handle_expression(env, operation.right)
elif operation.op == parse.Operator.minus:
return self.handle_expression(env, operation.left) - self.handle_expression(env, operation.right)
elif operation.op == parse.Operator.mult:
return self.handle_expression(env, operation.left) * self.handle_expression(env, operation.right)
elif operation.op == parse.Operator.div:
return self.handle_expression(env, operation.left) / self.handle_expression(env, operation.right)
def handle_expression(self, env, expression):
if type(expression.expression) == parse.LiteralInt:
return self.handle_literal_int(env, expression.expression)
elif type(expression.expression) == parse.FunctionCall:
return self.handle_function_call(env, expression.expression)
elif type(expression.expression) == parse.Identifier:
return self.handle_identifier(env, expression.expression)
elif type(expression.expression) == parse.Operation:
return self.handle_operation(env, expression.expression)
elif type(expression.expression) == parse.Expression:
return self.handle_expression(env, expression.expression)
else:
raise Exception(f"unexpected type: {type(expression.expression)}")
def handle_block(self, env, block):
return self.handle_expression(env, block.expression)
def run(self, module):
env = Environment(identifiers={})
for function in module.functions:
env.identifiers[function.name.name] = function
if 'main' not in env.identifiers:
raise Exception("must have main function")
return self.handle_function_call(env, parse.FunctionCall(name=parse.Identifier("main"), arguments=[]))
if __name__ == '__main__':
with open(sys.argv[1]) as f:
tree = parse.boring_parser.parse(f.read())
# print(tree)
ast = parse.TreeToBoring().transform(tree)
print(ast)
result = Interpreter().run(ast)
print(result)
exit(result)