Skip to content

Instantly share code, notes, and snippets.

@chelseatroy
Last active Aug 7, 2021
Embed
What would you like to do?
Interpreter Without Environment Poltergeist
# 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 = {}
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):
env[str(node.name)] = {"value": interpret(node.value, env), "mutable": True}
return Unit()
elif isinstance(node, ConstantAssignment):
env[str(node.name)] = {"value": interpret(node.value, env), "mutable": False}
return Unit()
elif isinstance(node, VariableDeclaration):
env[str(node.name)] = {"value": None, "mutable": True}
return Unit()
elif isinstance(node, VariableReAssignment):
if str(node.name) in env.keys():
if not env[str(node.name)]['mutable']:
raise RuntimeError("Cannot reassign the value of a constant")
else:
env[str(node.name)] = interpret(node.value, env)
else:
raise RuntimeError(f"{node.name} not found for reassignment")
return Unit()
elif isinstance(node, Name):
if node.name in env.keys():
return env.get(node.name).get('value')
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