-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlecture11_calculator_language
212 lines (175 loc) · 6.48 KB
/
lecture11_calculator_language
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/*
CS1101S Lecture L11: CSE Machine
This program contains a CSE machine for a
calculator language
Examples at the end of the program
*/
function evaluate(expr) { // syntax tree as argument
let C = list(expr); // C is the whole program first
// control - when we start, the given program is the only thing on the control
let S = null; // stash
while (! is_null(C)) { // in loop keep taking the next element from the control
// and decide what to do next
display_control(C);
display_stash(S);
const command = head(C); // take head
C = tail(C); // and remove it from C
// take action on command accordingly
// expressions and statements
if (is_literal(command)) { // if command is literal
// move the literal from the control to the stash
// push the literal to the stash (put it in front)
S = pair(literal_value(command), S);
// if command is binary operator combination:
} else if (is_binary_operator_combination(command)) {
// split the combination into its components
// first operand as first item on control
// beginning of the list
// (in the visualiser at the bottom)
/* eg here in control the first thing is taken first
when we see the cse visualiser we see the literal is actually
at the bottom
but the process is the same
here the top of our control is actually at the top
so it goes forward
in cse its reverse so it takes the commands also reverse
*** control *** ""
list("literal", 1.4)
list("binary_operator_combination", "/", "...")
list("binop", "+")
""
*** stash *** ""
""
*** control *** ""
list("binary_operator_combination", "/", "...")
list("binop", "+")
""
*** stash *** ""
1.4
*/
// then second operand
// then actual operator
// from the selector operator_symbol(command)
// and make instructions out of that
// in control: program components and instructions
// in binary operator combinations -
// making binary operator instruction
// and putting it on the control
C = pair(first_operand(command),
pair(second_operand(command),
pair(make_binary_operator_instruction(
operator_symbol(command)),
C)));
// machine instructions
// from the previous step after making the instruction
// and putting it in the control
// when we encounter the binary operator instruction
} else if (is_binary_operator_instruction(command)) {
// find the arguments i.e. operands on the stash
// remove the two arguments from the stash
// apply the binary operator corresponding to the operator symbol
// put the result back onto the stash
S = pair(apply_binary(operator_instruction_symbol(command),
head(tail(S)), head(S)),
tail(tail(S)));
} else {
error(command, "unknown command:");
}
}
return head(S); // return the top thing on the stash ("top" on stash)
}
// apply binary operator
// like symbolic evaluator
function apply_binary(operator, op1, op2) {
return operator === "+"
? op1 + op2
: operator === "-"
? op1 - op2
: operator === "*"
? op1 * op2
: operator === "/"
? op1 / op2
: error(operator, "Unknown operator");
}
//
// syntax functions (SICP JS 4.1.2)
//
function is_tagged_list(component, the_tag) {
return is_pair(component) && head(component) === the_tag;
}
// literals
function is_literal(component) {
return is_tagged_list(component, "literal");
}
function literal_value(component) {
return head(tail(component));
}
function make_literal(val) {
return list("literal", val);
}
// operator combinations
function is_operator_combination(component) {
return is_unary_operator_combination(component) ||
is_binary_operator_combination(component);
}
function is_unary_operator_combination(component) {
return is_tagged_list(component, "unary_operator_combination");
}
function is_binary_operator_combination(component) {
return is_tagged_list(component, "binary_operator_combination");
}
function operator_symbol(component) {
return list_ref(component, 1);
}
function first_operand(component) {
return list_ref(component, 2);
}
function second_operand(component) {
return list_ref(component, 3);
}
//
// CSE machine instructions
//
// operators instructions
function is_binary_operator_instruction(component) {
return is_tagged_list(component, "binop");
}
function is_unary_operator_instruction(component) {
return is_tagged_list(component, "unop");
}
function operator_instruction_symbol(component) {
return list_ref(component, 1);
}
function make_binary_operator_instruction(symbol) {
return list("binop", symbol);
}
function make_unary_operator_instruction(symbol) {
return list("unop", symbol);
}
//
// testing
//
function display_control(C) {
display("", "*** control *** ");
for_each(command =>
is_literal(command) ||
is_binary_operator_instruction(command)
? display_list(command)
: display_list(list(head(command),
head(tail(command)),
"...")),
C);
display("", " ");
}
function display_stash(S) {
display("", "*** stash *** ");
for_each(value => {
display_list(value);
},
S);
display("", " ");
}
function parse_and_evaluate(string) {
return evaluate(parse(string));
}
parse_and_evaluate("1.4 + 2.3 / 70.4;");