Original JavaScript
Original JavaScript
Original JavaScript
Original JavaScript

[1] There is no need to distinguish between statements and expressions in our evaluator. For example, we do not differentiate between expressions and expression statements; we represent them identically and consequently they are handled in the same way by the evaluate function. Similarly, our evaluator does not enforce JavaScript's syntactic restriction that statements cannot appear inside expressions other than lambda expressions.
[2] This test is a deferred operation, and thus our evaluator will give rise to a recursive process even if the interpreted program should give rise to an iterative process according to the description in section 1.2.1. In other words, our metacircular evaluator implementation of JavaScript is not tail-recursive. Sections 5.4.2 and 5.5.3 show how to achieve tail recursion using a register machine.
[3] We could have simplified the application? clause in eval by using map (and stipulating that operands returns a list) rather than writing an explicit list-of-values procedure. We chose not to use map here to emphasize the fact that the evaluator can be implemented without any use of higher-order procedures (and thus could be written in a language that doesn't have higher-order procedures), even though the language that it supports will include higher-order procedures.
[4] We chose to implement list_of_values using the higher-order function map, and we will use map in other places as well. However, the evaluator can be implemented without any use of higher-order functions (and thus could be written in a language that doesn't have higher-order functions), even though the language that it supports will include higher-order functions. For example, list_of_values can be written without map as follows: function list_of_values(exps, env) { return is_null(exps) ? null : pair(evaluate(head(exps), env), list_of_values(tail(exps), env)); }
[5] In this case, the language being implemented and the implementation language are the same. Contemplation of the meaning of true? is_truthy here yields expansion of consciousness without the abuse of substance.
[6] The treatment of return statements in eval_sequence reflects the proper result of evaluating function applications in JavaScript, but the evaluator presented here does not comply with the ECMAScript specification for the value of a program that consists of a sequence of statements outside of any function body. Exercise 4.13 addresses this issue.
[7] The application of the function make_return_value to the result of evaluating the return expression creates a deferred operation, in addition to the deferred operation created by apply. See footnote 2 for details.
[8] This implementation of define ignores a subtle issue in the handling of internal definitions, although it works correctly in most cases. We will see what the problem is and how to solve it in section 4.1.6.
[9] As we said when we introduced define and set!, these values are implementation-dependent in Scheme—that is, the implementor can choose what value to return.
4.1.1   The Core of the Evaluator