cb8e18600d40cbfd97a6eb768e2ebb982478a3d4
[ou-summer-of-code-2017.git] / 07-interpreter / machine-code.ipynb
1 {
2 "cells": [
3 {
4 "cell_type": "code",
5 "execution_count": 111,
6 "metadata": {},
7 "outputs": [],
8 "source": [
9 "def new_machine():\n",
10 " return {'pc': 0, \n",
11 " 'a': 0,\n",
12 " 'b': 0, \n",
13 " 'c': 0,\n",
14 " 'instructions': []}"
15 ]
16 },
17 {
18 "cell_type": "code",
19 "execution_count": 193,
20 "metadata": {
21 "collapsed": true
22 },
23 "outputs": [],
24 "source": [
25 "def show_machine(machine):\n",
26 " return ', '.join('{}: {}'.format(sk, machine[int(sk) if sk.isnumeric() else sk]) \n",
27 " for sk in sorted(str(k) for k in machine)\n",
28 " if sk != 'instructions')"
29 ]
30 },
31 {
32 "cell_type": "code",
33 "execution_count": 112,
34 "metadata": {
35 "collapsed": true
36 },
37 "outputs": [],
38 "source": [
39 "def inc(reg, machine):\n",
40 " machine[reg] += 1\n",
41 " machine['pc'] += 1"
42 ]
43 },
44 {
45 "cell_type": "code",
46 "execution_count": 113,
47 "metadata": {
48 "collapsed": true
49 },
50 "outputs": [],
51 "source": [
52 "def dec(reg, machine):\n",
53 " machine[reg] -= 1\n",
54 " machine['pc'] += 1"
55 ]
56 },
57 {
58 "cell_type": "code",
59 "execution_count": 114,
60 "metadata": {
61 "collapsed": true
62 },
63 "outputs": [],
64 "source": [
65 "def jmp(addr, machine):\n",
66 " machine['pc'] += addr"
67 ]
68 },
69 {
70 "cell_type": "code",
71 "execution_count": 115,
72 "metadata": {
73 "collapsed": true
74 },
75 "outputs": [],
76 "source": [
77 "def jpz(reg, addr, machine):\n",
78 " if machine[reg] == 0:\n",
79 " machine['pc'] += addr\n",
80 " else:\n",
81 " machine['pc'] += 1"
82 ]
83 },
84 {
85 "cell_type": "code",
86 "execution_count": 116,
87 "metadata": {
88 "collapsed": true
89 },
90 "outputs": [],
91 "source": [
92 "def set_literal(reg, literal, machine):\n",
93 " machine[reg] = literal\n",
94 " machine['pc'] += 1"
95 ]
96 },
97 {
98 "cell_type": "code",
99 "execution_count": 117,
100 "metadata": {
101 "collapsed": true
102 },
103 "outputs": [],
104 "source": [
105 "def cpy(from_reg, to_reg, machine):\n",
106 " machine[to_reg] = machine[from_reg]\n",
107 " machine['pc'] += 1"
108 ]
109 },
110 {
111 "cell_type": "code",
112 "execution_count": 129,
113 "metadata": {
114 "collapsed": true
115 },
116 "outputs": [],
117 "source": [
118 "def sto(reg, addr, machine):\n",
119 " machine[addr] = machine[reg]\n",
120 " machine['pc'] += 1"
121 ]
122 },
123 {
124 "cell_type": "code",
125 "execution_count": 130,
126 "metadata": {
127 "collapsed": true
128 },
129 "outputs": [],
130 "source": [
131 "def ld(reg, addr, machine):\n",
132 " if addr in machine:\n",
133 " machine[reg] = machine[addr]\n",
134 " else:\n",
135 " machine[reg] = 0\n",
136 " machine['pc'] += 1"
137 ]
138 },
139 {
140 "cell_type": "code",
141 "execution_count": 131,
142 "metadata": {},
143 "outputs": [],
144 "source": [
145 "instruction_table = {'inc': inc, 'dec': dec, 'jmp': jmp,\n",
146 " 'jpz': jpz, 'set': set_literal, 'cpy': cpy,\n",
147 " 'sto': sto, 'ld': ld}\n",
148 "numeric_args_table = {'jmp': [0], 'jpz': [1], 'set': [1], 'sto': [1], 'ld': [1]}"
149 ]
150 },
151 {
152 "cell_type": "code",
153 "execution_count": 121,
154 "metadata": {
155 "collapsed": true
156 },
157 "outputs": [],
158 "source": [
159 "def parse(instruction):\n",
160 " words = instruction.split()\n",
161 " instr = words[0]\n",
162 " args = words[1:]\n",
163 " if instr in numeric_args_table:\n",
164 " for p in numeric_args_table[instr]:\n",
165 " args[p] = int(args[p])\n",
166 " return instruction_table[instr], args"
167 ]
168 },
169 {
170 "cell_type": "code",
171 "execution_count": 122,
172 "metadata": {},
173 "outputs": [
174 {
175 "data": {
176 "text/plain": [
177 "{'a': 2, 'b': 1, 'c': 0, 'instructions': [], 'pc': 3}"
178 ]
179 },
180 "execution_count": 122,
181 "metadata": {},
182 "output_type": "execute_result"
183 }
184 ],
185 "source": [
186 "m = new_machine()\n",
187 "inc('a', m)\n",
188 "cargs = ['a', 'b']\n",
189 "cpy(*cargs, m)\n",
190 "inc('a', m)\n",
191 "m"
192 ]
193 },
194 {
195 "cell_type": "code",
196 "execution_count": 123,
197 "metadata": {
198 "collapsed": true
199 },
200 "outputs": [],
201 "source": [
202 "def program_from_instructions(prog, machine):\n",
203 " machine['instructions'] = [parse(instr) for instr in prog]"
204 ]
205 },
206 {
207 "cell_type": "code",
208 "execution_count": 124,
209 "metadata": {
210 "collapsed": true
211 },
212 "outputs": [],
213 "source": [
214 "def program_from_listing(listing, machine):\n",
215 " program_from_instructions([i for i in listing.split('\\n') if i], machine)"
216 ]
217 },
218 {
219 "cell_type": "code",
220 "execution_count": 156,
221 "metadata": {
222 "collapsed": true
223 },
224 "outputs": [],
225 "source": [
226 "def run(machine, initial_state=None, trace=False):\n",
227 " if initial_state:\n",
228 " machine.update(initial_state)\n",
229 " while machine['pc'] < len(machine['instructions']):\n",
230 " if trace:\n",
231 " print(show_machine(machine))\n",
232 " cmd, args = machine['instructions'][machine['pc']]\n",
233 " cmd(*args, machine)"
234 ]
235 },
236 {
237 "cell_type": "code",
238 "execution_count": 146,
239 "metadata": {
240 "collapsed": true
241 },
242 "outputs": [],
243 "source": [
244 "def execute(listing, initial_state=None, trace=False):\n",
245 " m = new_machine()\n",
246 " program_from_listing(listing, m)\n",
247 " run(m, initial_state=initial_state, trace=trace)\n",
248 " return m"
249 ]
250 },
251 {
252 "cell_type": "code",
253 "execution_count": 127,
254 "metadata": {},
255 "outputs": [
256 {
257 "data": {
258 "text/plain": [
259 "{'a': 3,\n",
260 " 'b': 2,\n",
261 " 'c': 0,\n",
262 " 'instructions': [(<function __main__.inc>, ['a']),\n",
263 " (<function __main__.inc>, ['a']),\n",
264 " (<function __main__.cpy>, ['a', 'b']),\n",
265 " (<function __main__.inc>, ['a'])],\n",
266 " 'pc': 4}"
267 ]
268 },
269 "execution_count": 127,
270 "metadata": {},
271 "output_type": "execute_result"
272 }
273 ],
274 "source": [
275 "program = \"\"\"\n",
276 "inc a\n",
277 "inc a\n",
278 "cpy a b\n",
279 "inc a\n",
280 "\"\"\"\n",
281 "execute(program)"
282 ]
283 },
284 {
285 "cell_type": "code",
286 "execution_count": 143,
287 "metadata": {},
288 "outputs": [
289 {
290 "data": {
291 "text/plain": [
292 "{'c': 20,\n",
293 " 'instructions': [(<function __main__.set_literal>, ['a', 10]),\n",
294 " (<function __main__.dec>, ['a']),\n",
295 " (<function __main__.inc>, ['b']),\n",
296 " (<function __main__.sto>, ['b', 1]),\n",
297 " (<function __main__.jpz>, ['a', 2]),\n",
298 " (<function __main__.jmp>, [-4])],\n",
299 " 1: 10,\n",
300 " 'b': 10,\n",
301 " 'pc': 6,\n",
302 " 'a': 0}"
303 ]
304 },
305 "execution_count": 143,
306 "metadata": {},
307 "output_type": "execute_result"
308 }
309 ],
310 "source": [
311 "program = \"\"\"\n",
312 "set a 10\n",
313 "dec a\n",
314 "inc b\n",
315 "sto b 1\n",
316 "jpz a 2\n",
317 "jmp -4\n",
318 "\"\"\"\n",
319 "# m = new_machine()\n",
320 "# program_from_listing(program, m)\n",
321 "# run(m)\n",
322 "execute(program, initial_state={'c': 20})"
323 ]
324 },
325 {
326 "cell_type": "code",
327 "execution_count": 159,
328 "metadata": {},
329 "outputs": [
330 {
331 "data": {
332 "text/plain": [
333 "{'a': 0,\n",
334 " 'b': 1,\n",
335 " 'c': 5,\n",
336 " 'instructions': [(<function __main__.cpy>, ['c', 'a']),\n",
337 " (<function __main__.set_literal>, ['b', 0]),\n",
338 " (<function __main__.dec>, ['a']),\n",
339 " (<function __main__.jpz>, ['b', 3]),\n",
340 " (<function __main__.dec>, ['b']),\n",
341 " (<function __main__.jmp>, [2]),\n",
342 " (<function __main__.inc>, ['b']),\n",
343 " (<function __main__.jpz>, ['a', 3]),\n",
344 " (<function __main__.jmp>, [-6])],\n",
345 " 'pc': 10}"
346 ]
347 },
348 "execution_count": 159,
349 "metadata": {},
350 "output_type": "execute_result"
351 }
352 ],
353 "source": [
354 "program = \"\"\"\n",
355 "cpy c a\n",
356 "set b 0\n",
357 "dec a\n",
358 "jpz b 3\n",
359 "dec b\n",
360 "jmp 2\n",
361 "inc b\n",
362 "jpz a 3\n",
363 "jmp -6\n",
364 "\"\"\"\n",
365 "# m = new_machine()\n",
366 "# program_from_listing(program, m)\n",
367 "# run(m)\n",
368 "execute(program, initial_state={'c': 5})"
369 ]
370 },
371 {
372 "cell_type": "code",
373 "execution_count": 196,
374 "metadata": {},
375 "outputs": [
376 {
377 "data": {
378 "text/plain": [
379 "'10: 10, a: 0, b: 0, c: 5, pc: 11'"
380 ]
381 },
382 "execution_count": 196,
383 "metadata": {},
384 "output_type": "execute_result"
385 }
386 ],
387 "source": [
388 "program = \"\"\"\n",
389 "sto a 10\n",
390 "set c 0\n",
391 "set b 0\n",
392 "dec a\n",
393 "jpz b 4\n",
394 "dec b\n",
395 "inc c\n",
396 "jmp 2\n",
397 "inc b\n",
398 "jpz a 2\n",
399 "jmp -7\n",
400 "\"\"\"\n",
401 "# m = new_machine()\n",
402 "# program_from_listing(program, m)\n",
403 "# run(m)\n",
404 "show_machine(execute(program, initial_state={'a': 10}))"
405 ]
406 },
407 {
408 "cell_type": "code",
409 "execution_count": null,
410 "metadata": {
411 "collapsed": true
412 },
413 "outputs": [],
414 "source": []
415 }
416 ],
417 "metadata": {
418 "kernelspec": {
419 "display_name": "Python 3",
420 "language": "python",
421 "name": "python3"
422 },
423 "language_info": {
424 "codemirror_mode": {
425 "name": "ipython",
426 "version": 3
427 },
428 "file_extension": ".py",
429 "mimetype": "text/x-python",
430 "name": "python",
431 "nbconvert_exporter": "python",
432 "pygments_lexer": "ipython3",
433 "version": "3.5.2+"
434 }
435 },
436 "nbformat": 4,
437 "nbformat_minor": 2
438 }