Skip to content

Instantly share code, notes, and snippets.

@chelseatroy
Last active August 7, 2021 16:16
Show Gist options
  • Save chelseatroy/a65f912fd25b2eaff15c6b15d9569eac to your computer and use it in GitHub Desktop.
Save chelseatroy/a65f912fd25b2eaff15c6b15d9569eac to your computer and use it in GitHub Desktop.
My ersatz interpreter
# 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