From: Neil Smith Date: Sat, 10 Jun 2017 19:07:25 +0000 (+0100) Subject: Started on interpreter X-Git-Url: https://git.njae.me.uk/?a=commitdiff_plain;h=009976af40a98c5cb0151fca6525c75f12222373;hp=fda89d02980df6c79d05dfdc8db9bea3d7856254;p=ou-summer-of-code-2017.git Started on interpreter --- diff --git a/07-interpreter/machine-code.ipynb b/07-interpreter/machine-code.ipynb new file mode 100644 index 0000000..cb8e186 --- /dev/null +++ b/07-interpreter/machine-code.ipynb @@ -0,0 +1,438 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 111, + "metadata": {}, + "outputs": [], + "source": [ + "def new_machine():\n", + " return {'pc': 0, \n", + " 'a': 0,\n", + " 'b': 0, \n", + " 'c': 0,\n", + " 'instructions': []}" + ] + }, + { + "cell_type": "code", + "execution_count": 193, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def show_machine(machine):\n", + " return ', '.join('{}: {}'.format(sk, machine[int(sk) if sk.isnumeric() else sk]) \n", + " for sk in sorted(str(k) for k in machine)\n", + " if sk != 'instructions')" + ] + }, + { + "cell_type": "code", + "execution_count": 112, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def inc(reg, machine):\n", + " machine[reg] += 1\n", + " machine['pc'] += 1" + ] + }, + { + "cell_type": "code", + "execution_count": 113, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def dec(reg, machine):\n", + " machine[reg] -= 1\n", + " machine['pc'] += 1" + ] + }, + { + "cell_type": "code", + "execution_count": 114, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def jmp(addr, machine):\n", + " machine['pc'] += addr" + ] + }, + { + "cell_type": "code", + "execution_count": 115, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def jpz(reg, addr, machine):\n", + " if machine[reg] == 0:\n", + " machine['pc'] += addr\n", + " else:\n", + " machine['pc'] += 1" + ] + }, + { + "cell_type": "code", + "execution_count": 116, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def set_literal(reg, literal, machine):\n", + " machine[reg] = literal\n", + " machine['pc'] += 1" + ] + }, + { + "cell_type": "code", + "execution_count": 117, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def cpy(from_reg, to_reg, machine):\n", + " machine[to_reg] = machine[from_reg]\n", + " machine['pc'] += 1" + ] + }, + { + "cell_type": "code", + "execution_count": 129, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def sto(reg, addr, machine):\n", + " machine[addr] = machine[reg]\n", + " machine['pc'] += 1" + ] + }, + { + "cell_type": "code", + "execution_count": 130, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def ld(reg, addr, machine):\n", + " if addr in machine:\n", + " machine[reg] = machine[addr]\n", + " else:\n", + " machine[reg] = 0\n", + " machine['pc'] += 1" + ] + }, + { + "cell_type": "code", + "execution_count": 131, + "metadata": {}, + "outputs": [], + "source": [ + "instruction_table = {'inc': inc, 'dec': dec, 'jmp': jmp,\n", + " 'jpz': jpz, 'set': set_literal, 'cpy': cpy,\n", + " 'sto': sto, 'ld': ld}\n", + "numeric_args_table = {'jmp': [0], 'jpz': [1], 'set': [1], 'sto': [1], 'ld': [1]}" + ] + }, + { + "cell_type": "code", + "execution_count": 121, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def parse(instruction):\n", + " words = instruction.split()\n", + " instr = words[0]\n", + " args = words[1:]\n", + " if instr in numeric_args_table:\n", + " for p in numeric_args_table[instr]:\n", + " args[p] = int(args[p])\n", + " return instruction_table[instr], args" + ] + }, + { + "cell_type": "code", + "execution_count": 122, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'a': 2, 'b': 1, 'c': 0, 'instructions': [], 'pc': 3}" + ] + }, + "execution_count": 122, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m = new_machine()\n", + "inc('a', m)\n", + "cargs = ['a', 'b']\n", + "cpy(*cargs, m)\n", + "inc('a', m)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": 123, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def program_from_instructions(prog, machine):\n", + " machine['instructions'] = [parse(instr) for instr in prog]" + ] + }, + { + "cell_type": "code", + "execution_count": 124, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def program_from_listing(listing, machine):\n", + " program_from_instructions([i for i in listing.split('\\n') if i], machine)" + ] + }, + { + "cell_type": "code", + "execution_count": 156, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def run(machine, initial_state=None, trace=False):\n", + " if initial_state:\n", + " machine.update(initial_state)\n", + " while machine['pc'] < len(machine['instructions']):\n", + " if trace:\n", + " print(show_machine(machine))\n", + " cmd, args = machine['instructions'][machine['pc']]\n", + " cmd(*args, machine)" + ] + }, + { + "cell_type": "code", + "execution_count": 146, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def execute(listing, initial_state=None, trace=False):\n", + " m = new_machine()\n", + " program_from_listing(listing, m)\n", + " run(m, initial_state=initial_state, trace=trace)\n", + " return m" + ] + }, + { + "cell_type": "code", + "execution_count": 127, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'a': 3,\n", + " 'b': 2,\n", + " 'c': 0,\n", + " 'instructions': [(, ['a']),\n", + " (, ['a']),\n", + " (, ['a', 'b']),\n", + " (, ['a'])],\n", + " 'pc': 4}" + ] + }, + "execution_count": 127, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "program = \"\"\"\n", + "inc a\n", + "inc a\n", + "cpy a b\n", + "inc a\n", + "\"\"\"\n", + "execute(program)" + ] + }, + { + "cell_type": "code", + "execution_count": 143, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'c': 20,\n", + " 'instructions': [(, ['a', 10]),\n", + " (, ['a']),\n", + " (, ['b']),\n", + " (, ['b', 1]),\n", + " (, ['a', 2]),\n", + " (, [-4])],\n", + " 1: 10,\n", + " 'b': 10,\n", + " 'pc': 6,\n", + " 'a': 0}" + ] + }, + "execution_count": 143, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "program = \"\"\"\n", + "set a 10\n", + "dec a\n", + "inc b\n", + "sto b 1\n", + "jpz a 2\n", + "jmp -4\n", + "\"\"\"\n", + "# m = new_machine()\n", + "# program_from_listing(program, m)\n", + "# run(m)\n", + "execute(program, initial_state={'c': 20})" + ] + }, + { + "cell_type": "code", + "execution_count": 159, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'a': 0,\n", + " 'b': 1,\n", + " 'c': 5,\n", + " 'instructions': [(, ['c', 'a']),\n", + " (, ['b', 0]),\n", + " (, ['a']),\n", + " (, ['b', 3]),\n", + " (, ['b']),\n", + " (, [2]),\n", + " (, ['b']),\n", + " (, ['a', 3]),\n", + " (, [-6])],\n", + " 'pc': 10}" + ] + }, + "execution_count": 159, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "program = \"\"\"\n", + "cpy c a\n", + "set b 0\n", + "dec a\n", + "jpz b 3\n", + "dec b\n", + "jmp 2\n", + "inc b\n", + "jpz a 3\n", + "jmp -6\n", + "\"\"\"\n", + "# m = new_machine()\n", + "# program_from_listing(program, m)\n", + "# run(m)\n", + "execute(program, initial_state={'c': 5})" + ] + }, + { + "cell_type": "code", + "execution_count": 196, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'10: 10, a: 0, b: 0, c: 5, pc: 11'" + ] + }, + "execution_count": 196, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "program = \"\"\"\n", + "sto a 10\n", + "set c 0\n", + "set b 0\n", + "dec a\n", + "jpz b 4\n", + "dec b\n", + "inc c\n", + "jmp 2\n", + "inc b\n", + "jpz a 2\n", + "jmp -7\n", + "\"\"\"\n", + "# m = new_machine()\n", + "# program_from_listing(program, m)\n", + "# run(m)\n", + "show_machine(execute(program, initial_state={'a': 10}))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2+" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}