Started on interpreter
authorNeil Smith <neil.git@njae.me.uk>
Sat, 10 Jun 2017 19:07:25 +0000 (20:07 +0100)
committerNeil Smith <neil.git@njae.me.uk>
Sat, 10 Jun 2017 19:07:25 +0000 (20:07 +0100)
07-interpreter/machine-code.ipynb [new file with mode: 0644]

diff --git a/07-interpreter/machine-code.ipynb b/07-interpreter/machine-code.ipynb
new file mode 100644 (file)
index 0000000..cb8e186
--- /dev/null
@@ -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': [(<function __main__.inc>, ['a']),\n",
+       "  (<function __main__.inc>, ['a']),\n",
+       "  (<function __main__.cpy>, ['a', 'b']),\n",
+       "  (<function __main__.inc>, ['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': [(<function __main__.set_literal>, ['a', 10]),\n",
+       "  (<function __main__.dec>, ['a']),\n",
+       "  (<function __main__.inc>, ['b']),\n",
+       "  (<function __main__.sto>, ['b', 1]),\n",
+       "  (<function __main__.jpz>, ['a', 2]),\n",
+       "  (<function __main__.jmp>, [-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': [(<function __main__.cpy>, ['c', 'a']),\n",
+       "  (<function __main__.set_literal>, ['b', 0]),\n",
+       "  (<function __main__.dec>, ['a']),\n",
+       "  (<function __main__.jpz>, ['b', 3]),\n",
+       "  (<function __main__.dec>, ['b']),\n",
+       "  (<function __main__.jmp>, [2]),\n",
+       "  (<function __main__.inc>, ['b']),\n",
+       "  (<function __main__.jpz>, ['a', 3]),\n",
+       "  (<function __main__.jmp>, [-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
+}