Expressions Components - SICP Comparison Edition" /> 5.5.2   Compiling <span style="color:green">Expressions</span> <span style="color:blue">Components</span> - SICP Comparison Edition
 Original JavaScript The literal value is extracted at compile time from the component being compiled and put into the constant part of the assign instruction. For a name, an instruction is generated to use the lookup_symbol_value operation when the compiled program is run, to look up the value associated with a symbol in the current environment. Like a literal value, the symbol is extracted at compile time from the component being compiled. Thus symbol_of_name(component) is executed only once, when the program is being compiled, and the symbol appears as a constant in the assign instruction.
 Original JavaScript Note that cond is a derived expression, so all that the compiler needs to do to handle it is to apply the cond->if transformer (from section 4.1.2) and compile the resulting if expression.
Original JavaScript
 Original JavaScript To ensure that all functions end by executing a return statement, compile_lambda_body appends to the lambda body a return statement whose return expression is the literal undefined. To do so, it uses the function append_return_undefined, which constructs the parser's tagged-list representation (from section 4.1.2) of a sequence consisting of the body and a return undefined; statement. function append_return_undefined(body) { return list("sequence", list(body, list("return_statement", list("literal", undefined)))); } This simple transformation of lambda bodies is a third way to ensure that a function that does not return explicitly has the return value undefined. In the metacircular evaluator, we used a return-value object, which also played a role in stopping a sequence evaluation. In the explicit-control evaluator, functions that did not return explicitly continued to an entry point that stored undefined in val. See exercise 5.37 for a more elegant way to handle insertion of return statements. Exercise 5.36 Footnote 4 pointed out that the compiler does not identify all instances of dead code. What would be required of a compiler to detect all instances of dead code? Hint: The answer depends on how we define dead code. One possible (and useful) definition is code following a return statement in a sequence—but what about code in the consequent branch of if (false) $\ldots$ or code following a call to run_forever() in exercise 4.20? There is currently no solution available for this exercise. This textbook adaptation is a community effort. Do consider contributing by providing a solution for this exercise, using a Pull Request in Github. Exercise 5.37 The current design of append_return_undefined is a bit crude: It always appends a return undefined; to a lambda body, even if there is already a return statement in every execution path of the body. Rewrite append_return_undefined so that it inserts return undefined; at the end of only those paths that do not contain a return statement. Test your solution on the functions below, substituting any expressions for $e_1$ and $e_2$ and any (non-return) statements for $s_1$ and $s_2$. In t, a return statement should be added either at both (*)'s or just at (**). In w and h, a return statement should be added at one of the (*)'s. In m, no return statement should be added. function t(b) { function w(b) { function m(b) { function h(b1, b2) { if (b) { if (b) { if (b) { if (b1) { $s_1~~$ return $e_1;~$ return $e_1;~$ return $e_1$; (*) } else { } else { } else { } else { if (b2) { $s_2~~$ $s_1~~$ return $e_2$; $s_1$ (*) (*) (*) } } } } else { (**) (*) return $e_2$; } } } } (*) } (*) } There is currently no solution available for this exercise. This textbook adaptation is a community effort. Do consider contributing by providing a solution for this exercise, using a Pull Request in Github.

[1] This procedure uses a feature of Lisp called backquote (or quasiquote) that is handy for constructing lists. Preceding a list with a backquote symbol is much like quoting it, except that anything in the list that is flagged with a comma is evaluated.

For example, if the value of linkage is the symbol branch25, then the expression ((goto (label ,linkage))) evaluates to the list ((goto (label branch25))). Similarly, if the value of x is the list (a b c), then (1 2 ,x) evaluates to the list (1 2 a).
[2] We can't just use the labels true-branch, true_branch, false-branch, false_branch, and after-if after_cond as shown above, because there might be more than one ifconditional in the program. The compiler uses the procedure function make-label make_label to generate labels. Make-label The function make_label takes a symbolstring as argument and returns a new symbolstring that begins with the given symbolstring. For example, successive calls to (make-label 'a) make_label("a") would return a1"a1", a2"a2", and so on. Make-label The function make_label can be implemented similarly to the generation of unique variable names in the query language, as follows:
 Original JavaScript (define label-counter 0) (define (new-label-number) (set! label-counter (+ 1 label-counter)) label-counter) (define (make-label name) (string->symbol (string-append (symbol->string name) (number->string (new-label-number))))) let label_counter = 0; function new_label_number() { label_counter = label_counter + 1; return label_counter; } function make_label(string) { return string + stringify(new_label_number()); }
[3] The continue register would be needed for a "return" linkage, which can result from a compilation by compile_and_go (section 5.5.7).
[4] Our compiler does not detect all dead code. For example, a conditional statement whose consequent and alternative branches both end in a return statement will not stop subsequent statements from being compiled. See exercises 5.36 and 5.37.
[5] We need machine operations to implement a data structure for representing compiled procedures, functions, analogous to the structure for compound procedures functions described in section 4.1.3:
 Original JavaScript (define (make-compiled-procedure entry env) (list 'compiled-procedure entry env)) (define (compiled-procedure? proc) (tagged-list? proc 'compiled-procedure)) (define (compiled-procedure-entry c-proc) (cadr c-proc)) (define (compiled-procedure-env c-proc) (caddr c-proc)) function make_compiled_function(entry, env) { return list("compiled_function", entry, env); } function is_compiled_function(fun) { return is_tagged_list(fun, "compiled_function"); } function compiled_function_entry(c_fun) { return head(tail(c_fun)); } function compiled_function_env(c_fun) { return head(tail(tail(c_fun))); }
[6] The augmented function body is a sequence ending with a return statement. Compilation of a sequence of statements uses the linkage "next" for all its component statements except the last, for which it uses the given linkage. In this case, the last statement is a return statement, and as we will see in section 5.5.3, a return statement always uses the "return" linkage descriptor for its return expression. Thus all function bodies will end with a "return" linkage, not the "next" we pass as the linkage argument to compile in compile_lambda_body.
5.5.2   Compiling Expressions Components