Skip to content

Commit 5b6f137

Browse files
committed
Forgot to check this in last time
1 parent a94b8cc commit 5b6f137

File tree

1 file changed

+306
-0
lines changed

1 file changed

+306
-0
lines changed

controlAndBooleanExpressions.js

Lines changed: 306 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,306 @@
1+
'use strict';
2+
3+
const cradle = require('./cradle'),
4+
expressionParsing = require('./expression');
5+
6+
7+
const q = require('q');
8+
9+
const emitLn = cradle.emitLn,
10+
getName = cradle.getName,
11+
init = cradle.init,
12+
look = cradle.look,
13+
expected = cradle.expected,
14+
match = cradle.match,
15+
abort = cradle.abort,
16+
expression = expressionParsing.expression,
17+
boolExpression = expressionParsing.boolExpression;
18+
19+
let labelCount = 0;
20+
21+
function newLabel() {
22+
let result = 'L' + labelCount;
23+
labelCount++;
24+
return result;
25+
}
26+
27+
function postLabel(l) {
28+
console.log(l + ':');
29+
}
30+
31+
function other() {
32+
return getName()
33+
.then((name) => {
34+
emitLn(name);
35+
});
36+
}
37+
38+
function doFor() {
39+
let label1, label2, counterName;
40+
41+
return match('f')
42+
.then(() => {
43+
label1 = newLabel();
44+
label2 = newLabel();
45+
return getName();
46+
})
47+
.then((name) => {
48+
counterName = name;
49+
return match('=');
50+
})
51+
.then(() => {
52+
return expression();
53+
})
54+
.then(() => {
55+
emitLn('SUBQ #1,D0');
56+
emitLn('LEA ' + counterName + '(PC),A0');
57+
emitLn('MOVE D0,(A0)');
58+
return expression();
59+
})
60+
.then(() => {
61+
emitLn('MOVE D0,-(SP)');
62+
postLabel(label1);
63+
emitLn('LEA ' + counterName + '(PC),A0');
64+
emitLn('MOVE (A0),D0');
65+
emitLn('ADDQ #1,D0');
66+
emitLn('MOVE D0,(A0)');
67+
emitLn('CMP (SP),D0');
68+
emitLn('BGT ' + label2);
69+
return block(label2);
70+
})
71+
.then(() => {
72+
return match('e');
73+
})
74+
.then(() => {
75+
emitLn('BRA ' + label1);
76+
postLabel(label2);
77+
emitLn('ADDQ #2,SP');
78+
})
79+
80+
81+
}
82+
83+
function block(exitLabel) {
84+
function continueBlock() {
85+
return fin()
86+
.then(() => {
87+
return block(exitLabel);
88+
})
89+
};
90+
return q()
91+
.then(() => {
92+
const c = look();
93+
if (c !== 'e' && c !== 'l' && c !== 'u') {
94+
return fin()
95+
.then(() => {
96+
switch(c) {
97+
case 'i':
98+
return doIf(exitLabel)
99+
.then(continueBlock);
100+
case 'w':
101+
return doWhile()
102+
.then(continueBlock);
103+
case 'p':
104+
return doLoop()
105+
.then(continueBlock);
106+
case 'r':
107+
return doRepeat()
108+
.then(continueBlock);
109+
case 'f':
110+
return doFor()
111+
.then(continueBlock);
112+
case 'd':
113+
return doDo()
114+
.then(continueBlock);
115+
case 'b':
116+
return doBreak(exitLabel)
117+
.then(continueBlock);
118+
default:
119+
return other()
120+
.then(continueBlock);
121+
}
122+
});
123+
}
124+
});
125+
}
126+
127+
function doIf(loopExitLabel) {
128+
let label1, label2;
129+
130+
return match('i')
131+
.then(() => {
132+
label1 = newLabel();
133+
label2 = label1;
134+
return boolExpression();
135+
})
136+
.then(() => {
137+
emitLn('BEQ ' + label1);
138+
return block();
139+
})
140+
.then(() => {
141+
let nextChar = look();
142+
if (nextChar === 'l') {
143+
return match('l')
144+
.then(() => {
145+
label2 = newLabel();
146+
emitLn('BRA ' + label2);
147+
postLabel(label1);
148+
return block(loopExitLabel);
149+
});
150+
}
151+
}).then(() => {
152+
return match('e');
153+
})
154+
.then(() => {
155+
postLabel(label2);
156+
});
157+
}
158+
159+
function doBreak(label) {
160+
return match('b')
161+
.then(() => {
162+
if (label !== '') {
163+
emitLn('BRA ' + label);
164+
} else {
165+
abort('No loop to break from');
166+
}
167+
});
168+
}
169+
170+
function doWhile() {
171+
let label1, label2;
172+
173+
return match('w')
174+
.then(() => {
175+
label1 = newLabel();
176+
label2 = newLabel();
177+
postLabel(label1);
178+
return boolExpression();
179+
})
180+
.then(() => {
181+
emitLn('BEQ ' + label2);
182+
return block(label2);
183+
})
184+
.then(() => {
185+
return match('e');
186+
})
187+
.then(() => {
188+
emitLn('BRA ' + label1);
189+
postLabel(label2);
190+
});
191+
}
192+
193+
function doLoop() {
194+
let label1, label2;
195+
return match('p')
196+
.then(() => {
197+
label1 = newLabel();
198+
label2 = newLabel();
199+
postLabel(label1);
200+
return block(label2);
201+
})
202+
.then(() => {
203+
return match('e');
204+
})
205+
.then(() => {
206+
emitLn('BRA ' + label1);
207+
postLabel(label2);
208+
});
209+
}
210+
211+
function doRepeat() {
212+
let label1, label2;
213+
return match('r')
214+
.then(() => {
215+
label1 = newLabel();
216+
label2 = newLabel();
217+
postLabel(label1);
218+
return block(label2);
219+
})
220+
.then(() => {
221+
return match('u');
222+
})
223+
.then(() => {
224+
return boolExpression();
225+
})
226+
.then(() => {
227+
emitLn('BEQ ' + label1);
228+
postLabel(label2);
229+
});
230+
}
231+
232+
function doDo() {
233+
let label1, label2;
234+
return match('d')
235+
.then(() => {
236+
label1 = newLabel();
237+
label2 = newLabel();
238+
return expression();
239+
})
240+
.then(() => {
241+
emitLn('SUBQ #1,D0');
242+
postLabel(label1);
243+
emitLn('MOVE D0,-(SP)');
244+
return block(label2);
245+
})
246+
.then(() => {
247+
emitLn('MOVE (SP)+,D0');
248+
emitLn('DBRA D0,' + label);
249+
emitLn('SUBQ #2,SP');
250+
postLabel(label2);
251+
emitLn('ADDQ #2,SP');
252+
});
253+
}
254+
255+
function doProgram() {
256+
return block('')
257+
.then(() => {
258+
const c = look();
259+
if (c !== 'e') return expected('End');
260+
emitLn('END');
261+
});
262+
}
263+
264+
function fin() {
265+
return q()
266+
.then(() => {
267+
let nextChar = look();
268+
if (nextChar === '\r')
269+
return getChar();
270+
})
271+
.then(() => {
272+
let nextChar = look();
273+
if (nextChar === '\n')
274+
return getChar();
275+
});
276+
}
277+
278+
function assignment() {
279+
// Somewhere we need to generate DS directives
280+
// for this to work with the EASy68K assembler.
281+
// Leaving this as an exercise for now to collect variables
282+
// and collect generated code in a buffer so that
283+
// the appropriate header with symbol definitions
284+
// is put before the code in the results emitted
285+
// on stdout
286+
return getName()
287+
.then((name) => {
288+
return match('=')
289+
.then(() => {
290+
return boolExpression()
291+
.then(() => {
292+
emitLn('LEA ' + name + '(PC),A0');
293+
emitLn('MOVE D0,(A0)');
294+
});
295+
});
296+
});
297+
}
298+
299+
300+
init()
301+
.then(() => {
302+
return doProgram();
303+
})
304+
.catch((err) => {
305+
console.log(err.stack);
306+
});

0 commit comments

Comments
 (0)