Problem 2 (150pts): @builtin

To be able to call built-in procedures, such as +, you need to complete the BuiltinProcedure case within the scheme_apply function in scheme_eval_apply.py. Built-in procedures are applied by calling a corresponding Python function that implements the procedure.

To see a list of all Scheme built-in procedures used in the project, look in the scheme_builtins.py file. Any function decorated with @builtin will be added to the globally-defined BUILTINS list.

A BuiltinProcedure has two instance attributes:

  • py_func: the Python function that implements the built-in Scheme procedure.
  • expect_env: a Boolean flag that indicates whether or not this built-in procedure will expect the current environment to be passed in as the last argument. The environment is required, for instance, to implement the built-in eval procedure.

scheme_apply takes the procedure object, a list of argument values, and the current environment. args is a Scheme list represented as a Pair object or nil. Your implementation should do the following:

  • Convert the Scheme list to a Python list of arguments. Hint: args is a Pair, which has a .first and .rest similar to a Linked List. Think about how you would put the values of a Linked List into a list.
  • If procedure.expect_env is True, then add the current environment env as the last argument to this Python list.
  • Call procedure.py_func on all of those arguments using *args notation (f(1, 2, 3) is equivalent to f(*[1, 2, 3])).
  • If calling the function results in a TypeError exception being raised, then the wrong number of arguments were passed. Use a try/except block to intercept the exception and raise a SchemeError with the message 'incorrect number of arguments'.
  • Otherwise, scheme_apply should return the value obtained by calling procedure.py_func

Use Ok to unlock and test your code:

python ok -q 02 -u
python ok -q 02