Last active
August 7, 2021 16:16
-
-
Save chelseatroy/a65f912fd25b2eaff15c6b15d9569eac to your computer and use it in GitHub Desktop.
My ersatz interpreter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Top level function that interprets an entire program. It creates the | |
# initial environment that's used for storing variables. | |
def interpret_program(model): | |
# Make the initial environment (a dict). The environment is | |
# where you will create and store variables. | |
env = {'constants':{}, 'variables':{}} | |
for structure in model.statements: | |
interpret(structure, env) | |
# Internal function to interpret a node in the environment. You need | |
# to expand to cover all of the classes in the model.py file. | |
def interpret(node, env): | |
# Expand to check for different node types | |
if isinstance(node, Integer): | |
return int(node.value) | |
elif isinstance(node, Float): | |
return node.value | |
elif isinstance(node, BinaryOperator): | |
if node.op == '*': | |
return interpret(node.left, env) * interpret(node.right, env) | |
elif node.op == '/': | |
return interpret(node.left, env) / interpret(node.right, env) | |
elif node.op == '+': | |
return interpret(node.left, env) + interpret(node.right, env) | |
elif node.op == '-': | |
return interpret(node.left, env) - interpret(node.right, env) | |
elif isinstance(node, Comparison): | |
if node.op == '>': | |
return interpret(node.left, env) > interpret(node.right, env) | |
elif node.op == '<': | |
return interpret(node.left, env) < interpret(node.right, env) | |
elif node.op == '==': | |
return interpret(node.left, env) == interpret(node.right, env) | |
elif node.op == '>=': | |
return interpret(node.left, env) >= interpret(node.right, env) | |
elif node.op == '<=': | |
return interpret(node.left, env) <= interpret(node.right, env) | |
elif node.op == '!=': | |
return interpret(node.left, env) != interpret(node.right, env) | |
elif isinstance(node, Print): | |
print(interpret(node.value, env)) | |
elif isinstance(node, VariableAssignment): | |
# if node.type.string_representation == the start of type checking | |
env['variables'][str(node.name)] = interpret(node.value, env) | |
return Unit() | |
elif isinstance(node, ConstantAssignment): | |
env['constants'][str(node.name)] = interpret(node.value, env) | |
return Unit() | |
elif isinstance(node, VariableDeclaration): | |
env['variables'][str(node.name)] = "WABBITASSIGNMENTINWAITING" | |
return Unit() | |
elif isinstance(node, VariableReAssignment): | |
if str(node.name) in env['variables'].keys(): | |
env['variables'][str(node.name)] = interpret(node.value, env) | |
elif str(node.name) in env['constants'].keys(): | |
raise RuntimeError("Cannot reassign the value of a constant") | |
else: | |
raise RuntimeError(f"{node.name} not found for reassignment") | |
return Unit() | |
elif isinstance(node, Name): | |
if node.name in env['variables'].keys(): | |
return env['variables'].get(node.name) | |
elif node.name in env['constants'].keys(): | |
return env['constants'].get(str(node.name)) | |
else: | |
raise RuntimeError(f"'{node.name}' not defined") | |
elif isinstance(node, Negative): | |
# gotta check if its type that can be negative | |
return interpret(node.value, env) * -1 | |
elif isinstance(node, Conditional): | |
if interpret(node.if_condition, env): | |
result = interpret(node.if_block, env) | |
if isinstance(result, Break): | |
return Break() | |
else: | |
if node.else_block: | |
result = interpret(node.else_block, env) | |
if isinstance(result, Break): | |
return Break() | |
elif isinstance(node, WhileLoop): | |
if interpret(node.while_condition, env): | |
result = interpret(node.while_block, env) | |
if not isinstance(result, Break): | |
interpret(node, env) | |
else: | |
return Unit() | |
elif isinstance(node, Block): | |
for statement in node.statements: | |
maybe_flow_interruptor = interpret(statement, env) | |
if isinstance(maybe_flow_interruptor, Continue): | |
return Unit() | |
elif isinstance(maybe_flow_interruptor, Break): | |
return Break() | |
return Unit() | |
elif isinstance(node, CompoundExpression): | |
final_statement = None | |
for statement in node.statements: | |
final_statement = interpret(statement, env) | |
return final_statement | |
elif isinstance(node, Break): | |
return Break() | |
elif isinstance(node, Continue): | |
return Continue() | |
elif isinstance(node, WabbitType): | |
return Unit() | |
elif isinstance(node, WabbitBoolean): | |
return node.value | |
elif isinstance(node, Character): | |
return str(node.value) | |
else: | |
raise RuntimeError(f"Can't interpret {node}") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment