|
|
|
@ -4,6 +4,8 @@ date: 2020-03-06T17:56:55-08:00 |
|
|
|
|
tags: ["Programming Languages"] |
|
|
|
|
--- |
|
|
|
|
|
|
|
|
|
{{< stack_css >}} |
|
|
|
|
|
|
|
|
|
In CS 381, Programming Language Fundamentals, many students chose to |
|
|
|
|
implement a stack based language. Such languages are very neat, |
|
|
|
|
but two of the requirements for such languages may, at first, |
|
|
|
@ -132,16 +134,31 @@ However, to stick by convention 4, we pretend that the stack is empty, and that |
|
|
|
|
trying to manipulate it will result in an error. So, we can start by imagining |
|
|
|
|
an empty stack, with an integer \\(x\\) on top: |
|
|
|
|
|
|
|
|
|
{{< stack_image "if_999_1_part1.png" >}} |
|
|
|
|
{{< stack >}} |
|
|
|
|
{{< stack_element >}}{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}\(x\){{< /stack_element >}} |
|
|
|
|
{{< /stack >}} |
|
|
|
|
|
|
|
|
|
Then, \\(\\text{PushI} \\; 0\\) will push 0 onto the stack: |
|
|
|
|
|
|
|
|
|
{{< stack_image "if_999_1_part2.png" >}} |
|
|
|
|
{{< stack >}} |
|
|
|
|
{{< stack_element >}}{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}0{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}\(x\){{< /stack_element >}} |
|
|
|
|
{{< /stack >}} |
|
|
|
|
|
|
|
|
|
\\(\\text{Slide} \\; 1\\) will then remove the 1 element after the top element: \\(x\\). |
|
|
|
|
We end up with the following stack: |
|
|
|
|
|
|
|
|
|
{{< stack_image "slide_example_part3.png" >}} |
|
|
|
|
{{< stack >}} |
|
|
|
|
{{< stack_element >}}{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}0{{< /stack_element >}} |
|
|
|
|
{{< /stack >}} |
|
|
|
|
|
|
|
|
|
The function has finished running, and we maintain convention 3: the function's |
|
|
|
|
return value is in place of its argument on the stack. |
|
|
|
@ -194,20 +211,40 @@ Eq |
|
|
|
|
Let's walk through this. We start with only the arguments |
|
|
|
|
on the stack: |
|
|
|
|
|
|
|
|
|
{{< stack_image "recursion_all_part1.png" >}} |
|
|
|
|
{{< stack >}} |
|
|
|
|
{{< stack_element >}}{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}\(n\){{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}factorial{{< /stack_element >}} |
|
|
|
|
{{< /stack >}} |
|
|
|
|
|
|
|
|
|
Then, \\(\\text{Offset} \\; 0\\) duplicates the first argument |
|
|
|
|
(the number): |
|
|
|
|
|
|
|
|
|
{{< stack_image "recursion_all_part2.png" >}} |
|
|
|
|
{{< stack >}} |
|
|
|
|
{{< stack_element >}}{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}\(n\){{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}\(n\){{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}factorial{{< /stack_element >}} |
|
|
|
|
{{< /stack >}} |
|
|
|
|
|
|
|
|
|
Next, 0 is pushed onto the stack: |
|
|
|
|
|
|
|
|
|
{{< stack_image "recursion_all_part3.png" >}} |
|
|
|
|
{{< stack >}} |
|
|
|
|
{{< stack_element >}}0{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}\(n\){{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}\(n\){{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}factorial{{< /stack_element >}} |
|
|
|
|
{{< /stack >}} |
|
|
|
|
|
|
|
|
|
Finally, \\(\\text{Eq}\\) performs the equality check: |
|
|
|
|
|
|
|
|
|
{{< stack_image "recursion_all_part4.png" >}} |
|
|
|
|
{{< stack >}} |
|
|
|
|
{{< stack_element >}}{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}true/false{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}\(n\){{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}factorial{{< /stack_element >}} |
|
|
|
|
{{< /stack >}} |
|
|
|
|
|
|
|
|
|
Great! Now, it's time to branch. What happens if "true" is on top of |
|
|
|
|
the stack? In that case, we no longer need any more information. |
|
|
|
@ -221,11 +258,21 @@ Slide 2 |
|
|
|
|
|
|
|
|
|
As before, we push the desired answer onto the stack: |
|
|
|
|
|
|
|
|
|
{{< stack_image "recursion_base_part2.png" >}} |
|
|
|
|
{{< stack >}} |
|
|
|
|
{{< stack_element >}}{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}1{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}\(n\){{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}factorial{{< /stack_element >}} |
|
|
|
|
{{< /stack >}} |
|
|
|
|
|
|
|
|
|
Then, to follow convention 3, we must get rid of the arguments. We do this by using \\(\\text{Slide}\\): |
|
|
|
|
|
|
|
|
|
{{< stack_image "recursion_base_part3.png" >}} |
|
|
|
|
{{< stack >}} |
|
|
|
|
{{< stack_element >}}{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}1{{< /stack_element >}} |
|
|
|
|
{{< /stack >}} |
|
|
|
|
|
|
|
|
|
Great! The \\(\\textbf{if}\\) branch is now done, and we're left with the correct answer on the stack. |
|
|
|
|
Excellent! |
|
|
|
@ -240,7 +287,12 @@ Offset 1 |
|
|
|
|
|
|
|
|
|
The result is as follows: |
|
|
|
|
|
|
|
|
|
{{< stack_image "recursion_rec_part1.png" >}} |
|
|
|
|
{{< stack >}} |
|
|
|
|
{{< stack_element >}}{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}factorial{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}\(n\){{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}factorial{{< /stack_element >}} |
|
|
|
|
{{< /stack >}} |
|
|
|
|
|
|
|
|
|
Next, we must compute \\(n-1\\). This is pretty standard stuff: |
|
|
|
|
|
|
|
|
@ -253,11 +305,21 @@ Add |
|
|
|
|
Why these three instructions? Well, with the function now on the top of the stack, the number argument is somewhat |
|
|
|
|
buried, and thus, we need to use \\(\\text{Offset} \\; 1\\) to get to it: |
|
|
|
|
|
|
|
|
|
{{< stack_image "recursion_rec_part2.png" >}} |
|
|
|
|
{{< stack >}} |
|
|
|
|
{{< stack_element >}}\(n\){{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}factorial{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}\(n\){{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}factorial{{< /stack_element >}} |
|
|
|
|
{{< /stack >}} |
|
|
|
|
|
|
|
|
|
Then, we push a negative number, and add it to to the number on top. We end up with: |
|
|
|
|
|
|
|
|
|
{{< stack_image "recursion_rec_part3.png" >}} |
|
|
|
|
{{< stack >}} |
|
|
|
|
{{< stack_element >}}\(n-1\){{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}factorial{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}\(n\){{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}factorial{{< /stack_element >}} |
|
|
|
|
{{< /stack >}} |
|
|
|
|
|
|
|
|
|
Finally, we have our arguments in order as per convention 2. To follow convention 1, we must |
|
|
|
|
now push the function onto the top of the stack: |
|
|
|
@ -268,7 +330,13 @@ Offset 1 |
|
|
|
|
|
|
|
|
|
The stack is now as follows: |
|
|
|
|
|
|
|
|
|
{{< stack_image "recursion_rec_part4.png" >}} |
|
|
|
|
{{< stack >}} |
|
|
|
|
{{< stack_element >}}factorial{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}\(n-1\){{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}factorial{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}\(n\){{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}factorial{{< /stack_element >}} |
|
|
|
|
{{< /stack >}} |
|
|
|
|
|
|
|
|
|
Good! With the preparations for the function call now complete, we take |
|
|
|
|
the leap: |
|
|
|
@ -284,7 +352,12 @@ will be removed from the stack and replaced with the result of the function |
|
|
|
|
as per convention 2. The rest of the stack will remain untouched as |
|
|
|
|
per convention 4. We thus expect the stack to look as follows: |
|
|
|
|
|
|
|
|
|
{{< stack_image "recursion_rec_part5.png" >}} |
|
|
|
|
{{< stack >}} |
|
|
|
|
{{< stack_element >}}{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}\((n-1)!\){{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}\(n\){{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}factorial{{< /stack_element >}} |
|
|
|
|
{{< /stack >}} |
|
|
|
|
|
|
|
|
|
We're almost there! What's left is to perform the multiplication (we're |
|
|
|
|
safe to destroy the argument now, since we will not be needing it after |
|
|
|
@ -298,12 +371,22 @@ Slide 1 |
|
|
|
|
The multiplication leaves us with \\(n(n-1)! = n!\\) on top of the stack, |
|
|
|
|
and the function argument below it: |
|
|
|
|
|
|
|
|
|
{{< stack_image "recursion_rec_part6.png" >}} |
|
|
|
|
{{< stack >}} |
|
|
|
|
{{< stack_element >}}{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}\(n!\){{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}factorial{{< /stack_element >}} |
|
|
|
|
{{< /stack >}} |
|
|
|
|
|
|
|
|
|
We then use \\(\\text{Slide}\\) so that only the factorial is on the |
|
|
|
|
stack, satisfying convention 3: |
|
|
|
|
|
|
|
|
|
{{< stack_image "recursion_rec_part7.png" >}} |
|
|
|
|
{{< stack >}} |
|
|
|
|
{{< stack_element >}}{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}{{< /stack_element >}} |
|
|
|
|
{{< stack_element >}}\(n!\){{< /stack_element >}} |
|
|
|
|
{{< /stack >}} |
|
|
|
|
|
|
|
|
|
That's it! We have successfully executed the recursive case. The whole |
|
|
|
|
function is now as follows: |