# SICP Solutions

### Chapter 5, Computing with Register Machines

#### Exercise 5.38

Interesting and took much more time than i anticipated!

Few points for the approach:

• For consistency, I think it is important to evaluate the primitive arguments also in the right to left order as is the case with all the procedures arguments.
• Since in the first part for spread-arguments, it was not mentioned that there will only be two arg registers. So I made a global list of arg registers and if there can be more than 2 then just need add them in the global list(in code all-arg-regs) of arg regs.
• Used a inbuilt scheme procedure take which returns the first n elements of the list passed to it.

Since this contained a good amount of changes, I have also put the complete code of file ch5-compiler.scm at the bottom of this page.

#### (a)

Code follows after this description.

Note the iter procedure inside spread-arguments is called with two arguments, operands-list and arg-args. Since we need as many arg registers (like arg1, arg2) as the number of operands. Thus iter is invoked with by taking(using take) as many registers from all-arg-regs as the number of operands.

Note that for right to left evaluation, preserving first is passed the instruction for the rest operands and then the first operand.

For first-operand, again preserving is used(see the line marked with ;;;1), because the results of rest-operands must be saved before evaluating the first operand.

Why canâ€™t we just used only the first use of preserving and pass the registers to be preserved along with the env.

To understand the preserving marked with comment ;;;1, first let me recall how preserving works:

It preserves the registers which are modified by first sequence but needed in second sequence.

Now, where are the results of rest operands saved?

Well, there is one to one mapping between each register in arg-regs and each operand in operands-list. Thus (cdr arg-regs) is the answer.

Ofcourse, we need to preserve env register as the remaining arguments might use variables from the environment stored in env.

Note that spread-arguments assumes that there are atleast as many arg registers as there are the number of operands. The user/caller of spread-arguments should ensure it.

#### (b)

compile-open-code is a common procedure used by all the code generators compile-add, compile-sub etc.

Just one thing to note, continue might get modified by call to spread-arguments and end-with-linkage takes care of it.

#### (c)

factorial with Open Coding

As we can see, now there are no more procedure invocation instructions generated for =, -.

#### (d)

This took me quite some time but turned out quite simple. We can just use the procedures created above.

The idea is quite simple: To compile (+ 1 2 3 4 5), compile (+ 1 2) and compile (+ 3 4 5) separately and merge the results as (+ result-1 result-2). The recursion takes care of the rest!

One special case: (+ 1 2 3) should be splitted as (+ 1 2) and 3(not + 3).

Procedure split, divides the list passed to it in two parts, with first containing n items and second part containing the remaining items. If n is large than the number of items then it will return all the iterms in the first part only and rest part will be empty.