def evaluate(env: ValueEnv, exp: Expression) -> int: """Given an environment, evaluate expression.""" if isinstance(exp, int): # number return exp if isinstance(exp, str): # variable try: return env[exp] except KeyError: try: return global_env[exp] except KeyError as exc: raise errors.UndefinedVariable(exp) from exc else: # application expression op_name = exp[0] args = exp[1:] if op_name in CONTROL_OPS: statement = CONTROL_OPS[op_name] return statement(env, *args) else: op = VALUE_OPS[op_name] values = tuple(evaluate(env, x) for x in args) return op(*values)
def evaluate(environment, expression): """Given an environment, evaluate expression.""" if isinstance(expression, int): # number return expression if isinstance(expression, str): # variable try: return environment[expression] except KeyError: try: return global_environment[expression] except KeyError as exc: raise errors.UndefinedVariable(expression) from exc else: # application expression op_name = expression[0] args = expression[1:] if op_name in CONTROL_OPS: op = CONTROL_OPS[op_name] return op(environment, *args) else: op = VALUE_OPS[op_name] values = (evaluate(environment, x) for x in args) return op(*values)
def fetch_variable(environment, name): try: return environment[name] except KeyError: try: return global_env[name] except KeyError as exc: raise errors.UndefinedVariable(name) from exc
def fetch_variable(env: ValueEnv, name: str) -> int: try: return env[name] except KeyError: try: return global_env[name] except KeyError as exc: raise errors.UndefinedVariable(name) from exc
def evaluate(exp: Expression) -> int: """Evaluate expression, return its value (a number).""" if isinstance(exp, int): # number return exp if isinstance(exp, str): # variable try: return global_environment[exp] except KeyError as exc: raise errors.UndefinedVariable(exp) from exc else: # application expression op_name = exp[0] args = exp[1:] if op_name == 'let': name, val_exp = args return let_statement(name, val_exp) else: op = VALUE_OPS[op_name] values = (evaluate(x) for x in args) return op(*values)
VALUE_OPS = { '+': lambda *args: sum(args), '-': operator.sub, '*': operator.mul, '/': divide, } Number: TypeAlias = int | float Atom: TypeAlias = str | Number Expression: TypeAlias = Atom | list global_env: dict[str, int] = {} def evaluate(exp: Expression) -> Number: """Compute value of expression; return a number.""" match exp: case int() | float(): return exp case ['let', name, exp]: value = evaluate(exp) global_env[name] = value return value case [op, *args] if func := VALUE_OPS.get(op): values = map(evaluate, args) return func(*values) case variable if (value := global_env.get(variable)) is not None: return value case _: raise errors.UndefinedVariable(exp)