Example #1
0
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)
Example #2
0
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)
Example #3
0
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
Example #4
0
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
Example #5
0
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)
Example #6
0
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)