15-122: Principles of Imperative Computation Lab 5: Misclaculations Tom Cortina, Rob Simmons
15-122: Principles of Imperative Computation Lab 5: Misclaculations Tom Cortina, Rob Simmons
Lab 5: Misclaculations
Tom Cortina, Rob Simmons
Collaboration: In lab, we encourage collaboration and discussion as you work through the problems.
These activities, like recitation, are meant to get you to review what weve learned, look at problems from
a different perspective and allow you to ask questions about topics you dont understand. We encourage
discussing problems with your neighbors as you work through this lab!
During the Clac programming assignment (not just during this lab), we furthermore encourage you to
share any interesting Clac programs you write with other students on Piazza.
Grading: For two points, you must correctly answer (1.a), (2.a), and (2.b). Write down your answers
and get a TA to check them. For three points, finish the rest of the lab.
Postfix expressions
You are used to using infix expressions where the operator is in between its two operands (e.g. 3 + 4).
In postfix expressions, the operand follows ("post") its two operands (e.g 3 4 +). Postfix expressions
can be used as operands in other postfix expressions. Here are some examples:
INFIX
1 + 2 * 3 - 4
(1 + 2) * 3 - 4
1 + 2 * (3 - 4)
POSTFIX
1 2 3 * + 4 1 2 + 3 * 4 1 2 3 4 - * +
Note that order of operations determines what is converted from infix to postfix first. Also, postfix
expressions never have parentheses.
To evaluate a postfix expression, we can separate it into a queue of tokens of operands and operators,
and then use a stack to evaluate it. For each token in the postfix expression, if it is an operand (e.g. 1),
it is pushed on the stack. If it is an operator, the top two operands are popped from the stack, combined
using that operator, and the result is pushed back on the stack. Once all tokens are processed from the
queue, the final result of the computation should be at the top of the stack.
(1.a) Convert the infix expression
125 - 15 * (3 + 2) / (6 * 4 + 1)
to postfix by hand, and then trace the algorithm described above to compute the value of the
postfix expression. The result should be the same as if you calculated the infix expression directly.
Clac
For the next programming assignment for class, you will implement a stack-based calculator named Clac
that evaluates postfix expressions. A reference (i.e. completed) implementation clac-ref is available
on AFS. Use the -trace option to see how the stack and queue change as an expression is evaluated:
% clac-ref -trace
clac>> 2 3 * 4 +
stack ||
||
2 ||
2 3 ||
6 ||
6 4 ||
10 ||
queue
2 3 * 4 +
3 * 4 +
* 4 +
4 +
+
Note that the stack is written left (bottom) to right (top). Enter quit to exit Clac.
(2.a) Use clac-ref to compute the value of your postfix expression from Exercise 1. What is the
maximum size of the stack as this expression is evaluated?
Clac has additional features. The operator < pops an operand y off the stack, then pops another operand
x off the stack, and pushes 1 on the stack if x < y or 0 if x y. The sequence of tokens
(where a and b are replaced by integers)
if a 1 skip b
pops the top operand off the stack, and pushes a on the stack if the popped value was 1 or b if the
popped value was 0.
(2.b) Determine what this function computes in Clac, substituting different values for x as you test it.
x x 0 < if -1 1 skip 1 *
(2.c) The Clac operator if can be used apart from the if a 1 skip b pattern (see the reference
below). Write a program that uses if without a subsequent 1 skip.
We can create new functions in Clac by using the : token followed by the function name and the
operations and a final ; token. For example, here is a function that squares the number on top of the
stack:
: square 1 pick * ;
(2.d) Implement a function that performs the computation in (2.b) by assuming that one copy of x is
on the top of the stack before the function is executed.
Clac reference
Most Clac tokens, when removed from the queue, only manipulate the stack:
Token
n
+
*
/
%
<
<
drop
swap
rot
pick
print
quit
:
:
:
:
:
:
:
:
:
:
:
:
:
:
Before
S
S, x, y
S, x, y
S, x, y
S, x, y
S, x, y
S, x, y
S, x, y
S, x
S, x, y
S, x, y, z
S, xn , . . . , x1 , n
S, x
S
After
S, n
S, x + y
S, x y
S, x y
S, x / y
S, x % y
S, 1
S, 0
S
S, y, x
S, y, z, x
S, xn , . . . , x1 , xn
S
_
Condition or Effect
for 231 n < 231 in decimal
error, if n <= 0
print x followed by newline
exit Clac
The if and skip operations, on the other hand, also manipulate the token queue:
Before
Stack
Queue
S, n || if, Q
After
Stack
Queue
S || Q
S || Q
S || Q
Cond
n 6= 0
n=0
n0